增加app模板和代码生成
@@ -8,6 +8,9 @@
|
||||
},
|
||||
{
|
||||
"path": "docs"
|
||||
},
|
||||
{
|
||||
"path": "x_admin_app"
|
||||
}
|
||||
]
|
||||
}
|
@@ -42,12 +42,14 @@
|
||||
|
||||
<uv-back-top :scroll-top="scrollTop"></uv-back-top>
|
||||
|
||||
<uv-empty v-if="pager.loading =='nomore'&&pager.lists.length == 0" marginTop="150" mode="data"></uv-empty>
|
||||
<uv-loading-page
|
||||
:loading="pager.pageNo == 1 && pager.loading == 'loading'"
|
||||
loading-text="加载中..."
|
||||
font-size="24rpx"
|
||||
></uv-loading-page>
|
||||
<uv-load-more
|
||||
v-if="pager.lists.length > 0"
|
||||
:status="pager.loading"
|
||||
:loading-text="pager.loadingText"
|
||||
:loadmore-text="pager.loadmoreText"
|
||||
|
@@ -0,0 +1,34 @@
|
||||
// 请将pages里的数据手动合并到根目录下pages.json中
|
||||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/{{{ .ModuleName }}}/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "{{{.FunctionName}}}",
|
||||
"enablePullDownRefresh": true,
|
||||
"onReachBottomDistance": 100,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/{{{ .ModuleName }}}/details",
|
||||
"style": {
|
||||
"navigationBarTitleText": "{{{.FunctionName}}}详情",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/{{{ .ModuleName }}}/edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑{{{.FunctionName}}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/{{{ .ModuleName }}}/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索{{{.FunctionName}}}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@@ -8,7 +8,9 @@
|
||||
<x-date-range v-model:startTime="form.{{{ (toCamelCase .GoField) }}}Start"
|
||||
v-model:endTime="form.{{{ (toCamelCase .GoField) }}}End"></x-date-range>
|
||||
{{{- else if or (eq .HtmlType "select") (eq .HtmlType "radio") }}}
|
||||
{{{- if ne .DictType "" }}}
|
||||
<x-picker v-model="form.{{{ (toCamelCase .GoField) }}}" valueKey="value" labelKey="name" :columns="dictData.{{{ .DictType }}}"></x-picker>
|
||||
{{{- end }}}
|
||||
{{{- else if eq .HtmlType "input" }}}
|
||||
<uv-input v-model="form.{{{ (toCamelCase .GoField) }}}"> </uv-input>
|
||||
{{{- end }}}
|
||||
@@ -68,7 +70,7 @@ const { dictData } = useDictData([{{{- range .DictFields }}}'{{{ . }}}'{{{- if n
|
||||
return toast("请输入查询条件");
|
||||
}
|
||||
|
||||
toPath("/pages/equipment/equipment", search);
|
||||
toPath("/pages/{{{ .ModuleName }}}/index", search);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -170,6 +170,7 @@ func (tu templateUtil) GetTemplatePaths(genTpl string) []string {
|
||||
"uniapp/index.vue.tpl",
|
||||
"uniapp/details.vue.tpl",
|
||||
"uniapp/search.vue.tpl",
|
||||
"uniapp/pages.json.tpl",
|
||||
}
|
||||
if genTpl == GenConstants.TplCrud {
|
||||
tplPaths = append(tplPaths, "vue/index.vue.tpl")
|
||||
@@ -223,11 +224,12 @@ func (tu templateUtil) GetFilePaths(tplCodeMap map[string]string, ModuleName str
|
||||
"vue/index.vue.tpl": strings.Join([]string{"admin/src/views/", ModuleName, "/index.vue"}, ""), // "admin/src/views/%s/index.vue",
|
||||
"vue/index-tree.vue.tpl": strings.Join([]string{"admin/src/views/", ModuleName, "/index-tree.vue"}, ""), // "admin/src/views/%s/index-tree.vue",
|
||||
|
||||
"uniapp/api.ts.tpl": strings.Join([]string{"uniapp/api/", ModuleName, ".ts"}, ""),
|
||||
"uniapp/edit.vue.tpl": strings.Join([]string{"uniapp/pages/", ModuleName, "/edit.vue"}, ""),
|
||||
"uniapp/index.vue.tpl": strings.Join([]string{"uniapp/pages/", ModuleName, "/index.vue"}, ""),
|
||||
"uniapp/search.vue.tpl": strings.Join([]string{"uniapp/pages/", ModuleName, "/search.vue"}, ""),
|
||||
"uniapp/details.vue.tpl": strings.Join([]string{"uniapp/pages/", ModuleName, "/details.vue"}, ""),
|
||||
"uniapp/api.ts.tpl": strings.Join([]string{"x_admin_app/api/", ModuleName, ".ts"}, ""),
|
||||
"uniapp/edit.vue.tpl": strings.Join([]string{"x_admin_app/pages/", ModuleName, "/edit.vue"}, ""),
|
||||
"uniapp/index.vue.tpl": strings.Join([]string{"x_admin_app/pages/", ModuleName, "/index.vue"}, ""),
|
||||
"uniapp/search.vue.tpl": strings.Join([]string{"x_admin_app/pages/", ModuleName, "/search.vue"}, ""),
|
||||
"uniapp/details.vue.tpl": strings.Join([]string{"x_admin_app/pages/", ModuleName, "/details.vue"}, ""),
|
||||
"uniapp/pages.json.tpl": strings.Join([]string{"x_admin_app/pages/", ModuleName, "/pages.json"}, ""),
|
||||
}
|
||||
filePath := make(map[string]string)
|
||||
for tplPath, tplCode := range tplCodeMap {
|
||||
|
@@ -7,6 +7,10 @@ type MonitorProjectListReq struct {
|
||||
ProjectKey string `form:"projectKey"` // 项目uuid
|
||||
ProjectName string `form:"projectName"` // 项目名称
|
||||
ProjectType string `form:"projectType"` // 项目类型go java web node php 等
|
||||
CreateTimeStart string `form:"createTimeStart"` // 开始创建时间
|
||||
CreateTimeEnd string `form:"createTimeEnd"` // 结束创建时间
|
||||
UpdateTimeStart string `form:"updateTimeStart"` // 开始更新时间
|
||||
UpdateTimeEnd string `form:"updateTimeEnd"` // 结束更新时间
|
||||
}
|
||||
|
||||
//MonitorProjectDetailReq 错误项目详情参数
|
||||
|
@@ -49,6 +49,18 @@ func (service monitorProjectService) List(page request.PageReq, listReq MonitorP
|
||||
if listReq.ProjectType != "" {
|
||||
dbModel = dbModel.Where("project_type = ?", listReq.ProjectType)
|
||||
}
|
||||
if listReq.CreateTimeStart != "" {
|
||||
dbModel = dbModel.Where("create_time >= ?", listReq.CreateTimeStart)
|
||||
}
|
||||
if listReq.CreateTimeEnd != "" {
|
||||
dbModel = dbModel.Where("create_time <= ?", listReq.CreateTimeEnd)
|
||||
}
|
||||
if listReq.UpdateTimeStart != "" {
|
||||
dbModel = dbModel.Where("update_time >= ?", listReq.UpdateTimeStart)
|
||||
}
|
||||
if listReq.UpdateTimeEnd != "" {
|
||||
dbModel = dbModel.Where("update_time <= ?", listReq.UpdateTimeEnd)
|
||||
}
|
||||
dbModel = dbModel.Where("is_delete = ?", 0)
|
||||
// 总数
|
||||
var count int64
|
||||
|
25
x_admin_app/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
tests/**/coverage/
|
||||
pnpm-lock.yaml
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
stats.html
|
||||
.vscode/*
|
||||
!/.vscode/settings.json
|
||||
|
||||
release
|
||||
dist-electron
|
||||
unpackage/*
|
||||
!unpackage/res
|
||||
HBuilderConfigTemp.json
|
20
x_admin_app/.hbuilderx/launch.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"playground" : "custom",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"app-plus" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"mp-weixin" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
}
|
||||
]
|
||||
}
|
11
x_admin_app/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"dcloudio",
|
||||
"fota",
|
||||
"IMEI",
|
||||
"loadmore",
|
||||
"nomore",
|
||||
"pinia",
|
||||
"realname"
|
||||
]
|
||||
}
|
62
x_admin_app/App.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<script>
|
||||
import {
|
||||
useUserStore
|
||||
} from "@/stores/user";
|
||||
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
const userStore = useUserStore();
|
||||
userStore
|
||||
.getInfo()
|
||||
.then((res) => {
|
||||
console.log("userInfo", res);
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.redirectTo({
|
||||
url: "/pages/login/login",
|
||||
});
|
||||
});
|
||||
},
|
||||
onShow: function() {},
|
||||
onHide: function() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
/* 解决app上uv-sticky浮动的问题 ,估计又修复了先注释掉*/
|
||||
/* height: auto; */
|
||||
}
|
||||
button:after {
|
||||
border: 0 !important;
|
||||
}
|
||||
/*每个页面公共css */
|
||||
.h100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.flex_1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.center {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.search {
|
||||
padding: 5rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
52
x_admin_app/HBuilderConfig.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
//项目名字或项目绝对路径
|
||||
"project": "x_admin_app",
|
||||
//打包平台 默认值android 值有"android","ios" 如果要打多个逗号隔开打包平台
|
||||
"platform": "android",
|
||||
//是否使用自定义基座 默认值false true自定义基座 false自定义证书
|
||||
"iscustom": false,
|
||||
//打包方式是否为安心打包默认值false,true安心打包,false传统打包
|
||||
"safemode": true,
|
||||
//android打包参数
|
||||
"android": {
|
||||
//安卓包名
|
||||
"packagename": "uni.UNIFB29F21",
|
||||
//安卓打包类型 默认值0 0 使用自有证书 1 使用公共证书 2 使用老版证书
|
||||
"androidpacktype": "3",
|
||||
//安卓使用自有证书自有打包证书参数
|
||||
//安卓打包证书别名,自有证书打包填写的参数
|
||||
"certalias": "",
|
||||
//安卓打包证书文件路径,自有证书打包填写的参数
|
||||
"certfile": "",
|
||||
//安卓打包证书密码,自有证书打包填写的参数
|
||||
"certpassword": "",
|
||||
//安卓平台要打的渠道包 取值有"google","yyb","360","huawei","xiaomi","oppo","vivo",如果要打多个逗号隔开
|
||||
"channels": ""
|
||||
},
|
||||
//ios打包参数
|
||||
"ios": {
|
||||
//ios appid
|
||||
"bundle": "uni.UNIFB29F21",
|
||||
//ios打包支持的设备类型 默认值iPhone 值有"iPhone","iPad" 如果要打多个逗号隔开打包平台
|
||||
"supporteddevice": "iPhone,iPad",
|
||||
//iOS打包是否打越狱包,只有值为true时打越狱包,false打正式包
|
||||
"isprisonbreak": false,
|
||||
|
||||
//iOS使用自定义证书打包的profile文件路径
|
||||
"profile": "",
|
||||
//iOS使用自定义证书打包的p12文件路径
|
||||
"certfile": "",
|
||||
//iOS使用自定义证书打包的证书密码
|
||||
"certpassword": ""
|
||||
},
|
||||
//是否混淆 true混淆 false关闭
|
||||
"isconfusion": false,
|
||||
//开屏广告 true打开 false关闭
|
||||
"splashads": false,
|
||||
//悬浮红包广告true打开 false关闭
|
||||
"rpads": false,
|
||||
//push广告 true打开 false关闭
|
||||
"pushads": false,
|
||||
//加入换量联盟 true加入 false不加入
|
||||
"exchange": false
|
||||
}
|
3
x_admin_app/androidPrivacy.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"prompt" : "template"
|
||||
}
|
57
x_admin_app/api/monitor_project.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
|
||||
// 监控项目列表
|
||||
export function monitor_project_list(params?: Record<string, any>) {
|
||||
return request({
|
||||
url: '/monitor_project/list',
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
// 监控项目列表-所有
|
||||
export function monitor_project_list_all(params?: Record<string, any>) {
|
||||
return request({
|
||||
url: '/monitor_project/listAll',
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 监控项目详情
|
||||
export function monitor_project_detail(id: number | string) {
|
||||
return request({
|
||||
url: '/monitor_project/detail',
|
||||
method: 'GET',
|
||||
data: { id }
|
||||
})
|
||||
}
|
||||
|
||||
// 监控项目新增
|
||||
export function monitor_project_add(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/monitor_project/add',
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 监控项目编辑
|
||||
export function monitor_project_edit(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/monitor_project/edit',
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 监控项目删除
|
||||
export function monitor_project_delete(id: number | string) {
|
||||
return request({
|
||||
url: '/monitor_project/del',
|
||||
method: "POST",
|
||||
data:{
|
||||
id
|
||||
},
|
||||
});
|
||||
}
|
29
x_admin_app/api/user.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import {request} from '@/utils/request';
|
||||
|
||||
|
||||
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/system/login',
|
||||
method: 'POST',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getInfo(token) {
|
||||
return request({
|
||||
url: '/system/admin/self',
|
||||
method: 'GET',
|
||||
data: {
|
||||
token
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/system/logout',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
39
x_admin_app/components/LoadMore/LoadMore.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<uv-load-more
|
||||
:status="props.status"
|
||||
:loading-text="props.loadingText"
|
||||
:loadmore-text="props.loadmoreText"
|
||||
:nomore-text="props.nomoreText"
|
||||
@loadmore="loadmore"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onReady, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
|
||||
|
||||
import { ref, defineEmits,defineModel } from "vue";
|
||||
|
||||
var pager = defineModel();
|
||||
|
||||
const emits = defineEmits(["loadmore"]);
|
||||
const props = defineProps({
|
||||
status: {
|
||||
type: String,
|
||||
default: "loadmore",
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
default: "努力加载中",
|
||||
},
|
||||
loadmoreText: {
|
||||
type: String,
|
||||
default: "轻轻上拉",
|
||||
},
|
||||
nomoreText: {
|
||||
type: String,
|
||||
default: "实在没有了",
|
||||
},
|
||||
});
|
||||
function loadmore(e) {
|
||||
emits("loadmore", e);
|
||||
}
|
||||
</script>
|
11
x_admin_app/components/verifition/utils/ase.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
/**
|
||||
* @word 要加密的内容
|
||||
* @keyWord String 服务器随机返回的关键字
|
||||
* */
|
||||
export function aesEncrypt(word,keyWord="XwKsGlMcdPMEhR1B"){
|
||||
var key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||
var srcs = CryptoJS.enc.Utf8.parse(word);
|
||||
var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
|
||||
return encrypted.toString();
|
||||
}
|
20
x_admin_app/components/verifition/utils/request.js
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
// let baseUrl = "https://captcha.anji-plus.com/captcha-api"
|
||||
import env from "@/utils/env";
|
||||
let baseUrl =env.baseUrl+'/api/common';
|
||||
|
||||
export const myRequest = (option={})=>{
|
||||
return new Promise((reslove,reject)=>{
|
||||
uni.request({
|
||||
url: baseUrl + option.url,
|
||||
data :option.data,
|
||||
method:option.method || "GET",
|
||||
success: (result) => {
|
||||
reslove(result)
|
||||
},
|
||||
fail:(error)=>{
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
489
x_admin_app/components/verifition/verify.vue
Normal file
554
x_admin_app/components/verifition/verifyPoint/verifyPoint.vue
Normal file
671
x_admin_app/components/verifition/verifySlider/verifySlider.vue
Normal file
114
x_admin_app/components/x-card/x-card.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<view class="x-card" :style="{ marginBottom: bottom + 'px' }">
|
||||
<view class="x-card-image" v-if="icon">
|
||||
<uv-image width="100%" :src="icon" mode="widthFix"></uv-image>
|
||||
</view>
|
||||
<view class="x-card-title" v-if="title">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
<view class="x-card-content" v-if="content">
|
||||
<slot name="contentSlot">
|
||||
<text>{{ content }}</text>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="x-card-bottom" v-if="btnText">
|
||||
<slot name="btnSlot">
|
||||
<button :open-type="openType" @click="btnClick">{{ btnText }}</button>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
icon: {
|
||||
default: "",
|
||||
type: [String, Number],
|
||||
},
|
||||
title: {
|
||||
default: "",
|
||||
type: [String, Number],
|
||||
},
|
||||
content: {
|
||||
default: "",
|
||||
type: [String, Number],
|
||||
},
|
||||
btnText: {
|
||||
default: "",
|
||||
type: [String, Number],
|
||||
},
|
||||
openType: {
|
||||
default: "",
|
||||
type: String,
|
||||
},
|
||||
bottom: {
|
||||
default: "0",
|
||||
type: [String, Number],
|
||||
},
|
||||
url: {
|
||||
default: "",
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
btnClick() {
|
||||
if (this.url) {
|
||||
this.$toPath(this.url, {
|
||||
// id: item.id
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.$emit("btnClick");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.x-card {
|
||||
background-color: white;
|
||||
margin:0 10rpx;
|
||||
padding: 10px 10px;
|
||||
border-radius: 8px;
|
||||
// margin-bottom: 10px;
|
||||
|
||||
.x-card-image {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.x-card-title {
|
||||
padding-bottom: 10rpx;
|
||||
|
||||
text {
|
||||
line-height: 1;
|
||||
font-size: 32rpx;
|
||||
// color: #aaaaaa;
|
||||
}
|
||||
}
|
||||
|
||||
.x-card-content {
|
||||
padding-bottom: 10rpx;
|
||||
|
||||
text {
|
||||
line-height: 1;
|
||||
font-size: 26rpx;
|
||||
// color: #aaaaaa;
|
||||
}
|
||||
}
|
||||
|
||||
.x-card-bottom {
|
||||
padding-top: 20rpx;
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 16rpx 16rpx;
|
||||
line-height: 1;
|
||||
border: 0;
|
||||
font-size: 24rpx;
|
||||
background-color: rgba(111, 148, 205, 1);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
46
x_admin_app/components/x-date-range/x-date-range.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<uv-input
|
||||
:modelValue="title"
|
||||
:readonly="true"
|
||||
placeholder="请选择时间"
|
||||
@click="calendarsRef.open()"
|
||||
>
|
||||
</uv-input>
|
||||
<uv-calendars
|
||||
ref="calendarsRef"
|
||||
mode="range"
|
||||
:date="[props.startTime, props.endTime]"
|
||||
@confirm="Confirm"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
const emit = defineEmits(["update:startTime", "update:endTime"]);
|
||||
const props = defineProps({
|
||||
startTime: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
endTime: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
let calendarsRef = ref(null);
|
||||
function Confirm(e) {
|
||||
console.log(e);
|
||||
emit("update:startTime", e.range.before);
|
||||
emit("update:endTime", e.range.after);
|
||||
}
|
||||
|
||||
const title = computed(() => {
|
||||
if (!props.startTime || !props.endTime) {
|
||||
return "";
|
||||
}
|
||||
return props.startTime + "-" + props.endTime;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
106
x_admin_app/components/x-list/x-list.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template >
|
||||
<view class="x-list" :style="{marginBottom:bottom+'px'}">
|
||||
|
||||
<view class="x-list-left" v-if="icon">
|
||||
<uv-image width="24px" height="24px" :src="icon" mode="widthFix"></uv-image>
|
||||
</view>
|
||||
|
||||
<view class="x-list-content">
|
||||
<view v-if="title">{{title}}</view>
|
||||
<text v-if="des">{{des}}</text>
|
||||
</view>
|
||||
<view class="x-list-right" v-if="btnText">
|
||||
<slot name="right">
|
||||
<button :open-type="openType" @click="btnClick">{{btnText}}</button>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
icon:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
title:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
des:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
btnText:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
openType:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
bottom:{
|
||||
default:"0",
|
||||
type:[String,Number]
|
||||
},
|
||||
url:{
|
||||
default:"",
|
||||
type:String
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
},
|
||||
methods: {
|
||||
btnClick(){
|
||||
if(this.url){
|
||||
this.$toPath(this.url, {
|
||||
// id: item.id
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$emit('btnClick')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.x-list {
|
||||
display: flex;
|
||||
// justify-content: center;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
|
||||
padding: 10px 10px;
|
||||
border-radius: 8px;
|
||||
// margin-bottom: 10px;
|
||||
|
||||
.x-list-content {
|
||||
font-size: 16px;
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
|
||||
text {
|
||||
line-height: 1;
|
||||
font-size: 13px;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
}
|
||||
|
||||
.x-list-right {
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 6px 8px;
|
||||
line-height: 1;
|
||||
border: 0;
|
||||
font-size: 12px;
|
||||
background-color: rgba(111, 148, 205, 1);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
108
x_admin_app/components/x-picker/x-picker.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<uv-input
|
||||
:modelValue="selectItem?.[props.labelKey]"
|
||||
placeholder="请选择"
|
||||
readonly
|
||||
@click="openPicker"
|
||||
>
|
||||
</uv-input>
|
||||
|
||||
<uv-picker
|
||||
ref="picker"
|
||||
:columns="columns"
|
||||
:keyName="props.labelKey"
|
||||
:defaultIndex="pickerIndex"
|
||||
@confirm="handleConfirm"
|
||||
></uv-picker>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
defineModel,
|
||||
|
||||
onMounted,
|
||||
computed,
|
||||
watch,
|
||||
} from "vue";
|
||||
const props = defineProps({
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
labelKey: {
|
||||
type: String,
|
||||
default: "label",
|
||||
},
|
||||
valueKey: {
|
||||
type: String,
|
||||
default: "id",
|
||||
},
|
||||
});
|
||||
const columns = computed(() => {
|
||||
return [props.columns];
|
||||
});
|
||||
const picker = ref(null);
|
||||
|
||||
const model = defineModel();
|
||||
const pickerIndex = ref([0]);
|
||||
|
||||
const selectItem = ref({});
|
||||
|
||||
function openPicker() {
|
||||
picker.value.open();
|
||||
}
|
||||
function handleConfirm(e) {
|
||||
// debugger;
|
||||
if (e.value[0]!==undefined) {
|
||||
model.value = e.value[0][props.valueKey];
|
||||
selectItem.value = e.value[0];
|
||||
}else{
|
||||
model.value = null;
|
||||
selectItem.value = {};
|
||||
console.log('handleConfirm没有数据',e);
|
||||
}
|
||||
}
|
||||
function updateSelectItem() {
|
||||
console.log("updateSelectItem", model.value, props.columns);
|
||||
if (!model.value) {
|
||||
pickerIndex.value = [0];
|
||||
selectItem.value = {};
|
||||
return;
|
||||
}
|
||||
if(props.columns.length==0){
|
||||
pickerIndex.value = [0];
|
||||
selectItem.value = {};
|
||||
return;
|
||||
}
|
||||
let find=false
|
||||
for (let index = 0; index < props.columns.length; index++) {
|
||||
const item = props.columns[index];
|
||||
if (model.value == item[props.valueKey]) {
|
||||
selectItem.value = item;
|
||||
pickerIndex.value = [index];
|
||||
find=true
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!find){
|
||||
selectItem.value = {};
|
||||
pickerIndex.value = [0];
|
||||
model.value = null;
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
console.log("onMounted");
|
||||
updateSelectItem();
|
||||
});
|
||||
watch(
|
||||
() => [model.value, props.columns],
|
||||
(newVal) => {
|
||||
console.log("watch", newVal);
|
||||
updateSelectItem();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
55
x_admin_app/hooks/useDictOptions.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { request } from "@/utils/request";
|
||||
import { reactive, toRaw } from "vue";
|
||||
|
||||
interface Options {
|
||||
[propName: string]: string
|
||||
}
|
||||
|
||||
export function useDictOptions<T = any>(options: Options) {
|
||||
const optionsData: any = reactive({});
|
||||
const optionsKey = Object.keys(options);
|
||||
|
||||
const apiLists = optionsKey.map((key) => {
|
||||
const path = options[key];
|
||||
optionsData[key] = [];
|
||||
return () =>request({
|
||||
url: path,
|
||||
method: "GET",
|
||||
});
|
||||
});
|
||||
|
||||
const refresh = async () => {
|
||||
const res = await Promise.allSettled<Promise<any>>(
|
||||
apiLists.map((api) => api())
|
||||
);
|
||||
console.log(res);
|
||||
|
||||
res.forEach((item, index) => {
|
||||
const key = optionsKey[index];
|
||||
if (item.status == "fulfilled") {
|
||||
const data = item.value;
|
||||
optionsData[key] = data.data;
|
||||
}
|
||||
});
|
||||
};
|
||||
refresh();
|
||||
return {
|
||||
optionsData: optionsData as T,
|
||||
refresh,
|
||||
};
|
||||
}
|
||||
|
||||
export function useDictData<T = any>(dict: string[]) {
|
||||
const options: Options = {};
|
||||
for (const type of dict) {
|
||||
options[type] = `/setting/dict/data/all?dictType=${type}`
|
||||
}
|
||||
const { optionsData } = useDictOptions<T>(options);
|
||||
console.log('optionsData',optionsData);
|
||||
|
||||
return {
|
||||
dictData: optionsData as T,
|
||||
};
|
||||
}
|
||||
|
||||
// export function useAllList<T = any>(options: Options) {}
|
106
x_admin_app/hooks/usePaging.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { reactive, toRaw } from "vue";
|
||||
import { toast } from "@/utils/utils";
|
||||
|
||||
// 分页钩子函数
|
||||
interface Options {
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
loadingText?: string;
|
||||
loadmoreText?: string;
|
||||
nomoreText?: string;
|
||||
|
||||
fetchFun: (_arg: any) => Promise<any>;
|
||||
params?: Record<any, any>;
|
||||
firstStatus?: string; //loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
}
|
||||
|
||||
export function usePaging(options: Options) {
|
||||
const {
|
||||
pageNo = 1,
|
||||
pageSize = 30,
|
||||
loadingText = "努力加载中",
|
||||
loadmoreText = "继续加载",
|
||||
nomoreText = "没有数据了",
|
||||
fetchFun,
|
||||
params = {},
|
||||
firstStatus = "loadmore",
|
||||
} = options;
|
||||
// 记录分页初始参数
|
||||
const paramsInit: Record<any, any> = Object.assign({}, toRaw(params));
|
||||
// 分页数据
|
||||
const pager = reactive({
|
||||
pageNo,
|
||||
pageSize,
|
||||
loadingText,
|
||||
loadmoreText,
|
||||
nomoreText,
|
||||
loading: firstStatus,
|
||||
count: 0,
|
||||
lists: [] as any[],
|
||||
});
|
||||
// 请求分页接口
|
||||
const getLists = () => {
|
||||
pager.loading = "loading";
|
||||
return fetchFun({
|
||||
pageNo: pager.pageNo,
|
||||
pageSize: pager.pageSize,
|
||||
...params,
|
||||
})
|
||||
.then((res: any) => {
|
||||
uni.stopPullDownRefresh();
|
||||
|
||||
if (res.code == 200) {
|
||||
pager.count = res?.data?.count;
|
||||
var list = res?.data?.lists || [];
|
||||
|
||||
pager.lists.push(...list);
|
||||
|
||||
if (res?.data?.lists?.length < pager.pageSize) {
|
||||
pager.loading = "nomore";
|
||||
} else {
|
||||
pager.loading = "loadmore";
|
||||
}
|
||||
}else{
|
||||
pager.loading = "loadmore";
|
||||
}
|
||||
return Promise.resolve(res);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
uni.stopPullDownRefresh();
|
||||
toast(err.message);
|
||||
pager.loading = "nomore";
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
// 下一页
|
||||
const NextPage = () => {
|
||||
if (pager.loading === "nomore") {
|
||||
toast("没有数据了");
|
||||
return;
|
||||
}
|
||||
pager.pageNo += 1;
|
||||
getLists();
|
||||
};
|
||||
|
||||
// 重置为第一页
|
||||
const resetPage = () => {
|
||||
pager.pageNo = 1;
|
||||
pager.lists = [];
|
||||
getLists();
|
||||
};
|
||||
// 重置参数
|
||||
const resetParams = () => {
|
||||
Object.keys(paramsInit).forEach((item) => {
|
||||
params[item] = paramsInit[item];
|
||||
});
|
||||
pager.lists = [];
|
||||
getLists();
|
||||
};
|
||||
return {
|
||||
pager,
|
||||
getLists,
|
||||
NextPage,
|
||||
resetParams,
|
||||
resetPage,
|
||||
};
|
||||
}
|
7
x_admin_app/images.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
declare module '*.svg'
|
||||
declare module '*.png'
|
||||
declare module '*.jpg'
|
||||
declare module '*.jpeg'
|
||||
declare module '*.gif'
|
||||
declare module '*.bmp'
|
||||
declare module '*.tiff'
|
20
x_admin_app/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
19
x_admin_app/main.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import App from "./App";
|
||||
import { createSSRApp } from "vue";
|
||||
|
||||
import { installMethods } from "@/methods/index";
|
||||
import * as Pinia from "pinia";
|
||||
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App);
|
||||
|
||||
app.use(Pinia.createPinia());
|
||||
|
||||
installMethods(app);
|
||||
|
||||
return {
|
||||
app,
|
||||
Pinia, // 此处必须将 Pinia 返回
|
||||
};
|
||||
}
|
132
x_admin_app/manifest.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"name": "x_admin_app",
|
||||
"appid": "__UNI__FB29F21",
|
||||
"description": "",
|
||||
"versionName": "1.0.2",
|
||||
"versionCode": 102,
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
"compatible": {
|
||||
"ignoreVersion": true
|
||||
},
|
||||
"usingComponents": true,
|
||||
"nvueStyleCompiler": "uni-app",
|
||||
"compilerVersion": 3,
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
},
|
||||
"modules": {},
|
||||
"distribute": {
|
||||
"android": {
|
||||
"permissions": [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
],
|
||||
"minSdkVersion": 26,
|
||||
"schemes": "x_admin",
|
||||
"targetSdkVersion": 30
|
||||
},
|
||||
"ios": {
|
||||
"urltypes": "x_admin",
|
||||
"dSYMs": false
|
||||
},
|
||||
"sdkConfigs": {
|
||||
"ad": {}
|
||||
},
|
||||
"icons": {
|
||||
"android": {
|
||||
"hdpi": "unpackage/res/icons/72x72.png",
|
||||
"xhdpi": "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi": "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi": "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios": {
|
||||
"appstore": "unpackage/res/icons/1024x1024.png",
|
||||
"ipad": {
|
||||
"app": "unpackage/res/icons/76x76.png",
|
||||
"app@2x": "unpackage/res/icons/152x152.png",
|
||||
"notification": "unpackage/res/icons/20x20.png",
|
||||
"notification@2x": "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x": "unpackage/res/icons/167x167.png",
|
||||
"settings": "unpackage/res/icons/29x29.png",
|
||||
"settings@2x": "unpackage/res/icons/58x58.png",
|
||||
"spotlight": "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x": "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone": {
|
||||
"app@2x": "unpackage/res/icons/120x120.png",
|
||||
"app@3x": "unpackage/res/icons/180x180.png",
|
||||
"notification@2x": "unpackage/res/icons/40x40.png",
|
||||
"notification@3x": "unpackage/res/icons/60x60.png",
|
||||
"settings@2x": "unpackage/res/icons/58x58.png",
|
||||
"settings@3x": "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x": "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x": "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
"splashscreen": {
|
||||
"useOriginalMsgbox": true
|
||||
}
|
||||
},
|
||||
"nvueLaunchMode": "",
|
||||
"nativePlugins": {
|
||||
"usb-serial-for-uniapp": {
|
||||
"__plugin_info__": {
|
||||
"name": "usb-serial-for-uniapp",
|
||||
"description": "uniapp的USB串口通信插件,驱动基于开源项目usb-serial-for-android,无需ROOT,支持OTG USB串口、CP210X、CH34X等",
|
||||
"platforms": "Android",
|
||||
"url": "https://ext.dcloud.net.cn/plugin?id=13935",
|
||||
"android_package_name": "uni.UNIFB29F21",
|
||||
"ios_bundle_id": "",
|
||||
"isCloud": true,
|
||||
"bought": 1,
|
||||
"pid": "13935",
|
||||
"parameters": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"quickapp": {},
|
||||
"mp-weixin": {
|
||||
"appid": "",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
"usingComponents": true,
|
||||
"unipush": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-alipay": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-baidu": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-toutiao": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"vueVersion": "3",
|
||||
"locale": "zh-Hans",
|
||||
"fallbackLocale": "zh-Hans"
|
||||
}
|
27
x_admin_app/methods/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { perms } from "@/utils/perms.js";
|
||||
import { toPath } from "@/utils/utils.js";
|
||||
import env from "@/utils/env";
|
||||
|
||||
/**
|
||||
* @description: 获取文件路径
|
||||
* @param {String} src 文件路径
|
||||
* @return {String} 文件路径
|
||||
*/
|
||||
export function filePath(src :string) {
|
||||
let path = "";
|
||||
if (src) {
|
||||
if (src.startsWith("http")) {
|
||||
return src;
|
||||
}
|
||||
path = `${env.baseUrl}${src}`;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
// 在全局配置对象中添加$perms属性,并将其值设为perms
|
||||
export function installMethods(app) {
|
||||
app.config.globalProperties.$perms = perms;
|
||||
app.config.globalProperties.$toPath = toPath;
|
||||
app.config.globalProperties.$filePath = filePath;
|
||||
}
|
12
x_admin_app/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.1.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.4.8",
|
||||
"@uni-helper/uni-app-types": "^0.5.13"
|
||||
}
|
||||
}
|
84
x_admin_app/pages.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"pages": [{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "管理系统"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/my/my",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/monitor_project/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "项目监控",
|
||||
"enablePullDownRefresh": true,
|
||||
"onReachBottomDistance": 100,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/monitor_project/details",
|
||||
"style": {
|
||||
"navigationBarTitleText": "项目监控详情",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/monitor_project/edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑项目监控"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/monitor_project/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索项目监控"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "x admin",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#ccc",
|
||||
"pageOrientation": "portrait"
|
||||
},
|
||||
|
||||
|
||||
"tabBar": {
|
||||
"color": "#000000",
|
||||
"selectedColor": "#007aff",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/icons/tabs/home.png",
|
||||
"selectedIconPath": "static/icons/tabs/homeActive.png",
|
||||
"text": "首页"
|
||||
},
|
||||
|
||||
{
|
||||
"pagePath": "pages/my/my",
|
||||
"iconPath": "static/icons/tabs/my.png",
|
||||
"selectedIconPath": "static/icons/tabs/myActive.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
121
x_admin_app/pages/index/index.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<uv-swiper :list="list" circular indicator indicatorMode="dot"></uv-swiper>
|
||||
<!-- <uv-notice-bar :text="text" direction="column"></uv-notice-bar> -->
|
||||
|
||||
<uv-grid :border="false">
|
||||
<uv-grid-item v-for="(item, index) in baseList" :key="index" @click="toList(item)">
|
||||
<uv-icon :customStyle="{ padding: '50rpx 0 20rpx' }" :name="item.icon" :size="26"></uv-icon>
|
||||
|
||||
<text class="grid-text">{{ item.title }}</text>
|
||||
</uv-grid-item>
|
||||
</uv-grid>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from "vue";
|
||||
|
||||
import {
|
||||
toPath,
|
||||
toast,
|
||||
scanCode,
|
||||
queryToObj,
|
||||
} from "@/utils/utils.js";
|
||||
|
||||
let list = [
|
||||
"https://cdn.uviewui.com/uview/swiper/swiper1.png",
|
||||
"https://cdn.uviewui.com/uview/swiper/swiper2.png",
|
||||
"https://cdn.uviewui.com/uview/swiper/swiper3.png",
|
||||
];
|
||||
let text = ["Fota", "轻松管理"];
|
||||
|
||||
|
||||
let baseList = [
|
||||
// {
|
||||
// icon: "/static/index/product.png",
|
||||
// path: "/pages/product/product",
|
||||
// title: "产品",
|
||||
// },
|
||||
// {
|
||||
// icon: "/static/index/group.png",
|
||||
// path: "/pages/group/group",
|
||||
// title: "分组",
|
||||
// },
|
||||
// {
|
||||
// icon: "/static/index/version.png",
|
||||
// path: "/pages/version/version",
|
||||
// title: "版本",
|
||||
// },
|
||||
{
|
||||
icon: "/static/index/equipment.png",
|
||||
path: "/pages/monitor_project/index",
|
||||
title: "项目监控",
|
||||
},
|
||||
|
||||
{
|
||||
icon: "/static/index/equipment.png",
|
||||
path: "/pages/equipment/equipment",
|
||||
title: "设备管理",
|
||||
},
|
||||
|
||||
{
|
||||
icon: "scan",
|
||||
// path: "/pages/equipment/equipment",
|
||||
title: "扫码维护",
|
||||
fn: function() {
|
||||
// console.log('this', this);
|
||||
scanCode().then((path) => {
|
||||
// toPath(path);
|
||||
if (!path) {
|
||||
return
|
||||
}
|
||||
var query = queryToObj(path);
|
||||
if (!query.state) {
|
||||
toast("请扫描设备二维码");
|
||||
return;
|
||||
}
|
||||
toPath("/pages/equipment/details", {
|
||||
number: query.state,
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "/static/index/equipmentLog.png",
|
||||
path: "/pages/statistics/statistics",
|
||||
title: "销量统计",
|
||||
},
|
||||
// {
|
||||
// icon: "/static/index/sysUp.png",
|
||||
// path: "/pages/log/sysUp/sysUp",
|
||||
// title: "上行日志",
|
||||
// },
|
||||
// {
|
||||
// icon: "/static/index/sysDown.png",
|
||||
// path: "/pages/log/sysDown/sysDown",
|
||||
// title: "下行日志",
|
||||
// },
|
||||
// {
|
||||
// icon: "/static/index/log.png",
|
||||
// path: "/pages/log/sysLog/sysLog",
|
||||
// title: "系统日志",
|
||||
// },
|
||||
];
|
||||
|
||||
function toList(item) {
|
||||
if (item.fn) {
|
||||
item.fn();
|
||||
} else {
|
||||
toPath(item.path);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.grid-text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
176
x_admin_app/pages/login/login.vue
Normal file
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<view>
|
||||
<uv-form
|
||||
class="form"
|
||||
ref="form"
|
||||
labelWidth="60"
|
||||
labelAlign="right"
|
||||
:model="model"
|
||||
:rules="rules"
|
||||
>
|
||||
<uv-form-item class="hide">
|
||||
<uv-input
|
||||
class="hide"
|
||||
v-model="model.username"
|
||||
placeholder="请输入账号"
|
||||
:rules="[{ required: true, message: '请填写账号' }]"
|
||||
/>
|
||||
</uv-form-item>
|
||||
<uv-form-item class="hide">
|
||||
<uv-input
|
||||
type="password"
|
||||
v-model="model.password"
|
||||
placeholder="请输入密码"
|
||||
:rules="[{ required: true, message: '请填写密码' }]"
|
||||
/>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="账号" name="username" prop="username">
|
||||
<uv-input
|
||||
v-model="model.username"
|
||||
placeholder="请输入账号"
|
||||
:rules="[{ required: true, message: '请填写账号' }]"
|
||||
/>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="密码" name="password" prop="password">
|
||||
<uv-input
|
||||
type="password"
|
||||
v-model="model.password"
|
||||
placeholder="请输入密码"
|
||||
:rules="[{ required: true, message: '请填写密码' }]"
|
||||
/>
|
||||
</uv-form-item>
|
||||
|
||||
<Verify
|
||||
@success="VerifySuccess"
|
||||
:mode="'pop'"
|
||||
:captchaType="'blockPuzzle'"
|
||||
ref="verifyRef"
|
||||
:imgSize="{ width: '310px', height: '155px' }"
|
||||
></Verify>
|
||||
|
||||
|
||||
<view class="footer">
|
||||
<!-- -->
|
||||
|
||||
<wd-button class="btn" size="large" @click="VerifyShow" block
|
||||
>VerifyShow</wd-button
|
||||
>
|
||||
|
||||
<wd-button class="btn" size="large" @click="handleSubmit" block
|
||||
>登录</wd-button
|
||||
>
|
||||
</view>
|
||||
</uv-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from "vue";
|
||||
import { v1 as uuid_v1 } from "uuid";
|
||||
|
||||
import Verify from "@/components/verifition/verify";
|
||||
|
||||
import { login } from "@/api/user.js";
|
||||
import { setLocalStorage } from "@/utils/storage.js";
|
||||
import { toast } from "@/utils/utils.js";
|
||||
// import appicon from "@/static/appicon.png";
|
||||
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
|
||||
const model = reactive({
|
||||
username: "",
|
||||
password: "",
|
||||
});
|
||||
const rules = {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写账号",
|
||||
trigger: ["blur", "change"],
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写密码",
|
||||
trigger: ["blur", "change"],
|
||||
},
|
||||
],
|
||||
|
||||
};
|
||||
const form = ref();
|
||||
const verifyRef=ref()
|
||||
function VerifyShow(e) {
|
||||
verifyRef.value.show()
|
||||
}
|
||||
function VerifySuccess(e) {
|
||||
console.log('VerifySuccess',e);
|
||||
|
||||
handleSubmit(e)
|
||||
}
|
||||
function handleSubmit(verify) {
|
||||
form.value
|
||||
.validate()
|
||||
.then((res) => {
|
||||
let data = {
|
||||
username: model.username,
|
||||
password: model.password,
|
||||
|
||||
...verify
|
||||
};
|
||||
|
||||
// userStore.getUser();
|
||||
|
||||
login(data)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
setLocalStorage("token", res.data.token);
|
||||
|
||||
userStore.getInfo().then((res) => {
|
||||
uni.switchTab({
|
||||
url: "/pages/index/index",
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
||||
toast(res.message);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
toast(err.message);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
toast(err.message);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.hide {
|
||||
height: 0 !important;
|
||||
padding: 0 !important;
|
||||
|
||||
border: 0 !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.form {
|
||||
margin: 200rpx 20rpx;
|
||||
|
||||
.captchaImage {
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 60rpx 20rpx 200rpx;
|
||||
|
||||
.btn {
|
||||
background-color: #00b294;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
102
x_admin_app/pages/monitor_project/details.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<view class="page-content">
|
||||
<uv-navbar leftText="" :placeholder="true" title="监控项目详情" autoBack>
|
||||
<template v-slot:right>
|
||||
<uv-icon name="edit-pen" size="20" @click="edit"></uv-icon>
|
||||
</template>
|
||||
</uv-navbar>
|
||||
|
||||
<uv-form labelPosition="left" labelWidth="80" :model="form">
|
||||
<uv-form-item label="项目uuid" prop="projectKey" borderBottom>
|
||||
{{form.projectKey}}
|
||||
</uv-form-item>
|
||||
<uv-form-item label="项目名称" prop="projectName" borderBottom>
|
||||
{{form.projectName}}
|
||||
</uv-form-item>
|
||||
<uv-form-item label="项目类型" prop="projectType" borderBottom>
|
||||
{{form.projectType}}
|
||||
</uv-form-item>
|
||||
<uv-form-item label="创建时间" prop="createTime" borderBottom>
|
||||
{{form.createTime}}
|
||||
</uv-form-item>
|
||||
<uv-form-item label="更新时间" prop="updateTime" borderBottom>
|
||||
{{form.updateTime}}
|
||||
</uv-form-item>
|
||||
</uv-form>
|
||||
<uv-button
|
||||
v-if="$perms('admin:monitor_project:edit')"
|
||||
type="primary"
|
||||
text="编辑"
|
||||
customStyle="margin-top: 20rpx"
|
||||
@click="edit"
|
||||
></uv-button>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
computed
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onPullDownRefresh
|
||||
} from "@dcloudio/uni-app";
|
||||
|
||||
import {
|
||||
useDictData
|
||||
} from "@/hooks/useDictOptions";
|
||||
import {
|
||||
monitor_project_detail
|
||||
} from "@/api/monitor_project";
|
||||
|
||||
|
||||
import {
|
||||
toast,
|
||||
alert,
|
||||
toPath
|
||||
} from "@/utils/utils";
|
||||
|
||||
let form = ref({});
|
||||
onLoad((e) => {
|
||||
console.log("onLoad", e);
|
||||
getDetails(e.id);
|
||||
});
|
||||
onShow((e) => {
|
||||
if (form.value?.id) {
|
||||
getDetails(form.value.id);
|
||||
}
|
||||
});
|
||||
onPullDownRefresh(() => {
|
||||
getDetails(form.value.id);
|
||||
});
|
||||
function getDetails(id) {
|
||||
monitor_project_detail(id).then((res) => {
|
||||
uni.stopPullDownRefresh();
|
||||
if (res.code == 200) {
|
||||
if (res?.data) {
|
||||
form.value = res?.data
|
||||
}
|
||||
} else {
|
||||
toast(res.message);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.stopPullDownRefresh();
|
||||
toast(err.message||"网络错误");
|
||||
});
|
||||
}
|
||||
|
||||
function edit() {
|
||||
toPath("/pages/monitor_project/edit", { id: form.value.id });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
padding: 10rpx 20rpx 300rpx;
|
||||
}
|
||||
</style>
|
112
x_admin_app/pages/monitor_project/edit.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<view class="page-content">
|
||||
<uv-form
|
||||
labelPosition="left"
|
||||
labelWidth="80"
|
||||
:model="form"
|
||||
:rules="formRules"
|
||||
ref="formRef"
|
||||
>
|
||||
|
||||
<uv-form-item label="项目uuid" prop="projectKey" borderBottom>
|
||||
<uv-input v-model="form.projectKey" border="surround"></uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="项目名称" prop="projectName" borderBottom>
|
||||
<uv-input v-model="form.projectName" border="surround"></uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="项目类型" prop="projectType" borderBottom>
|
||||
<x-picker v-model="form.projectType" valueKey="value" labelKey="name" :columns="dictData.project_type"></x-picker>
|
||||
</uv-form-item>
|
||||
|
||||
<uv-button
|
||||
type="primary"
|
||||
text="提交"
|
||||
customStyle="margin-top: 20rpx"
|
||||
@click="submit"
|
||||
></uv-button>
|
||||
</uv-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, computed } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import {
|
||||
monitor_project_detail,
|
||||
monitor_project_edit,
|
||||
} from "@/api/monitor_project";
|
||||
import { toast, alert } from "@/utils/utils";
|
||||
import { useDictData } from "@/hooks/useDictOptions";
|
||||
const { dictData } = useDictData(['project_type'])
|
||||
let formRef = ref();
|
||||
let form = ref({
|
||||
id: "",
|
||||
projectKey: "",
|
||||
projectName: "",
|
||||
projectType: "",
|
||||
});
|
||||
const formRules = {
|
||||
projectKey: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目uuid",
|
||||
trigger: ["blur"],
|
||||
},
|
||||
],
|
||||
projectName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目名称",
|
||||
trigger: ["blur"],
|
||||
},
|
||||
],
|
||||
projectType: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择项目类型",
|
||||
trigger: ["blur"],
|
||||
},
|
||||
],
|
||||
};
|
||||
onLoad((e) => {
|
||||
console.log("onLoad", e);
|
||||
getDetails(e.id);
|
||||
});
|
||||
|
||||
function getDetails(id) {
|
||||
monitor_project_detail(id)
|
||||
.then((res) => {
|
||||
if (res.code == 200) {
|
||||
if (res?.data) {
|
||||
form.value = res?.data;
|
||||
}
|
||||
} else {
|
||||
toast(res.message);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
toast(err.message || "网络错误");
|
||||
});
|
||||
}
|
||||
|
||||
function submit(item) {
|
||||
console.log("submit", form);
|
||||
formRef.value.validate().then(() => {
|
||||
monitor_project_edit(form.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
toast("编辑成功");
|
||||
|
||||
getDetails(form.value?.id);
|
||||
} else {
|
||||
toast(res.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
padding: 10rpx 20rpx 300rpx;
|
||||
}
|
||||
</style>
|
119
x_admin_app/pages/monitor_project/index.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
<uv-sticky :customNavHeight="0" bgColor="#fff">
|
||||
<uv-status-bar></uv-status-bar>
|
||||
<uv-navbar
|
||||
leftText=""
|
||||
:safeAreaInsetTop="false"
|
||||
:fixed="false"
|
||||
title="监控项目"
|
||||
autoBack
|
||||
>
|
||||
<template v-slot:right>
|
||||
<uv-icon v-if="!fromSearch" name="search" size="24" @click="moreSearch"></uv-icon>
|
||||
</template>
|
||||
</uv-navbar>
|
||||
<!-- <view class="search">
|
||||
<uv-search
|
||||
placeholder="请输入搜索内容"
|
||||
shape="square"
|
||||
v-model="queryParams.key"
|
||||
:showAction="false"
|
||||
bgColor="#fff"
|
||||
borderColor="rgba(0, 0, 0, .1)"
|
||||
@search="resetPage"
|
||||
></uv-search>
|
||||
</view> -->
|
||||
</uv-sticky>
|
||||
|
||||
<uv-list>
|
||||
<uv-list-item
|
||||
v-for="item of pager.lists"
|
||||
:key="item.id"
|
||||
clickable
|
||||
show-arrow
|
||||
:title="item.projectName"
|
||||
:note="item.projectType"
|
||||
|
||||
@click="toDetails(item)"
|
||||
></uv-list-item>
|
||||
</uv-list>
|
||||
|
||||
<uv-back-top :scroll-top="scrollTop"></uv-back-top>
|
||||
|
||||
<uv-empty v-if="pager.loading =='nomore'&&pager.lists.length == 0" marginTop="150" mode="data"></uv-empty>
|
||||
|
||||
<uv-loading-page
|
||||
:loading="pager.pageNo == 1 && pager.loading == 'loading'"
|
||||
loading-text="加载中..."
|
||||
font-size="24rpx"
|
||||
></uv-loading-page>
|
||||
<uv-load-more
|
||||
v-if="pager.lists.length > 0"
|
||||
:status="pager.loading"
|
||||
:loading-text="pager.loadingText"
|
||||
:loadmore-text="pager.loadmoreText"
|
||||
:nomore-text="pager.nomoreText"
|
||||
@loadmore="NextPage"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onPullDownRefresh,
|
||||
onReachBottom,
|
||||
onPageScroll,
|
||||
} from "@dcloudio/uni-app";
|
||||
import { monitor_project_list } from "@/api/monitor_project";
|
||||
import { usePaging } from "@/hooks/usePaging";
|
||||
import { toPath } from "@/utils/utils";
|
||||
const queryParams = reactive({
|
||||
key: "",
|
||||
|
||||
});
|
||||
let fromSearch=ref(false);
|
||||
onLoad((e) => {
|
||||
console.log("monitor_project onLoad", e);
|
||||
if (e) {
|
||||
for (const key in e) {
|
||||
if (Object.hasOwnProperty.call(e, key)) {
|
||||
fromSearch.value = true;
|
||||
queryParams[key] = e[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
getLists();
|
||||
});
|
||||
const { pager, getLists, NextPage, resetPage, resetParams } = usePaging({
|
||||
fetchFun: monitor_project_list,
|
||||
params: queryParams,
|
||||
});
|
||||
let scrollTop = ref(0);
|
||||
onPageScroll((e) => {
|
||||
scrollTop.value = e.scrollTop;
|
||||
});
|
||||
onPullDownRefresh(() => {
|
||||
resetPage();
|
||||
});
|
||||
onReachBottom(() => {
|
||||
NextPage();
|
||||
});
|
||||
|
||||
function toDetails(item) {
|
||||
toPath("/pages/monitor_project/details", { id: item.id });
|
||||
}
|
||||
function moreSearch() {
|
||||
toPath("/pages/monitor_project/search");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
padding: 5rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
75
x_admin_app/pages/monitor_project/search.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<view class="page-content">
|
||||
<uv-form labelPosition="left" labelWidth="80" :model="form" ref="formRef">
|
||||
<uv-form-item label="项目uuid" prop="projectKey" borderBottom>
|
||||
<uv-input v-model="form.projectKey"> </uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="项目名称" prop="projectName" borderBottom>
|
||||
<uv-input v-model="form.projectName"> </uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item
|
||||
label="项目类型"
|
||||
prop="projectType"
|
||||
borderBottom
|
||||
>
|
||||
<x-picker v-model="form.projectType" valueKey="value" labelKey="name" :columns="dictData.project_type"></x-picker>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="创建时间" prop="createTime" borderBottom>
|
||||
<xDateRange
|
||||
v-model:startTime="form.createTimeStart"
|
||||
v-model:endTime="form.createTimeEnd"
|
||||
></xDateRange>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="更新时间" prop="updateTime" borderBottom>
|
||||
<xDateRange
|
||||
v-model:startTime="form.updateTimeStart"
|
||||
v-model:endTime="form.updateTimeEnd"
|
||||
></xDateRange>
|
||||
</uv-form-item>
|
||||
|
||||
<uv-button
|
||||
type="primary"
|
||||
text="搜索"
|
||||
customStyle="margin-top: 20rpx"
|
||||
@click="submit"
|
||||
></uv-button>
|
||||
</uv-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { reactive, ref, computed } from "vue";
|
||||
import { toPath, toast, clearObjEmpty } from "@/utils/utils";
|
||||
import { useDictData } from "@/hooks/useDictOptions";
|
||||
import xDateRange from "@/components/x-date-range/x-date-range.vue"
|
||||
const { dictData } = useDictData(['project_type'])
|
||||
let formRef = ref();
|
||||
let form = ref({
|
||||
projectKey: "",
|
||||
projectName: "",
|
||||
projectType: "",
|
||||
createTimeStart: "",
|
||||
createTimeEnd: "",
|
||||
updateTimeStart: "",
|
||||
updateTimeEnd: "",
|
||||
});
|
||||
|
||||
function submit() {
|
||||
console.log("submit", form.value);
|
||||
|
||||
const search = clearObjEmpty(form.value);
|
||||
|
||||
if (Object.keys(search).length === 0) {
|
||||
return toast("请输入查询条件");
|
||||
}
|
||||
|
||||
toPath("/pages/monitor_project/index", search);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
padding: 10rpx 20rpx 300rpx;
|
||||
}
|
||||
</style>
|
63
x_admin_app/pages/my/my.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view class="my">
|
||||
<uv-sticky offsetTop="-1" bgColor="#ffffff">
|
||||
<view style="background: #fff">
|
||||
<uv-cell :title="userStore?.username" :label="userStore?.nickname" isLink>
|
||||
<!-- -->
|
||||
<template v-slot:icon>
|
||||
<button class="avatar-wrapper" open-type="chooseAvatar" @click.stop>
|
||||
<uv-avatar
|
||||
width="100%"
|
||||
height="100%"
|
||||
shape="circle"
|
||||
:src="$filePath(userStore.avatar)"
|
||||
mode="widthFix"
|
||||
></uv-avatar>
|
||||
</button>
|
||||
</template>
|
||||
</uv-cell>
|
||||
</view>
|
||||
</uv-sticky>
|
||||
<uv-button
|
||||
class="btn"
|
||||
type="primary"
|
||||
text="登录"
|
||||
@click="toLogin"
|
||||
></uv-button>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
function toLogin() {
|
||||
uni.redirectTo({
|
||||
url: "/pages/login/login",
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.my {
|
||||
background-color: rgba(243, 246, 249, 1);
|
||||
padding-bottom: 40px;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 7px;
|
||||
background-color: white;
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 200rpx 20rpx;
|
||||
}
|
||||
</style>
|
BIN
x_admin_app/static/appicon.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
x_admin_app/static/default.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
x_admin_app/static/icons/tabs/home.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
x_admin_app/static/icons/tabs/homeActive.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
x_admin_app/static/icons/tabs/my.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
x_admin_app/static/icons/tabs/myActive.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
x_admin_app/static/index/equipment.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
x_admin_app/static/index/equipmentLog.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
x_admin_app/static/index/group.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
x_admin_app/static/index/log.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
x_admin_app/static/index/product.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
x_admin_app/static/index/serial.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
x_admin_app/static/index/sysDown.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
x_admin_app/static/index/sysUp.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
x_admin_app/static/index/version.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
77
x_admin_app/stores/user.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { logout, getInfo } from "@/api/user";
|
||||
|
||||
import { getLocalStorage, removeLocalStorage } from "@/utils/storage.js";
|
||||
|
||||
export const useUserStore = defineStore("user", {
|
||||
state: () => {
|
||||
return {
|
||||
nickname: "",
|
||||
username: "",
|
||||
avatar: "",
|
||||
userInfo: {},
|
||||
menu: [],
|
||||
auth: [],
|
||||
};
|
||||
},
|
||||
// 也可以这样定义
|
||||
// state: () => ({ count: 0 })
|
||||
actions: {
|
||||
// get user info
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let token = getLocalStorage("token");
|
||||
if (!token) {
|
||||
return reject(new Error("需要登录"));
|
||||
}
|
||||
getInfo(token)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
const { data } = res;
|
||||
this.nickname = data.user.nickname;
|
||||
this.username = data.user.username;
|
||||
|
||||
this.avatar = data.user.avatar ||"";
|
||||
// this.menu = data.menu;
|
||||
// this.auth = data.auth;
|
||||
this.userInfo = data.user;
|
||||
resolve(data);
|
||||
} else {
|
||||
reject(new Error(res.message));
|
||||
}
|
||||
|
||||
// addRoutes(result.menu);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// user logout
|
||||
logout() {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout()
|
||||
.then(() => {
|
||||
// resetRouter();
|
||||
this.resetToken();
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// remove token
|
||||
resetToken() {
|
||||
return new Promise((resolve) => {
|
||||
// this.token = "";
|
||||
this.name = "";
|
||||
this.avatar = "";
|
||||
removeLocalStorage("token");
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
29
x_admin_app/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"include": [
|
||||
"global.d.ts",
|
||||
"methods/**/*",
|
||||
"api/**/*.ts",
|
||||
"pages/**/*.vue",
|
||||
"components/**/*.vue",
|
||||
"stores/**/*",
|
||||
"utils/**/*",
|
||||
"typings/**/*.d.ts",
|
||||
"hooks/usePaging.ts"
|
||||
],
|
||||
"exclude": ["dist", "node_modules", "uni_modules", "unpackage"],
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "Bundler",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"outDir": "./dist",
|
||||
"isolatedModules": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
},
|
||||
"types": ["@dcloudio/types", "@uni-helper/uni-app-types"]
|
||||
}
|
||||
}
|
7
x_admin_app/typings/methods.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomProperties {
|
||||
$filePath: (typeof import('@/methods/index'))['filePath']
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
32
x_admin_app/typings/uniapp.d.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/// <reference types="@dcloudio/types" />
|
||||
/// <reference types="@dcloudio/types" />
|
||||
/// <reference types="@dcloudio/types" />
|
||||
/// <reference types="@dcloudio/types" />
|
||||
|
||||
declare module '@dcloudio/uni-app' {
|
||||
export const onShow: (callback: ((options?: App.LaunchShowOption) => void) | (() => void), target?: null) => Function;
|
||||
export const onHide: (callback: (() => void) | (() => void), target?: null) => Function;
|
||||
export const onLaunch: (callback: (options?: App.LaunchShowOption) => void, target?: null) => Function;
|
||||
export const onError: (callback: (error: string) => void, target?: null) => Function;
|
||||
export const onPageNotFound: (callback: (options: App.PageNotFoundOption) => void, target?: null) => Function;
|
||||
export const onUnhandledRejection: (callback: (options: UniApp.OnUnhandledRejectionCallbackResult) => void, target?: null) => Function;
|
||||
export const onThemeChange: (callback: (options: UniApp.OnThemeChangeCallbackResult) => void, target?: null) => Function;
|
||||
export const onUniNViewMessage: (callback: (options: AnyObject) => void, target?: null) => Function;
|
||||
export const onInit: (callback: (query?: AnyObject) => void, target?: null) => Function;
|
||||
export const onLoad: (callback: (query?: AnyObject) => void, target?: null) => Function;
|
||||
export const onReady: (callback: () => void, target?: null) => Function;
|
||||
export const onUnload: (callback: () => void, target?: null) => Function;
|
||||
export const onPullDownRefresh: (callback: () => void, target?: null) => Function;
|
||||
export const onReachBottom: (callback: () => void, target?: null) => Function;
|
||||
export const onShareAppMessage: (callback: (options: Page.ShareAppMessageOption) => Page.CustomShareContent, target?: null) => Function;
|
||||
export const onShareTimeline: (callback: () => Page.ShareTimelineContent, target?: null) => Function;
|
||||
export const onAddToFavorites: (callback: (options: Page.AddToFavoritesOption) => Page.CustomFavoritesContent, target?: null) => Function;
|
||||
export const onPageScroll: (callback: (options: Page.PageScrollOption) => void, target?: null) => Function;
|
||||
export const onResize: (callback: (options: Page.PageScrollOption) => void, target?: null) => Function;
|
||||
export const onTabItemTap: (callback: (options: Page.TabItemTapOption) => void, target?: null) => Function;
|
||||
export const onNavigationBarButtonTap: (callback: (options: Page.NavigationBarButtonTapOption) => void, target?: null) => Function;
|
||||
export const onBackPress: (callback: (options: Page.BackPressOption) => any, target?: null) => Function;
|
||||
export const onNavigationBarSearchInputChanged: (callback: (event: Page.NavigationBarSearchInputEvent) => void, target?: null) => Function;
|
||||
export const onNavigationBarSearchInputConfirmed: (callback: (event: Page.NavigationBarSearchInputEvent) => void, target?: null) => Function;
|
||||
export const onNavigationBarSearchInputClicked: (callback: () => void, target?: null) => Function;
|
||||
}
|
10
x_admin_app/uni.promisify.adaptor.js
Normal file
@@ -0,0 +1,10 @@
|
||||
uni.addInterceptor({
|
||||
returnValue (res) {
|
||||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||
return res;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1]));
|
||||
});
|
||||
},
|
||||
});
|
76
x_admin_app/uni.scss
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
// @import '@/uni_modules/uv-ui-tools/theme.scss';
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color:#333;//基本色
|
||||
$uni-text-color-inverse:#fff;//反色
|
||||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable:#c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-bg-color-grey:#f8f8f8;
|
||||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color:#c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm:12px;
|
||||
$uni-font-size-base:14px;
|
||||
$uni-font-size-lg:16px;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm:20px;
|
||||
$uni-img-size-base:26px;
|
||||
$uni-img-size-lg:40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2C405A; // 文章标题颜色
|
||||
$uni-font-size-title:20px;
|
||||
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||
$uni-font-size-subtitle:26px;
|
||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$uni-font-size-paragraph:15px;
|
7
x_admin_app/uni_modules/uv-action-sheet/changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 1.0.2(2023-07-02)
|
||||
uv-action-sheet 由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/actionSheet.html
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-action-sheet 底部操作菜单
|
@@ -0,0 +1,50 @@
|
||||
export default {
|
||||
props: {
|
||||
// 标题,有值则显示,同时会显示关闭按钮
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 选项上方的描述信息
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 数据
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 取消按钮的文字,不为空时显示按钮
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 点击某个菜单项时是否关闭弹窗
|
||||
closeOnClickAction: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 处理底部安全区(默认true)
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 小程序的打开方式
|
||||
openType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 点击遮罩是否允许关闭 (默认true)
|
||||
closeOnClickOverlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 圆角值
|
||||
round: {
|
||||
type: [Boolean, String, Number],
|
||||
default: 0
|
||||
},
|
||||
...uni.$uv?.props?.actionSheet
|
||||
}
|
||||
}
|
@@ -0,0 +1,280 @@
|
||||
|
||||
<template>
|
||||
<uv-popup
|
||||
ref="popup"
|
||||
mode="bottom"
|
||||
:safeAreaInsetBottom="safeAreaInsetBottom"
|
||||
:round="round"
|
||||
:close-on-click-overlay="closeOnClickOverlay"
|
||||
@change="popupChange"
|
||||
>
|
||||
<view class="uv-action-sheet">
|
||||
<view
|
||||
class="uv-action-sheet__header"
|
||||
v-if="title"
|
||||
>
|
||||
<text class="uv-action-sheet__header__title uv-line-1">{{title}}</text>
|
||||
<view
|
||||
class="uv-action-sheet__header__icon-wrap"
|
||||
@tap.stop="cancel"
|
||||
>
|
||||
<uv-icon
|
||||
name="close"
|
||||
size="17"
|
||||
color="#c8c9cc"
|
||||
bold
|
||||
></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<text
|
||||
class="uv-action-sheet__description"
|
||||
:style="[{
|
||||
marginTop: `${title && description ? 0 : '18px'}`
|
||||
}]"
|
||||
v-if="description"
|
||||
>{{description}}</text>
|
||||
<slot>
|
||||
<uv-line v-if="description"></uv-line>
|
||||
<view class="uv-action-sheet__item-wrap">
|
||||
<view v-for="(item, index) in actions" :key="index">
|
||||
<!-- #ifdef MP -->
|
||||
<button
|
||||
class="uv-reset-button"
|
||||
:openType="item.openType"
|
||||
@getuserinfo="onGetUserInfo"
|
||||
@contact="onContact"
|
||||
@getphonenumber="onGetPhoneNumber"
|
||||
@error="onError"
|
||||
@launchapp="onLaunchApp"
|
||||
@opensetting="onOpenSetting"
|
||||
:lang="lang"
|
||||
:session-from="sessionFrom"
|
||||
:send-message-title="sendMessageTitle"
|
||||
:send-message-path="sendMessagePath"
|
||||
:send-message-img="sendMessageImg"
|
||||
:show-message-card="showMessageCard"
|
||||
:app-parameter="appParameter"
|
||||
@tap="selectHandler(index)"
|
||||
:hover-class="!item.disabled && !item.loading ? 'uv-action-sheet--hover' : ''"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<view
|
||||
class="uv-action-sheet__item-wrap__item"
|
||||
@tap.stop="selectHandler(index)"
|
||||
:hover-class="!item.disabled && !item.loading ? 'uv-action-sheet--hover' : ''"
|
||||
:hover-stay-time="150"
|
||||
>
|
||||
<template v-if="!item.loading">
|
||||
<text
|
||||
class="uv-action-sheet__item-wrap__item__name"
|
||||
:style="[itemStyle(index)]"
|
||||
>{{ item.name }}</text>
|
||||
<text
|
||||
v-if="item.subname"
|
||||
class="uv-action-sheet__item-wrap__item__subname"
|
||||
>{{ item.subname }}</text>
|
||||
</template>
|
||||
<uv-loading-icon
|
||||
v-else
|
||||
custom-class="van-action-sheet__loading"
|
||||
size="18"
|
||||
mode="circle"
|
||||
/>
|
||||
</view>
|
||||
<!-- #ifdef MP -->
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<uv-line v-if="index !== actions.length - 1"></uv-line>
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
<uv-gap
|
||||
bgColor="#eaeaec"
|
||||
height="6"
|
||||
v-if="cancelText"
|
||||
></uv-gap>
|
||||
<view hover-class="uv-action-sheet--hover">
|
||||
<text
|
||||
@touchmove.stop.prevent
|
||||
:hover-stay-time="150"
|
||||
v-if="cancelText"
|
||||
class="uv-action-sheet__cancel-text"
|
||||
@tap="cancel"
|
||||
>{{cancelText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import button from '@/uni_modules/uv-ui-tools/libs/mixin/button.js'
|
||||
import openType from '@/uni_modules/uv-ui-tools/libs/mixin/openType.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* ActionSheet 操作菜单
|
||||
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
|
||||
* @tutorial https://www.uvui.cn/components/actionSheet.html
|
||||
* @property {Boolean} show 操作菜单是否展示 (默认 false )
|
||||
* @property {String} title 操作菜单标题
|
||||
* @property {String} description 选项上方的描述信息
|
||||
* @property {Array<Object>} actions 按钮的文字数组,见官方文档示例
|
||||
* @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
|
||||
* @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true )
|
||||
* @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true )
|
||||
* @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
|
||||
* @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
|
||||
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
|
||||
* @property {String} sessionFrom 会话来源,openType="contact"时有效
|
||||
* @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
|
||||
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
|
||||
* @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
|
||||
* @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
|
||||
* @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
|
||||
*
|
||||
* @event {Function} select 点击ActionSheet列表项时触发
|
||||
* @event {Function} close 点击取消按钮时触发
|
||||
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
|
||||
* @event {Function} contact 客服消息回调,openType="contact"时有效
|
||||
* @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效
|
||||
* @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效
|
||||
* @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效
|
||||
* @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效
|
||||
* @example <uv-action-sheet ref="actionSheet" :actions="list" :title="title" ></uv-action-sheet>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-action-sheet",
|
||||
mixins: [openType, button, mpMixin , mixin, props],
|
||||
emits: ['close', 'select'],
|
||||
computed: {
|
||||
// 操作项目的样式
|
||||
itemStyle() {
|
||||
return (index) => {
|
||||
let style = {};
|
||||
if (this.actions[index].color) style.color = this.actions[index].color
|
||||
if (this.actions[index].fontSize) style.fontSize = this.$uv.addUnit(this.actions[index].fontSize)
|
||||
// 选项被禁用的样式
|
||||
if (this.actions[index].disabled) style.color = '#c0c4cc'
|
||||
return style;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.popup.open();
|
||||
},
|
||||
close() {
|
||||
this.$refs.popup.close();
|
||||
},
|
||||
popupChange(e) {
|
||||
if(!e.show) this.$emit('close');
|
||||
},
|
||||
// 点击取消按钮
|
||||
cancel() {
|
||||
this.close();
|
||||
},
|
||||
selectHandler(index) {
|
||||
const item = this.actions[index]
|
||||
if (item && !item.disabled && !item.loading) {
|
||||
this.$emit('select', item)
|
||||
if (this.closeOnClickAction) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
$show-reset-button: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
$uv-action-sheet-reset-button-width:100% !default;
|
||||
$uv-action-sheet-title-font-size: 16px !default;
|
||||
$uv-action-sheet-title-padding: 12px 30px !default;
|
||||
$uv-action-sheet-title-color: $uv-main-color !default;
|
||||
$uv-action-sheet-header-icon-wrap-right:15px !default;
|
||||
$uv-action-sheet-header-icon-wrap-top:15px !default;
|
||||
$uv-action-sheet-description-font-size:13px !default;
|
||||
$uv-action-sheet-description-color:14px !default;
|
||||
$uv-action-sheet-description-margin: 18px 15px !default;
|
||||
$uv-action-sheet-item-wrap-item-padding:15px !default;
|
||||
$uv-action-sheet-item-wrap-name-font-size:16px !default;
|
||||
$uv-action-sheet-item-wrap-subname-font-size:13px !default;
|
||||
$uv-action-sheet-item-wrap-subname-color: #c0c4cc !default;
|
||||
$uv-action-sheet-item-wrap-subname-margin-top:10px !default;
|
||||
$uv-action-sheet-cancel-text-font-size:16px !default;
|
||||
$uv-action-sheet-cancel-text-color:$uv-content-color !default;
|
||||
$uv-action-sheet-cancel-text-font-size:15px !default;
|
||||
$uv-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
|
||||
|
||||
.uv-reset-button {
|
||||
width: $uv-action-sheet-reset-button-width;
|
||||
}
|
||||
|
||||
.uv-action-sheet {
|
||||
text-align: center;
|
||||
&__header {
|
||||
position: relative;
|
||||
padding: $uv-action-sheet-title-padding;
|
||||
&__title {
|
||||
font-size: $uv-action-sheet-title-font-size;
|
||||
color: $uv-action-sheet-title-color;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__icon-wrap {
|
||||
position: absolute;
|
||||
right: $uv-action-sheet-header-icon-wrap-right;
|
||||
top: $uv-action-sheet-header-icon-wrap-top;
|
||||
}
|
||||
}
|
||||
|
||||
&__description {
|
||||
font-size: $uv-action-sheet-description-font-size;
|
||||
color: $uv-tips-color;
|
||||
margin: $uv-action-sheet-description-margin;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__item-wrap {
|
||||
|
||||
&__item {
|
||||
padding: $uv-action-sheet-item-wrap-item-padding;
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
&__name {
|
||||
font-size: $uv-action-sheet-item-wrap-name-font-size;
|
||||
color: $uv-main-color;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__subname {
|
||||
font-size: $uv-action-sheet-item-wrap-subname-font-size;
|
||||
color: $uv-action-sheet-item-wrap-subname-color;
|
||||
margin-top: $uv-action-sheet-item-wrap-subname-margin-top;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__cancel-text {
|
||||
font-size: $uv-action-sheet-cancel-text-font-size;
|
||||
color: $uv-action-sheet-cancel-text-color;
|
||||
text-align: center;
|
||||
padding: $uv-action-sheet-cancel-text-font-size;
|
||||
}
|
||||
|
||||
&--hover {
|
||||
background-color: $uv-action-sheet-cancel-text-hover-background-color;
|
||||
}
|
||||
}
|
||||
</style>
|
92
x_admin_app/uni_modules/uv-action-sheet/package.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"id": "uv-action-sheet",
|
||||
"displayName": "uv-action-sheet 底部操作菜单 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.2",
|
||||
"description": "该组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheet API,配置更加灵活,所有平台都表现一致。",
|
||||
"keywords": [
|
||||
"action-sheet",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"操作菜单",
|
||||
"菜单选择"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-popup",
|
||||
"uv-icon",
|
||||
"uv-line",
|
||||
"uv-loading-icon",
|
||||
"uv-gap"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
x_admin_app/uni_modules/uv-action-sheet/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## ActionSheet 操作菜单
|
||||
|
||||
> **组件名:uv-action-sheet**
|
||||
|
||||
本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。
|
||||
|
||||
本组件功能类似于uni的uni.showActionSheet API,配置更加灵活,所有平台都表现一致。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/actionSheet.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
10
x_admin_app/uni_modules/uv-album/changelog.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 1.0.4(2023-12-06)
|
||||
1. 阻止事件冒泡处理
|
||||
## 1.0.3(2023-10-23)
|
||||
1. 修复报错的BUG
|
||||
## 1.0.2(2023-10-23)
|
||||
1. 修复设置singleSize、multipleSize、space等值带单位,存在不显示的BUG
|
||||
## 1.0.1(2023-09-13)
|
||||
1. 添加依赖
|
||||
## 1.0.0(2023-08-30)
|
||||
1. 新增uv-album相册组件
|
@@ -0,0 +1,312 @@
|
||||
<template>
|
||||
<view class="uv-album">
|
||||
<view
|
||||
class="uv-album__row"
|
||||
ref="uv-album__row"
|
||||
v-for="(arr, index) in showUrls"
|
||||
:forComputedUse="albumWidth"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
class="uv-album__row__wrapper"
|
||||
v-for="(item, index1) in arr"
|
||||
:key="index1"
|
||||
:style="[imageStyle(index + 1, index1 + 1)]"
|
||||
@tap.stop="previewFullImage ? onPreviewTap(getSrc(item)) : ''"
|
||||
>
|
||||
<image
|
||||
:src="getSrc(item)"
|
||||
:mode="
|
||||
urls.length === 1
|
||||
? imageHeight > 0
|
||||
? singleMode
|
||||
: 'widthFix'
|
||||
: multipleMode
|
||||
"
|
||||
:style="[
|
||||
{
|
||||
width: imageWidth,
|
||||
height: imageHeight
|
||||
}
|
||||
]"
|
||||
></image>
|
||||
<view
|
||||
v-if="
|
||||
showMore &&
|
||||
urls.length > rowCount * showUrls.length &&
|
||||
index === showUrls.length - 1 &&
|
||||
index1 === showUrls[showUrls.length - 1].length - 1
|
||||
"
|
||||
class="uv-album__row__wrapper__text"
|
||||
>
|
||||
<uv-text
|
||||
:text="`+${urls.length - maxCount}`"
|
||||
color="#fff"
|
||||
:size="$uv.getPx(multipleSize) * 0.3"
|
||||
align="center"
|
||||
customStyle="justify-content: center"
|
||||
></uv-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
// #ifdef APP-NVUE
|
||||
// 由于weex为阿里的KPI业绩考核的产物,所以不支持百分比单位,这里需要通过dom查询组件的宽度
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* Album 相册
|
||||
* @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码
|
||||
* @tutorial https://www.uvui.cn/components/album.html
|
||||
* @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式
|
||||
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||
* @property {String | Number} singleSize 单图时,图片长边的长度 (默认 180 )
|
||||
* @property {String | Number} multipleSize 多图时,图片边长 (默认 70 )
|
||||
* @property {String | Number} space 多图时,图片水平和垂直之间的间隔 (默认 6 )
|
||||
* @property {String} singleMode 单图时,图片缩放裁剪的模式 (默认 'scaleToFill' )
|
||||
* @property {String} multipleMode 多图时,图片缩放裁剪的模式 (默认 'aspectFill' )
|
||||
* @property {String | Number} maxCount 取消按钮的提示文字 (默认 9 )
|
||||
* @property {Boolean} previewFullImage 是否可以预览图片 (默认 true )
|
||||
* @property {String | Number} rowCount 每行展示图片数量,如设置,singleSize和multipleSize将会无效 (默认 3 )
|
||||
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
|
||||
*
|
||||
* @event {Function} albumWidth 某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送 (回调参数 width )
|
||||
* @example <uv-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></uv-album>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-album',
|
||||
mixins: [mpMixin, mixin],
|
||||
emits: ['albumWidth'],
|
||||
props: {
|
||||
// 图片地址,Array<String>|Array<Object>形式
|
||||
urls: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||
keyName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 单图时,图片长边的长度
|
||||
singleSize: {
|
||||
type: [String, Number],
|
||||
default: 180
|
||||
},
|
||||
// 多图时,图片边长
|
||||
multipleSize: {
|
||||
type: [String, Number],
|
||||
default: 70
|
||||
},
|
||||
// 多图时,图片水平和垂直之间的间隔
|
||||
space: {
|
||||
type: [String, Number],
|
||||
default: 6
|
||||
},
|
||||
// 单图时,图片缩放裁剪的模式
|
||||
singleMode: {
|
||||
type: String,
|
||||
default: 'scaleToFill'
|
||||
},
|
||||
// 多图时,图片缩放裁剪的模式
|
||||
multipleMode: {
|
||||
type: String,
|
||||
default: 'aspectFill'
|
||||
},
|
||||
// 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
|
||||
maxCount: {
|
||||
type: [String, Number],
|
||||
default: 9
|
||||
},
|
||||
// 是否可以预览图片
|
||||
previewFullImage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 每行展示图片数量,如设置,singleSize和multipleSize将会无效
|
||||
rowCount: {
|
||||
type: [String, Number],
|
||||
default: 3
|
||||
},
|
||||
// 超出maxCount时是否显示查看更多的提示
|
||||
showMore: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
...uni.$uv?.props?.album
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 单图的宽度
|
||||
singleWidth: 0,
|
||||
// 单图的高度
|
||||
singleHeight: 0,
|
||||
// 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比
|
||||
singlePercent: 0.6
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
urls: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
if (newVal.length === 1) {
|
||||
this.getImageRect()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageStyle() {
|
||||
return (index1, index2) => {
|
||||
const { space, rowCount, multipleSize, urls } = this;
|
||||
const rowLen = this.showUrls.length;
|
||||
const allLen = this.urls.length;
|
||||
const style = {
|
||||
marginRight: this.$uv.addUnit(space),
|
||||
marginBottom: this.$uv.addUnit(space)
|
||||
}
|
||||
// 如果为最后一行,则每个图片都无需下边框
|
||||
if (index1 === rowLen) style.marginBottom = 0
|
||||
// 每行的最右边一张和总长度的最后一张无需右边框
|
||||
if (
|
||||
index2 === rowCount ||
|
||||
(index1 === rowLen &&
|
||||
index2 === this.showUrls[index1 - 1].length)
|
||||
)
|
||||
style.marginRight = 0
|
||||
return style
|
||||
}
|
||||
},
|
||||
// 将数组划分为二维数组
|
||||
showUrls() {
|
||||
const arr = []
|
||||
this.urls.map((item, index) => {
|
||||
// 限制最大展示数量
|
||||
if (index + 1 <= this.maxCount) {
|
||||
// 计算该元素为第几个素组内
|
||||
const itemIndex = Math.floor(index / this.rowCount)
|
||||
// 判断对应的索引是否存在
|
||||
if (!arr[itemIndex]) {
|
||||
arr[itemIndex] = []
|
||||
}
|
||||
arr[itemIndex].push(item)
|
||||
}
|
||||
})
|
||||
return arr
|
||||
},
|
||||
imageWidth() {
|
||||
return this.$uv.addUnit(
|
||||
this.urls.length === 1 ? this.singleWidth : this.multipleSize
|
||||
)
|
||||
},
|
||||
imageHeight() {
|
||||
return this.$uv.addUnit(
|
||||
this.urls.length === 1 ? this.singleHeight : this.multipleSize
|
||||
)
|
||||
},
|
||||
// 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
|
||||
// 因为用户在某些特殊的情况下,需要让文字与相册的宽度相等,所以这里事件的形式对外发送
|
||||
albumWidth() {
|
||||
let width = 0
|
||||
if (this.urls.length === 1) {
|
||||
width = this.singleWidth
|
||||
} else {
|
||||
width =
|
||||
this.showUrls[0].length * this.$uv.getPx(this.multipleSize) +
|
||||
this.$uv.getPx(this.space) * (this.showUrls[0].length - 1)
|
||||
}
|
||||
this.$emit('albumWidth', width)
|
||||
return width
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 预览图片
|
||||
onPreviewTap(url) {
|
||||
const urls = this.urls.map((item) => {
|
||||
return this.getSrc(item)
|
||||
})
|
||||
uni.previewImage({
|
||||
current: url,
|
||||
urls
|
||||
})
|
||||
},
|
||||
// 获取图片的路径
|
||||
getSrc(item) {
|
||||
return this.$uv.test.object(item) ?
|
||||
(this.keyName && item[this.keyName]) || item.src :
|
||||
item
|
||||
},
|
||||
// 单图时,获取图片的尺寸
|
||||
// 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸
|
||||
// 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent)
|
||||
getImageRect() {
|
||||
const src = this.getSrc(this.urls[0])
|
||||
uni.getImageInfo({
|
||||
src,
|
||||
success: (res) => {
|
||||
// 判断图片横向还是竖向展示方式
|
||||
const isHorizotal = res.width >= res.height
|
||||
this.singleWidth = isHorizotal ?
|
||||
this.singleSize :
|
||||
(res.width / res.height) * this.$uv.getPx(this.singleSize)
|
||||
this.singleHeight = !isHorizotal ?
|
||||
this.singleSize :
|
||||
(res.height / res.width) * this.singleWidth
|
||||
},
|
||||
fail: () => {
|
||||
this.getComponentWidth()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取组件的宽度
|
||||
async getComponentWidth() {
|
||||
// 延时一定时间,以获取dom尺寸
|
||||
await this.$uv.sleep(30)
|
||||
// #ifndef APP-NVUE
|
||||
this.$uGetRect('.uv-album__row').then((size) => {
|
||||
this.singleWidth = size.width * this.singlePercent
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
// 这里ref="uv-album__row"所在的标签为通过for循环出来,导致this.$refs['uv-album__row']是一个数组
|
||||
const ref = this.$refs['uv-album__row'][0]
|
||||
ref &&
|
||||
dom.getComponentRect(ref, (res) => {
|
||||
this.singleWidth = res.size.width * this.singlePercent
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
.uv-album {
|
||||
@include flex(column);
|
||||
&__row {
|
||||
@include flex(row);
|
||||
flex-wrap: wrap;
|
||||
&__wrapper {
|
||||
position: relative;
|
||||
&__text {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
@include flex(row);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
88
x_admin_app/uni_modules/uv-album/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uv-album",
|
||||
"displayName": "uv-album 相册 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.4",
|
||||
"description": "本组件提供一个类似相册的功能,让开发者开发起来更加得心应手,功能齐全,灵活配置可以,开箱即用。减少重复的模板代码",
|
||||
"keywords": [
|
||||
"album",
|
||||
"uv-ui",
|
||||
"uvui",
|
||||
"相册",
|
||||
"图片"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-text"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
x_admin_app/uni_modules/uv-album/readme.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Album 相册
|
||||
|
||||
> **组件名:uv-album**
|
||||
|
||||
本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。
|
||||
|
||||
功能齐全,灵活配置可以,开箱即用。减少重复的模板代码。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/album.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
7
x_admin_app/uni_modules/uv-alert/changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 1.0.2(2023-06-01)
|
||||
1. 修复点击触发两次实践的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-alert 警告提示组件
|
@@ -0,0 +1,45 @@
|
||||
export default {
|
||||
props: {
|
||||
// 显示文字
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 主题,success/warning/info/error
|
||||
type: {
|
||||
type: String,
|
||||
default: 'warning'
|
||||
},
|
||||
// 辅助性文字
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否可关闭
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示图标
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 浅或深色调,light-浅色,dark-深色
|
||||
effect: {
|
||||
type: String,
|
||||
default: 'light'
|
||||
},
|
||||
// 文字是否居中
|
||||
center: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 字体大小
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: 14
|
||||
},
|
||||
...uni.$uv?.props?.alert
|
||||
}
|
||||
}
|
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<uv-transition
|
||||
mode="fade"
|
||||
:show="show"
|
||||
>
|
||||
<view
|
||||
class="uv-alert"
|
||||
:class="[`uv-alert--${type}--${effect}`]"
|
||||
@tap.stop="clickHandler"
|
||||
:style="[$uv.addStyle(customStyle)]"
|
||||
>
|
||||
<view
|
||||
class="uv-alert__icon"
|
||||
v-if="showIcon"
|
||||
>
|
||||
<uv-icon
|
||||
:name="iconName"
|
||||
size="18"
|
||||
:color="iconColor"
|
||||
></uv-icon>
|
||||
</view>
|
||||
<view
|
||||
class="uv-alert__content"
|
||||
:style="[{
|
||||
paddingRight: closable ? '20px' : 0
|
||||
}]"
|
||||
>
|
||||
<text
|
||||
class="uv-alert__content__title"
|
||||
v-if="title"
|
||||
:style="[{
|
||||
fontSize: $uv.addUnit(fontSize),
|
||||
textAlign: center ? 'center' : 'left'
|
||||
}]"
|
||||
:class="[effect === 'dark' ? 'uv-alert__text--dark' : `uv-alert__text--${type}--light`]"
|
||||
>{{ title }}</text>
|
||||
<text
|
||||
class="uv-alert__content__desc"
|
||||
v-if="description"
|
||||
:style="[{
|
||||
fontSize: $uv.addUnit(fontSize),
|
||||
textAlign: center ? 'center' : 'left'
|
||||
}]"
|
||||
:class="[effect === 'dark' ? 'uv-alert__text--dark' : `uv-alert__text--${type}--light`]"
|
||||
>{{ description }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="uv-alert__close"
|
||||
v-if="closable"
|
||||
@tap.stop="closeHandler"
|
||||
>
|
||||
<uv-icon
|
||||
name="close"
|
||||
:color="iconColor"
|
||||
size="15"
|
||||
></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</uv-transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* Alert 警告提示
|
||||
* @description 警告提示,展现需要关注的信息。
|
||||
* @tutorial https://www.uvui.cn/components/alertTips.html
|
||||
*
|
||||
* @property {String} title 显示的文字
|
||||
* @property {String} type 使用预设的颜色 (默认 'warning' )
|
||||
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
|
||||
* @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
|
||||
* @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
|
||||
* @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
|
||||
* @property {Boolean} center 文字是否居中 (默认 false )
|
||||
* @property {String | Number} fontSize 字体大小 (默认 14 )
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @event {Function} click 点击组件时触发
|
||||
* @example <uv-alert :title="title" type = "warning" :closable="closable" :description = "description"></uv-alert>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-alert',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
emits: ['click'],
|
||||
data() {
|
||||
return {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconColor() {
|
||||
return this.effect === 'light' ? this.type : '#fff'
|
||||
},
|
||||
// 不同主题对应不同的图标
|
||||
iconName() {
|
||||
switch (this.type) {
|
||||
case 'success':
|
||||
return 'checkmark-circle-fill';
|
||||
break;
|
||||
case 'error':
|
||||
return 'close-circle-fill';
|
||||
break;
|
||||
case 'warning':
|
||||
return 'error-circle-fill';
|
||||
break;
|
||||
case 'info':
|
||||
return 'info-circle-fill';
|
||||
break;
|
||||
case 'primary':
|
||||
return 'more-circle-fill';
|
||||
break;
|
||||
default:
|
||||
return 'error-circle-fill';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 点击内容
|
||||
clickHandler() {
|
||||
this.$emit('click')
|
||||
},
|
||||
// 点击关闭按钮
|
||||
closeHandler() {
|
||||
this.show = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
.uv-alert {
|
||||
position: relative;
|
||||
background-color: $uv-primary;
|
||||
padding: 8px 10px;
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
&--primary--dark {
|
||||
background-color: $uv-primary;
|
||||
}
|
||||
|
||||
&--primary--light {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
&--error--dark {
|
||||
background-color: $uv-error;
|
||||
}
|
||||
|
||||
&--error--light {
|
||||
background-color: #FEF0F0;
|
||||
}
|
||||
|
||||
&--success--dark {
|
||||
background-color: $uv-success;
|
||||
}
|
||||
|
||||
&--success--light {
|
||||
background-color: #f5fff0;
|
||||
}
|
||||
|
||||
&--warning--dark {
|
||||
background-color: $uv-warning;
|
||||
}
|
||||
|
||||
&--warning--light {
|
||||
background-color: #FDF6EC;
|
||||
}
|
||||
|
||||
&--info--dark {
|
||||
background-color: $uv-info;
|
||||
}
|
||||
|
||||
&--info--light {
|
||||
background-color: #f4f4f5;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&__content {
|
||||
@include flex(column);
|
||||
flex: 1;
|
||||
|
||||
&__title {
|
||||
color: $uv-main-color;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
color: $uv-main-color;
|
||||
font-size: 14px;
|
||||
flex-wrap: wrap;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&__title--dark,
|
||||
&__desc--dark {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
&__text--primary--light,
|
||||
&__text--primary--light {
|
||||
color: $uv-primary;
|
||||
}
|
||||
|
||||
&__text--success--light,
|
||||
&__text--success--light {
|
||||
color: $uv-success;
|
||||
}
|
||||
|
||||
&__text--warning--light,
|
||||
&__text--warning--light {
|
||||
color: $uv-warning;
|
||||
}
|
||||
|
||||
&__text--error--light,
|
||||
&__text--error--light {
|
||||
color: $uv-error;
|
||||
}
|
||||
|
||||
&__text--info--light,
|
||||
&__text--info--light {
|
||||
color: $uv-info;
|
||||
}
|
||||
|
||||
&__close {
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
88
x_admin_app/uni_modules/uv-alert/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uv-alert",
|
||||
"displayName": "uv-alert 警告提示 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.2",
|
||||
"description": "uv-alert 警告提示,展现需要关注的信息。灵活配置,功能齐全,兼容全端",
|
||||
"keywords": [
|
||||
"alert",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"警告提示"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-transition",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
x_admin_app/uni_modules/uv-alert/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## Alert 警告提示
|
||||
|
||||
> **组件名:uv-alert**
|
||||
|
||||
警告提示,展现需要关注的信息。
|
||||
|
||||
当某个页面需要向用户显示警告的信息时。
|
||||
|
||||
非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/alert.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
13
x_admin_app/uni_modules/uv-avatar/changelog.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 1.0.5(2023-12-06)
|
||||
1. 优化
|
||||
## 1.0.4(2023-12-06)
|
||||
1. 优化
|
||||
## 1.0.3(2023-12-06)
|
||||
1. 阻止事件冒泡处理,单个头像模式
|
||||
## 1.0.2(2023-12-06)
|
||||
1. 阻止事件冒泡处理
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-avatar 头像组件
|
@@ -0,0 +1,53 @@
|
||||
export default {
|
||||
props: {
|
||||
// 头像图片组
|
||||
urls: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 最多展示的头像数量
|
||||
maxCount: {
|
||||
type: [String, Number],
|
||||
default: 5
|
||||
},
|
||||
// 头像形状
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'circle'
|
||||
},
|
||||
// 图片裁剪模式
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'scaleToFill'
|
||||
},
|
||||
// 超出maxCount时是否显示查看更多的提示
|
||||
showMore: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 头像大小
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 40
|
||||
},
|
||||
// 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||
keyName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 头像之间的遮挡比例
|
||||
gap: {
|
||||
type: [String, Number],
|
||||
validator(value) {
|
||||
return value >= 0 && value <= 1
|
||||
},
|
||||
default: 0.5
|
||||
},
|
||||
// 需额外显示的值
|
||||
extraValue: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
...uni.$uv?.props?.avatarGroup
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<view class="uv-avatar-group">
|
||||
<view
|
||||
class="uv-avatar-group__item"
|
||||
v-for="(item, index) in showUrl"
|
||||
:key="index"
|
||||
:style="{
|
||||
marginLeft: index === 0 ? 0 : $uv.addUnit(-size * gap)
|
||||
}"
|
||||
>
|
||||
<uv-avatar
|
||||
:size="size"
|
||||
:shape="shape"
|
||||
:mode="mode"
|
||||
:src="$uv.test.object(item) ? keyName && item[keyName] || item.url : item"
|
||||
></uv-avatar>
|
||||
<view
|
||||
class="uv-avatar-group__item__show-more"
|
||||
v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
|
||||
@tap="clickHandler"
|
||||
>
|
||||
<uv-text
|
||||
color="#ffffff"
|
||||
:size="size * 0.4"
|
||||
:text="`+${extraValue || urls.length - showUrl.length}`"
|
||||
align="center"
|
||||
customStyle="justify-content: center"
|
||||
></uv-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* AvatarGroup 头像组
|
||||
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
|
||||
* @tutorial https://www.uvui.cn/components/avatar.html
|
||||
*
|
||||
* @property {Array} urls 头像图片组 (默认 [] )
|
||||
* @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
|
||||
* @property {String} shape 头像形状( 'circle' (默认) | 'square' )
|
||||
* @property {String} mode 图片裁剪模式(默认 'scaleToFill' )
|
||||
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
|
||||
* @property {String | Number} size 头像大小 (默认 40 )
|
||||
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||
* @property {String | Number} gap 头像之间的遮挡比例(0.4代表遮挡40%) (默认 0.5 )
|
||||
* @property {String | Number} extraValue 需额外显示的值
|
||||
* @event {Function} showMore 头像组更多点击
|
||||
* @example <uv-avatar-group:urls="urls" size="35" gap="0.4" ></uv-avatar-group:urls=>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-avatar-group',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showUrl() {
|
||||
return this.urls.slice(0, this.maxCount)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickHandler() {
|
||||
this.$emit('showMore')
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
|
||||
.uv-avatar-group {
|
||||
@include flex;
|
||||
|
||||
&__item {
|
||||
margin-left: -10px;
|
||||
position: relative;
|
||||
|
||||
&--no-indent {
|
||||
// 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&__show-more {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,80 @@
|
||||
import { range } from '@/uni_modules/uv-ui-tools/libs/function/test.js'
|
||||
export default {
|
||||
props: {
|
||||
// 头像图片路径(不能为相对路径)
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 头像形状,circle-圆形,square-方形
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'circle'
|
||||
},
|
||||
// 头像尺寸
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 40
|
||||
},
|
||||
// 裁剪模式
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'scaleToFill'
|
||||
},
|
||||
// 显示的文字
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 背景色
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#c0c4cc'
|
||||
},
|
||||
// 文字颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
// 文字大小
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: 18
|
||||
},
|
||||
// 显示的图标
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 显示小程序头像,只对百度,微信,QQ小程序有效
|
||||
mpAvatar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否使用随机背景色
|
||||
randomBgColor: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 加载失败的默认头像(组件有内置默认图片)
|
||||
defaultUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
|
||||
colorIndex: {
|
||||
type: [String, Number],
|
||||
// 校验参数规则,索引在0-19之间
|
||||
validator(n) {
|
||||
return range(n, [0, 19]) || n === ''
|
||||
},
|
||||
default: ''
|
||||
},
|
||||
// 组件标识符
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.avatar
|
||||
}
|
||||
}
|
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-avatar"
|
||||
:class="[`uv-avatar--${shape}`]"
|
||||
:style="[{
|
||||
backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : $uv.random(0, 19)] : bgColor) : 'transparent',
|
||||
width: $uv.addUnit(size),
|
||||
height: $uv.addUnit(size),
|
||||
}, $uv.addStyle(customStyle)]"
|
||||
@tap="clickHandler"
|
||||
>
|
||||
<slot>
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
|
||||
<open-data
|
||||
v-if="mpAvatar && allowMp"
|
||||
type="userAvatarUrl"
|
||||
:style="[{
|
||||
width: $uv.addUnit(size),
|
||||
height: $uv.addUnit(size)
|
||||
}]"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU -->
|
||||
<template v-if="mpAvatar && allowMp"></template>
|
||||
<!-- #endif -->
|
||||
<uv-icon
|
||||
v-else-if="icon"
|
||||
:name="icon"
|
||||
:size="fontSize"
|
||||
:color="color"
|
||||
></uv-icon>
|
||||
<uv-text
|
||||
v-else-if="text"
|
||||
:text="text"
|
||||
:size="fontSize"
|
||||
:color="color"
|
||||
align="center"
|
||||
customStyle="justify-content: center"
|
||||
></uv-text>
|
||||
<image
|
||||
class="uv-avatar__image"
|
||||
v-else
|
||||
:class="[`uv-avatar__image--${shape}`]"
|
||||
:src="avatarUrl || defaultUrl"
|
||||
:mode="mode"
|
||||
@error="errorHandler"
|
||||
:style="[{
|
||||
width: $uv.addUnit(size),
|
||||
height: $uv.addUnit(size)
|
||||
}]"
|
||||
></image>
|
||||
</slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
const base64Avatar =
|
||||
"data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
|
||||
/**
|
||||
* Avatar 头像
|
||||
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
|
||||
* @tutorial https://www.uvui.cn/components/avatar.html
|
||||
*
|
||||
* @property {String} src 头像路径,如加载失败,将会显示默认头像(不能为相对路径)
|
||||
* @property {String} shape 头像形状 ( circle (默认) | square)
|
||||
* @property {String | Number} size 头像尺寸,可以为指定字符串(large, default, mini),或者数值 (默认 40 )
|
||||
* @property {String} mode 头像图片的裁剪类型,与uni的image组件的mode参数一致,如效果达不到需求,可尝试传widthFix值 (默认 'scaleToFill' )
|
||||
* @property {String} text 用文字替代图片,级别优先于src
|
||||
* @property {String} bgColor 背景颜色,一般显示文字时用 (默认 '#c0c4cc' )
|
||||
* @property {String} color 文字颜色 (默认 '#ffffff' )
|
||||
* @property {String | Number} fontSize 文字大小 (默认 18 )
|
||||
* @property {String} icon 显示的图标
|
||||
* @property {Boolean} mpAvatar 显示小程序头像,只对百度,微信,QQ小程序有效 (默认 false )
|
||||
* @property {Boolean} randomBgColor 是否使用随机背景色 (默认 false )
|
||||
* @property {String} defaultUrl 加载失败的默认头像(组件有内置默认图片)
|
||||
* @property {String | Number} colorIndex 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
|
||||
* @property {String} name 组件标识符 (默认 'level' )
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
*
|
||||
* @event {Function} click 点击组件时触发 index: 用户传递的标识符
|
||||
* @example <uv-avatar :src="src" mode="square"></uv-avatar>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-avatar',
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
// 如果配置randomBgColor参数为true,在图标或者文字的模式下,会随机从中取出一个颜色值当做背景色
|
||||
colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2',
|
||||
'#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee',
|
||||
'#73d1f1',
|
||||
'#80a7dc'
|
||||
],
|
||||
avatarUrl: this.src,
|
||||
allowMp: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听头像src的变化,赋值给内部的avatarUrl变量,因为图片加载失败时,需要修改图片的src为默认值
|
||||
// 而组件内部不能直接修改props的值,所以需要一个中间变量
|
||||
src: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.avatarUrl = newVal
|
||||
// 如果没有传src,则主动触发error事件,用于显示默认的头像,否则src为''空字符等的时候,会无内容展示
|
||||
if(!newVal) {
|
||||
this.errorHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageStyle() {
|
||||
const style = {}
|
||||
return style
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 目前只有这几个小程序平台具有open-data标签
|
||||
// 其他平台可以通过uni.getUserInfo类似接口获取信息,但是需要弹窗授权(首次),不合符组件逻辑
|
||||
// 故目前自动获取小程序头像只支持这几个平台
|
||||
// #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU
|
||||
this.allowMp = true
|
||||
// #endif
|
||||
},
|
||||
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
|
||||
isImg() {
|
||||
return this.src.indexOf('/') !== -1
|
||||
},
|
||||
// 图片加载时失败时触发
|
||||
errorHandler() {
|
||||
this.avatarUrl = this.defaultUrl || base64Avatar
|
||||
},
|
||||
clickHandler() {
|
||||
this.$emit('click', this.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
|
||||
.uv-avatar {
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&--circle {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
&--square {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&__image {
|
||||
&--circle {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
&--square {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
89
x_admin_app/uni_modules/uv-avatar/package.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"id": "uv-avatar",
|
||||
"displayName": "uv-avatar 头像 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.5",
|
||||
"description": "uv-avatar 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。",
|
||||
"keywords": [
|
||||
"uv-avatar",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"avatar",
|
||||
"头像"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon",
|
||||
"uv-text"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
x_admin_app/uni_modules/uv-avatar/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Avatar 头像
|
||||
|
||||
> **组件名:uv-avatar**
|
||||
|
||||
本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/avatar.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
8
x_admin_app/uni_modules/uv-back-top/changelog.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## 1.0.2(2023-07-03)
|
||||
1. 优化插槽自定义内容部分
|
||||
2. 增加backToTop方法说明
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-back-top 返回顶部
|
@@ -0,0 +1,58 @@
|
||||
export default {
|
||||
props: {
|
||||
// 返回顶部的形状,circle-圆形,square-方形
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'circle'
|
||||
},
|
||||
// 自定义图标
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'arrow-upward'
|
||||
},
|
||||
// 提示文字
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 返回顶部滚动时间
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 100
|
||||
},
|
||||
// 滚动距离
|
||||
scrollTop: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 距离顶部多少距离显示,单位px
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: 400
|
||||
},
|
||||
// 返回顶部按钮到底部的距离,单位px
|
||||
bottom: {
|
||||
type: [String, Number],
|
||||
default: 100
|
||||
},
|
||||
// 返回顶部按钮到右边的距离,单位px
|
||||
right: {
|
||||
type: [String, Number],
|
||||
default: 20
|
||||
},
|
||||
// 层级
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 9
|
||||
},
|
||||
// 图标的样式,对象形式
|
||||
iconStyle: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
color: '#909399',
|
||||
fontSize: '19px'
|
||||
})
|
||||
},
|
||||
...uni.$uv?.props?.backtop
|
||||
}
|
||||
}
|
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<uv-transition mode="fade" :customStyle="backTopStyle" :show="show">
|
||||
<slot>
|
||||
<view class="uv-back-top" :style="[contentStyle]" @click="backToTop">
|
||||
<uv-icon :name="icon" :custom-style="iconStyle"></uv-icon>
|
||||
<text v-if="text" class="uv-back-top__text">{{text}}</text>
|
||||
</view>
|
||||
</slot>
|
||||
</uv-transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
/**
|
||||
* backTop 返回顶部
|
||||
* @description 本组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
|
||||
* @tutorial https://www.uvui.cn/components/backTop.html
|
||||
* @property {String} mode 返回顶部的形状,circle-圆形,square-方形 (默认 'circle' )
|
||||
* @property {String} icon 自定义图标 (默认 'arrow-upward' ) 见官方文档示例
|
||||
* @property {String} text 提示文字
|
||||
* @property {String | Number} duration 返回顶部滚动时间 (默认 100)
|
||||
* @property {String | Number} scrollTop 滚动距离 (默认 0 )
|
||||
* @property {String | Number} top 距离顶部多少距离显示,单位px (默认 400 )
|
||||
* @property {String | Number} bottom 返回顶部按钮到底部的距离,单位px (默认 100 )
|
||||
* @property {String | Number} right 返回顶部按钮到右边的距离,单位px (默认 20 )
|
||||
* @property {String | Number} zIndex 层级 (默认 9 )
|
||||
* @property {Object<Object>} iconStyle 图标的样式,对象形式 (默认 {color: '#909399',fontSize: '19px'})
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
*
|
||||
* @example <uv-back-top :scrollTop="scrollTop"></uv-back-top>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-back-top',
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
computed: {
|
||||
backTopStyle() {
|
||||
// 动画组件样式
|
||||
const style = {
|
||||
bottom: this.$uv.addUnit(this.bottom),
|
||||
right: this.$uv.addUnit(this.right),
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
position: 'fixed',
|
||||
zIndex: 10,
|
||||
}
|
||||
return style
|
||||
},
|
||||
show() {
|
||||
return this.$uv.getPx(this.scrollTop) > this.$uv.getPx(this.top)
|
||||
},
|
||||
contentStyle() {
|
||||
const style = {}
|
||||
let radius = 0
|
||||
// 是否圆形
|
||||
if (this.mode === 'circle') {
|
||||
radius = '100px'
|
||||
} else {
|
||||
radius = '4px'
|
||||
}
|
||||
// 为了兼容安卓nvue,只能这么分开写
|
||||
style.borderTopLeftRadius = radius
|
||||
style.borderTopRightRadius = radius
|
||||
style.borderBottomLeftRadius = radius
|
||||
style.borderBottomRightRadius = radius
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backToTop() {
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.$parent.$refs['uv-back-top']) {
|
||||
this.$uv.error(`nvue页面需要给页面最外层元素设置"ref='uv-back-top'`)
|
||||
}
|
||||
dom.scrollToElement(this.$parent.$refs['uv-back-top'], {
|
||||
offset: 0
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: this.duration
|
||||
});
|
||||
// #endif
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
$uv-back-top-flex: 1 !default;
|
||||
$uv-back-top-height: 100% !default;
|
||||
$uv-back-top-background-color: #E1E1E1 !default;
|
||||
$uv-back-top-tips-font-size: 12px !default;
|
||||
.uv-back-top {
|
||||
@include flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex: $uv-back-top-flex;
|
||||
height: $uv-back-top-height;
|
||||
justify-content: center;
|
||||
background-color: $uv-back-top-background-color;
|
||||
&__tips {
|
||||
font-size: $uv-back-top-tips-font-size;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
</style>
|
89
x_admin_app/uni_modules/uv-back-top/package.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"id": "uv-back-top",
|
||||
"displayName": "uv-back-top 返回顶部 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.2",
|
||||
"description": "返回顶部 组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。",
|
||||
"keywords": [
|
||||
"uv-back-top",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"avatar",
|
||||
"返回顶部"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon",
|
||||
"uv-transition"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
x_admin_app/uni_modules/uv-back-top/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## BackTop 返回顶部
|
||||
|
||||
> **组件名:uv-back-top**
|
||||
|
||||
该组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/backTop.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
7
x_admin_app/uni_modules/uv-badge/changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 1.0.2(2023-06-04)
|
||||
1. 修复type等属性为null的时候不显示徽标的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-badge 徽标数,数字角标
|
@@ -0,0 +1,73 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否显示圆点
|
||||
isDot: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 显示的内容
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
// 是否显示
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 最大值,超过最大值会显示 '{max}+'
|
||||
max: {
|
||||
type: [Number, String],
|
||||
default: 999
|
||||
},
|
||||
// 主题类型,error|warning|success|primary
|
||||
type: {
|
||||
type: [String,undefined,null],
|
||||
default: 'error'
|
||||
},
|
||||
// 当数值为 0 时,是否展示 Badge
|
||||
showZero: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 背景颜色,优先级比type高,如设置,type参数会失效
|
||||
bgColor: {
|
||||
type: [String, null],
|
||||
default: null
|
||||
},
|
||||
// 字体颜色
|
||||
color: {
|
||||
type: [String, null],
|
||||
default: null
|
||||
},
|
||||
// 徽标形状,circle-四角均为圆角,horn-左下角为直角
|
||||
shape: {
|
||||
type: [String,undefined,null],
|
||||
default: 'circle'
|
||||
},
|
||||
// 设置数字的显示方式,overflow|ellipsis|limit
|
||||
// overflow会根据max字段判断,超出显示`${max}+`
|
||||
// ellipsis会根据max判断,超出显示`${max}...`
|
||||
// limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
|
||||
numberType: {
|
||||
type: [String,undefined,null],
|
||||
default: 'overflow'
|
||||
},
|
||||
// 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
|
||||
offset: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 是否反转背景和字体颜色
|
||||
inverted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否绝对定位
|
||||
absolute: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.badge
|
||||
}
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<text
|
||||
v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
|
||||
:class="[isDot ? 'uv-badge--dot' : 'uv-badge--not-dot', inverted && 'uv-badge--inverted', shape === 'horn' && 'uv-badge--horn', `uv-badge--${propsType}${inverted ? '--inverted' : ''}`]"
|
||||
:style="[$uv.addStyle(customStyle), badgeStyle]"
|
||||
class="uv-badge"
|
||||
>{{ isDot ? '' :showValue }}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* badge 徽标数
|
||||
* @description 该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
|
||||
* @tutorial https://www.uvui.cn/components/badge.html
|
||||
*
|
||||
* @property {Boolean} isDot 是否显示圆点 (默认 false )
|
||||
* @property {String | Number} value 显示的内容
|
||||
* @property {Boolean} show 是否显示 (默认 true )
|
||||
* @property {String | Number} max 最大值,超过最大值会显示 '{max}+' (默认999)
|
||||
* @property {String} type 主题类型,error|warning|success|primary (默认 'error' )
|
||||
* @property {Boolean} showZero 当数值为 0 时,是否展示 Badge (默认 false )
|
||||
* @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效
|
||||
* @property {String} color 字体颜色 (默认 '#ffffff' )
|
||||
* @property {String} shape 徽标形状,circle-四角均为圆角,horn-左下角为直角 (默认 'circle' )
|
||||
* @property {String} numberType 设置数字的显示方式,overflow|ellipsis|limit (默认 'overflow' )
|
||||
* @property {Array}} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
|
||||
* @property {Boolean} inverted 是否反转背景和字体颜色(默认 false )
|
||||
* @property {Boolean} absolute 是否绝对定位(默认 false )
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @example <uv-badge :type="type" :count="count"></uv-badge>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-badge',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
computed: {
|
||||
// 是否将badge中心与父组件右上角重合
|
||||
boxStyle() {
|
||||
let style = {};
|
||||
return style;
|
||||
},
|
||||
// 整个组件的样式
|
||||
badgeStyle() {
|
||||
const style = {}
|
||||
if(this.color) {
|
||||
style.color = this.color
|
||||
}
|
||||
if (this.bgColor && !this.inverted) {
|
||||
style.backgroundColor = this.bgColor
|
||||
}
|
||||
if (this.absolute) {
|
||||
style.position = 'absolute'
|
||||
// 如果有设置offset参数
|
||||
if(this.offset.length) {
|
||||
// top和right分为为offset的第一个和第二个值,如果没有第二个值,则right等于top
|
||||
const top = this.offset[0]
|
||||
const right = this.offset[1] || top
|
||||
style.top = this.$uv.addUnit(top)
|
||||
style.right = this.$uv.addUnit(right)
|
||||
}
|
||||
}
|
||||
return style
|
||||
},
|
||||
showValue() {
|
||||
switch (this.numberType) {
|
||||
case "overflow":
|
||||
return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
|
||||
break;
|
||||
case "ellipsis":
|
||||
return Number(this.value) > Number(this.max) ? "..." : this.value
|
||||
break;
|
||||
case "limit":
|
||||
return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
|
||||
Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
|
||||
1e3 * 100) / 100 + "k" : this.value
|
||||
break;
|
||||
default:
|
||||
return Number(this.value)
|
||||
}
|
||||
},
|
||||
propsType(){
|
||||
return this.type || 'error'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
$uv-badge-primary: $uv-primary !default;
|
||||
$uv-badge-error: $uv-error !default;
|
||||
$uv-badge-success: $uv-success !default;
|
||||
$uv-badge-info: $uv-info !default;
|
||||
$uv-badge-warning: $uv-warning !default;
|
||||
$uv-badge-dot-radius: 100px !default;
|
||||
$uv-badge-dot-size: 8px !default;
|
||||
$uv-badge-dot-right: 4px !default;
|
||||
$uv-badge-dot-top: 0 !default;
|
||||
$uv-badge-text-font-size: 11px !default;
|
||||
$uv-badge-text-right: 10px !default;
|
||||
$uv-badge-text-padding: 2px 5px !default;
|
||||
$uv-badge-text-align: center !default;
|
||||
$uv-badge-text-color: #FFFFFF !default;
|
||||
|
||||
.uv-badge {
|
||||
border-top-right-radius: $uv-badge-dot-radius;
|
||||
border-top-left-radius: $uv-badge-dot-radius;
|
||||
border-bottom-left-radius: $uv-badge-dot-radius;
|
||||
border-bottom-right-radius: $uv-badge-dot-radius;
|
||||
@include flex;
|
||||
line-height: $uv-badge-text-font-size;
|
||||
text-align: $uv-badge-text-align;
|
||||
font-size: $uv-badge-text-font-size;
|
||||
color: $uv-badge-text-color;
|
||||
|
||||
&--dot {
|
||||
height: $uv-badge-dot-size;
|
||||
width: $uv-badge-dot-size;
|
||||
}
|
||||
|
||||
&--inverted {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&--not-dot {
|
||||
padding: $uv-badge-text-padding;
|
||||
}
|
||||
|
||||
&--horn {
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
background-color: $uv-badge-primary;
|
||||
}
|
||||
|
||||
&--primary--inverted {
|
||||
color: $uv-badge-primary;
|
||||
}
|
||||
|
||||
&--error {
|
||||
background-color: $uv-badge-error;
|
||||
}
|
||||
|
||||
&--error--inverted {
|
||||
color: $uv-badge-error;
|
||||
}
|
||||
|
||||
&--success {
|
||||
background-color: $uv-badge-success;
|
||||
}
|
||||
|
||||
&--success--inverted {
|
||||
color: $uv-badge-success;
|
||||
}
|
||||
|
||||
&--info {
|
||||
background-color: $uv-badge-info;
|
||||
}
|
||||
|
||||
&--info--inverted {
|
||||
color: $uv-badge-info;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background-color: $uv-badge-warning;
|
||||
}
|
||||
|
||||
&--warning--inverted {
|
||||
color: $uv-badge-warning;
|
||||
}
|
||||
}
|
||||
</style>
|
87
x_admin_app/uni_modules/uv-badge/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uv-badge",
|
||||
"displayName": "uv-badge 徽标数,数字角标 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.2",
|
||||
"description": "徽标数一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。",
|
||||
"keywords": [
|
||||
"uv-badge",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"徽标数",
|
||||
"数字角标"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
x_admin_app/uni_modules/uv-badge/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Badge 徽标数
|
||||
|
||||
> **组件名:uv-badge**
|
||||
|
||||
该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/badge.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
33
x_admin_app/uni_modules/uv-button/changelog.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## 1.0.15(2023-12-20)
|
||||
1. 优化
|
||||
## 1.0.14(2023-12-06)
|
||||
1. 优化
|
||||
## 1.0.13(2023-12-06)
|
||||
1. 阻止事件冒泡处理
|
||||
## 1.0.12(2023-10-19)
|
||||
1. 增加后置插槽
|
||||
## 1.0.11(2023-09-21)
|
||||
1. 修复通过customStyle修改按钮宽度,组件中最外层节点不改变的问题
|
||||
## 1.0.10(2023-09-15)
|
||||
1. 按钮支持open-type="agreePrivacyAuthorization"
|
||||
## 1.0.9(2023-09-11)
|
||||
1. 增加参数iconSize,用于控制图标的大小
|
||||
## 1.0.8(2023-09-10)
|
||||
1. 修复多个按钮在一行宽度不正常的BUG
|
||||
## 1.0.7(2023-09-07)
|
||||
1. 修复warning颜色对应错误的BUG
|
||||
## 1.0.6(2023-07-25)
|
||||
1. 增加customTextStyle属性,方便自定义文字样式
|
||||
## 1.0.5(2023-07-20)
|
||||
1. 解决微信小程序动态设置hover-class点击态不消失的BUG
|
||||
## 1.0.4(2023-06-29)
|
||||
1. 修改上次更新出现nvue报错异常
|
||||
## 1.0.3(2023-06-28)
|
||||
修复:设置open-type="chooseAvatar"等值不生效的BUG
|
||||
## 1.0.2(2023-06-01)
|
||||
1. 修复按钮点击触发两次的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-button 按钮
|
@@ -0,0 +1,46 @@
|
||||
$uv-button-active-opacity:0.75 !default;
|
||||
$uv-button-loading-text-margin-left:4px !default;
|
||||
$uv-button-text-color: #FFFFFF !default;
|
||||
$uv-button-text-plain-error-color:$uv-error !default;
|
||||
$uv-button-text-plain-warning-color:$uv-warning !default;
|
||||
$uv-button-text-plain-success-color:$uv-success !default;
|
||||
$uv-button-text-plain-info-color:$uv-info !default;
|
||||
$uv-button-text-plain-primary-color:$uv-primary !default;
|
||||
.uv-button {
|
||||
&--active {
|
||||
opacity: $uv-button-active-opacity;
|
||||
}
|
||||
|
||||
&--active--plain {
|
||||
background-color: rgb(217, 217, 217);
|
||||
}
|
||||
|
||||
&__loading-text {
|
||||
margin-left:$uv-button-loading-text-margin-left;
|
||||
}
|
||||
|
||||
&__text,
|
||||
&__loading-text {
|
||||
color:$uv-button-text-color;
|
||||
}
|
||||
|
||||
&__text--plain--error {
|
||||
color:$uv-button-text-plain-error-color;
|
||||
}
|
||||
|
||||
&__text--plain--warning {
|
||||
color:$uv-button-text-plain-warning-color;
|
||||
}
|
||||
|
||||
&__text--plain--success{
|
||||
color:$uv-button-text-plain-success-color;
|
||||
}
|
||||
|
||||
&__text--plain--info {
|
||||
color:$uv-button-text-plain-info-color;
|
||||
}
|
||||
|
||||
&__text--plain--primary {
|
||||
color:$uv-button-text-plain-primary-color;
|
||||
}
|
||||
}
|
163
x_admin_app/uni_modules/uv-button/components/uv-button/props.js
Normal file
@@ -0,0 +1,163 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否细边框
|
||||
hairline: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 按钮的预置样式,info,primary,error,warning,success
|
||||
type: {
|
||||
type: String,
|
||||
default: 'info'
|
||||
},
|
||||
// 按钮尺寸,large,normal,small,mini
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
},
|
||||
// 按钮形状,circle(两边为半圆),square(带圆角)
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'square'
|
||||
},
|
||||
// 按钮是否镂空
|
||||
plain: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否禁止状态
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否加载中
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 加载中提示文字
|
||||
loadingText: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 加载状态图标类型
|
||||
loadingMode: {
|
||||
type: String,
|
||||
default: 'spinner'
|
||||
},
|
||||
// 加载图标大小
|
||||
loadingSize: {
|
||||
type: [String, Number],
|
||||
default: 14
|
||||
},
|
||||
// 开放能力,具体请看uniapp稳定关于button组件部分说明
|
||||
// https://uniapp.dcloud.io/component/button
|
||||
openType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
|
||||
// 取值为submit(提交表单),reset(重置表单)
|
||||
formType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
|
||||
// 只微信小程序、QQ小程序有效
|
||||
appParameter: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
|
||||
hoverStopPropagation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
|
||||
lang: {
|
||||
type: String,
|
||||
default: 'en'
|
||||
},
|
||||
// 会话来源,open-type="contact"时有效。只微信小程序有效
|
||||
sessionFrom: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 会话内消息卡片标题,open-type="contact"时有效
|
||||
// 默认当前标题,只微信小程序有效
|
||||
sendMessageTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
|
||||
// 默认当前分享路径,只微信小程序有效
|
||||
sendMessagePath: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 会话内消息卡片图片,open-type="contact"时有效
|
||||
// 默认当前页面截图,只微信小程序有效
|
||||
sendMessageImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
|
||||
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效
|
||||
showMessageCard: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
|
||||
dataName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 节流,一定时间内只能触发一次
|
||||
throttleTime: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 按住后多久出现点击态,单位毫秒
|
||||
hoverStartTime: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 手指松开后点击态保留时间,单位毫秒
|
||||
hoverStayTime: {
|
||||
type: [String, Number],
|
||||
default: 200
|
||||
},
|
||||
// 按钮文字,之所以通过props传入,是因为slot传入的话
|
||||
// nvue中无法控制文字的样式
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 按钮图标
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 按钮图标大小
|
||||
iconSize: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 按钮图标颜色
|
||||
iconColor: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
// 按钮颜色,支持传入linear-gradient渐变色
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 自定义按钮文本样式
|
||||
customTextStyle: {
|
||||
type: [Object,String],
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.button
|
||||
}
|
||||
}
|
@@ -0,0 +1,528 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-button-wrapper"
|
||||
:style="[btnWrapperStyle]"
|
||||
>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<!-- #ifdef MP -->
|
||||
<!-- 为了解决微信小程序动态设置hover-class点击态不消失的BUG -->
|
||||
<view class="uv-button-wrapper--dis" v-if="disabled || loading"></view>
|
||||
<button
|
||||
:hover-start-time="Number(hoverStartTime)"
|
||||
:hover-stay-time="Number(hoverStayTime)"
|
||||
:form-type="formType"
|
||||
:open-type="openType"
|
||||
:app-parameter="appParameter"
|
||||
:hover-stop-propagation="hoverStopPropagation"
|
||||
:send-message-title="sendMessageTitle"
|
||||
:send-message-path="sendMessagePath"
|
||||
:lang="lang"
|
||||
:data-name="dataName"
|
||||
:session-from="sessionFrom"
|
||||
:send-message-img="sendMessageImg"
|
||||
:show-message-card="showMessageCard"
|
||||
@getphonenumber="onGetPhoneNumber"
|
||||
@getuserinfo="onGetUserInfo"
|
||||
@error="onError"
|
||||
@opensetting="onOpenSetting"
|
||||
@launchapp="onLaunchApp"
|
||||
@contact="onContact"
|
||||
@chooseavatar="onChooseavatar"
|
||||
@agreeprivacyauthorization="onAgreeprivacyauthorization"
|
||||
@addgroupapp="onAddgroupapp"
|
||||
@chooseaddress="onChooseaddress"
|
||||
@subscribe="onSubscribe"
|
||||
@login="onLogin"
|
||||
@im="onIm"
|
||||
hover-class="uv-button--active"
|
||||
class="uv-button uv-reset-button"
|
||||
:style="[baseColor, $uv.addStyle(customStyle)]"
|
||||
@tap="clickHandler"
|
||||
:class="bemClass"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP -->
|
||||
<button
|
||||
:hover-start-time="Number(hoverStartTime)"
|
||||
:hover-stay-time="Number(hoverStayTime)"
|
||||
:form-type="formType"
|
||||
:open-type="openType"
|
||||
:app-parameter="appParameter"
|
||||
:hover-stop-propagation="hoverStopPropagation"
|
||||
:send-message-title="sendMessageTitle"
|
||||
:send-message-path="sendMessagePath"
|
||||
:lang="lang"
|
||||
:data-name="dataName"
|
||||
:session-from="sessionFrom"
|
||||
:send-message-img="sendMessageImg"
|
||||
:show-message-card="showMessageCard"
|
||||
:hover-class="!disabled && !loading ? 'uv-button--active' : ''"
|
||||
class="uv-button uv-reset-button"
|
||||
:style="[baseColor, $uv.addStyle(customStyle)]"
|
||||
@tap="clickHandler"
|
||||
:class="bemClass"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<template v-if="loading">
|
||||
<uv-loading-icon
|
||||
:mode="loadingMode"
|
||||
:size="loadingSize * 1.15"
|
||||
:color="loadingColor"
|
||||
></uv-loading-icon>
|
||||
<text
|
||||
class="uv-button__loading-text"
|
||||
:style="[
|
||||
{ fontSize: textSize + 'px' },
|
||||
$uv.addStyle(customTextStyle)
|
||||
]"
|
||||
>{{ loadingText || text }}</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<uv-icon
|
||||
v-if="icon"
|
||||
:name="icon"
|
||||
:color="iconColorCom"
|
||||
:size="getIconSize"
|
||||
:customStyle="{ marginRight: '2px' }"
|
||||
></uv-icon>
|
||||
<slot>
|
||||
<text
|
||||
class="uv-button__text"
|
||||
:style="[
|
||||
{ fontSize: textSize + 'px' },
|
||||
$uv.addStyle(customTextStyle)
|
||||
]"
|
||||
>{{ text }}</text>
|
||||
</slot>
|
||||
<slot name="suffix"></slot>
|
||||
</template>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view
|
||||
:hover-start-time="Number(hoverStartTime)"
|
||||
:hover-stay-time="Number(hoverStayTime)"
|
||||
class="uv-button"
|
||||
:hover-class="
|
||||
!disabled && !loading && !color && (plain || type === 'info')
|
||||
? 'uv-button--active--plain'
|
||||
: !disabled && !loading && !plain
|
||||
? 'uv-button--active'
|
||||
: ''
|
||||
"
|
||||
@tap="clickHandler"
|
||||
:class="bemClass"
|
||||
:style="[baseColor, $uv.addStyle(customStyle)]"
|
||||
>
|
||||
<template v-if="loading">
|
||||
<uv-loading-icon
|
||||
:mode="loadingMode"
|
||||
:size="loadingSize * 1.15"
|
||||
:color="loadingColor"
|
||||
></uv-loading-icon>
|
||||
<text
|
||||
class="uv-button__loading-text"
|
||||
:style="[nvueTextStyle,$uv.addStyle(customTextStyle)]"
|
||||
:class="[plain && `uv-button__text--plain--${type}`]"
|
||||
>{{ loadingText || text }}</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<uv-icon
|
||||
v-if="icon"
|
||||
:name="icon"
|
||||
:color="iconColorCom"
|
||||
:size="getIconSize"
|
||||
></uv-icon>
|
||||
<text
|
||||
class="uv-button__text"
|
||||
:style="[
|
||||
{
|
||||
marginLeft: icon ? '2px' : 0,
|
||||
},
|
||||
nvueTextStyle,
|
||||
$uv.addStyle(customTextStyle)
|
||||
]"
|
||||
:class="[plain && `uv-button__text--plain--${type}`]"
|
||||
>{{ text }}</text>
|
||||
<slot name="suffix"></slot>
|
||||
</template>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import throttle from '@/uni_modules/uv-ui-tools/libs/function/throttle.js';
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import button from '@/uni_modules/uv-ui-tools/libs/mixin/button.js'
|
||||
import openType from '@/uni_modules/uv-ui-tools/libs/mixin/openType.js'
|
||||
import props from "./props.js";
|
||||
/**
|
||||
* button 按钮
|
||||
* @description Button 按钮
|
||||
* @tutorial https://www.uvui.cn/components/button.html
|
||||
* @property {Boolean} hairline 是否显示按钮的细边框 (默认 true )
|
||||
* @property {String} type 按钮的预置样式,info,primary,error,warning,success (默认 'info' )
|
||||
* @property {String} size 按钮尺寸,large,normal,mini (默认 normal)
|
||||
* @property {String} shape 按钮形状,circle(两边为半圆),square(带圆角) (默认 'square' )
|
||||
* @property {Boolean} plain 按钮是否镂空,背景色透明 (默认 false)
|
||||
* @property {Boolean} disabled 是否禁用 (默认 false)
|
||||
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台,在 ios 上为雪花,Android上为圆圈) (默认 false)
|
||||
* @property {String | Number} loadingText 加载中提示文字
|
||||
* @property {String} loadingMode 加载状态图标类型 (默认 'spinner' )
|
||||
* @property {String | Number} loadingSize 加载图标大小 (默认 15 )
|
||||
* @property {String} openType 开放能力,具体请看uniapp稳定关于button组件部分说明
|
||||
* @property {String} formType 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
|
||||
* @property {String} appParameter 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 (注:只微信小程序、QQ小程序有效)
|
||||
* @property {Boolean} hoverStopPropagation 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效(默认 true )
|
||||
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文(默认 en )
|
||||
* @property {String} sessionFrom 会话来源,openType="contact"时有效
|
||||
* @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
|
||||
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
|
||||
* @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
|
||||
* @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效(默认false)
|
||||
* @property {String} dataName 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
|
||||
* @property {String | Number} throttleTime 节流,一定时间内只能触发一次 (默认 0 )
|
||||
* @property {String | Number} hoverStartTime 按住后多久出现点击态,单位毫秒 (默认 0 )
|
||||
* @property {String | Number} hoverStayTime 手指松开后点击态保留时间,单位毫秒 (默认 200 )
|
||||
* @property {String | Number} text 按钮文字,之所以通过props传入,是因为slot传入的话(注:nvue中无法控制文字的样式)
|
||||
* @property {String} icon 按钮图标
|
||||
* @property {String} iconColor 按钮图标颜色
|
||||
* @property {String} color 按钮颜色,支持传入linear-gradient渐变色
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
* @event {Function} click 非禁止并且非加载中,才能点击
|
||||
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
|
||||
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo
|
||||
* @event {Function} error 当使用开放能力时,发生错误的回调
|
||||
* @event {Function} opensetting 在打开授权设置页并关闭后回调
|
||||
* @event {Function} launchapp 打开 APP 成功的回调
|
||||
* @example <uv-button>月落</uv-button>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-button",
|
||||
// #ifdef MP
|
||||
mixins: [mpMixin, mixin, button, openType, props],
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
mixins: [mpMixin, mixin, props],
|
||||
// #endif
|
||||
emits: ['click'],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
// 生成bem风格的类名
|
||||
bemClass() {
|
||||
// this.bem为一个computed变量,在mixin中
|
||||
if (!this.color) {
|
||||
return this.bem("button",
|
||||
["type", "shape", "size"],
|
||||
["disabled", "plain", "hairline"]);
|
||||
} else {
|
||||
// 由于nvue的原因,在有color参数时,不需要传入type,否则会生成type相关的类型,影响最终的样式
|
||||
return this.bem("button",
|
||||
["shape", "size"],
|
||||
["disabled", "plain", "hairline"]);
|
||||
}
|
||||
},
|
||||
loadingColor() {
|
||||
if (this.plain) {
|
||||
// 如果有设置color值,则用color值,否则使用type主题颜色
|
||||
return this.color ? this.color : '#3c9cff';
|
||||
}
|
||||
if (this.type === "info") {
|
||||
return "#c9c9c9";
|
||||
}
|
||||
return "rgb(200, 200, 200)";
|
||||
},
|
||||
iconColorCom() {
|
||||
// 如果是镂空状态,设置了color就用color值,否则使用主题颜色,
|
||||
// uv-icon的color能接受一个主题颜色的值
|
||||
if (this.iconColor) return this.iconColor;
|
||||
if (this.plain) {
|
||||
return this.color ? this.color : this.type;
|
||||
} else {
|
||||
return this.type === "info" ? "#000000" : "#ffffff";
|
||||
}
|
||||
},
|
||||
baseColor() {
|
||||
let style = {};
|
||||
if (this.color) {
|
||||
// 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
|
||||
style.color = this.plain ? this.color : "white";
|
||||
if (!this.plain) {
|
||||
// 非镂空,背景色使用自定义的颜色
|
||||
style["background-color"] = this.color;
|
||||
}
|
||||
if (this.color.indexOf("gradient") !== -1) {
|
||||
// 如果自定义的颜色为渐变色,不显示边框,以及通过backgroundImage设置渐变色
|
||||
// weex文档说明可以写borderWidth的形式,为什么这里需要分开写?
|
||||
// 因为weex是阿里巴巴为了部门业绩考核而做的你懂的东西,所以需要这么写才有效
|
||||
style.borderTopWidth = 0;
|
||||
style.borderRightWidth = 0;
|
||||
style.borderBottomWidth = 0;
|
||||
style.borderLeftWidth = 0;
|
||||
if (!this.plain) {
|
||||
style.backgroundImage = this.color;
|
||||
}
|
||||
} else {
|
||||
// 非渐变色,则设置边框相关的属性
|
||||
style.borderColor = this.color;
|
||||
style.borderWidth = "1px";
|
||||
style.borderStyle = "solid";
|
||||
}
|
||||
}
|
||||
return style;
|
||||
},
|
||||
// nvue版本按钮的字体不会继承父组件的颜色,需要对每一个text组件进行单独的设置
|
||||
nvueTextStyle() {
|
||||
let style = {};
|
||||
// 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
|
||||
if (this.type === "info") {
|
||||
style.color = "#323233";
|
||||
}
|
||||
if (this.color) {
|
||||
style.color = this.plain ? this.color : "white";
|
||||
}
|
||||
style.fontSize = this.textSize + "px";
|
||||
return style;
|
||||
},
|
||||
// 字体大小
|
||||
textSize() {
|
||||
let fontSize = 14,
|
||||
{ size } = this;
|
||||
if (size === "large") fontSize = 16;
|
||||
if (size === "normal") fontSize = 14;
|
||||
if (size === "small") fontSize = 12;
|
||||
if (size === "mini") fontSize = 10;
|
||||
return fontSize;
|
||||
},
|
||||
// 设置图标大小
|
||||
getIconSize() {
|
||||
const size = this.iconSize ? this.iconSize : this.textSize * 1.35;
|
||||
return this.$uv.addUnit(size);
|
||||
},
|
||||
// 设置外层盒子的宽度,其他样式不需要
|
||||
btnWrapperStyle() {
|
||||
const style = {};
|
||||
const customStyle = this.$uv.addStyle(this.customStyle);
|
||||
if(customStyle.width) style.width = customStyle.width;
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickHandler() {
|
||||
// 非禁止并且非加载中,才能点击
|
||||
if (!this.disabled && !this.loading) {
|
||||
// 进行节流控制,每this.throttle毫秒内,只在开始处执行
|
||||
throttle(() => {
|
||||
this.$emit("click");
|
||||
}, this.throttleTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-reset-button: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "./vue.scss";
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
@import "./nvue.scss";
|
||||
/* #endif */
|
||||
|
||||
$uv-button-uv-button-height: 40px !default;
|
||||
$uv-button-text-font-size: 15px !default;
|
||||
$uv-button-loading-text-font-size: 15px !default;
|
||||
$uv-button-loading-text-margin-left: 4px !default;
|
||||
$uv-button-large-width: 100% !default;
|
||||
$uv-button-large-height: 50px !default;
|
||||
$uv-button-normal-padding: 0 12px !default;
|
||||
$uv-button-large-padding: 0 15px !default;
|
||||
$uv-button-normal-font-size: 14px !default;
|
||||
$uv-button-small-min-width: 60px !default;
|
||||
$uv-button-small-height: 30px !default;
|
||||
$uv-button-small-padding: 0px 8px !default;
|
||||
$uv-button-mini-padding: 0px 8px !default;
|
||||
$uv-button-small-font-size: 12px !default;
|
||||
$uv-button-mini-height: 22px !default;
|
||||
$uv-button-mini-font-size: 10px !default;
|
||||
$uv-button-mini-min-width: 50px !default;
|
||||
$uv-button-disabled-opacity: 0.5 !default;
|
||||
$uv-button-info-color: #323233 !default;
|
||||
$uv-button-info-background-color: #fff !default;
|
||||
$uv-button-info-border-color: #ebedf0 !default;
|
||||
$uv-button-info-border-width: 1px !default;
|
||||
$uv-button-info-border-style: solid !default;
|
||||
$uv-button-success-color: #fff !default;
|
||||
$uv-button-success-background-color: $uv-success !default;
|
||||
$uv-button-success-border-color: $uv-button-success-background-color !default;
|
||||
$uv-button-success-border-width: 1px !default;
|
||||
$uv-button-success-border-style: solid !default;
|
||||
$uv-button-primary-color: #fff !default;
|
||||
$uv-button-primary-background-color: $uv-primary !default;
|
||||
$uv-button-primary-border-color: $uv-button-primary-background-color !default;
|
||||
$uv-button-primary-border-width: 1px !default;
|
||||
$uv-button-primary-border-style: solid !default;
|
||||
$uv-button-error-color: #fff !default;
|
||||
$uv-button-error-background-color: $uv-error !default;
|
||||
$uv-button-error-border-color: $uv-button-error-background-color !default;
|
||||
$uv-button-error-border-width: 1px !default;
|
||||
$uv-button-error-border-style: solid !default;
|
||||
$uv-button-warning-color: #fff !default;
|
||||
$uv-button-warning-background-color: $uv-warning !default;
|
||||
$uv-button-warning-border-color: $uv-button-warning-background-color !default;
|
||||
$uv-button-warning-border-width: 1px !default;
|
||||
$uv-button-warning-border-style: solid !default;
|
||||
$uv-button-block-width: 100% !default;
|
||||
$uv-button-circle-border-top-right-radius: 100px !default;
|
||||
$uv-button-circle-border-top-left-radius: 100px !default;
|
||||
$uv-button-circle-border-bottom-left-radius: 100px !default;
|
||||
$uv-button-circle-border-bottom-right-radius: 100px !default;
|
||||
$uv-button-square-border-top-right-radius: 3px !default;
|
||||
$uv-button-square-border-top-left-radius: 3px !default;
|
||||
$uv-button-square-border-bottom-left-radius: 3px !default;
|
||||
$uv-button-square-border-bottom-right-radius: 3px !default;
|
||||
$uv-button-icon-min-width: 1em !default;
|
||||
$uv-button-plain-background-color: #fff !default;
|
||||
$uv-button-hairline-border-width: 0.5px !default;
|
||||
|
||||
.uv-button {
|
||||
height: $uv-button-uv-button-height;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@include flex;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
|
||||
&__text {
|
||||
font-size: $uv-button-text-font-size;
|
||||
}
|
||||
|
||||
&__loading-text {
|
||||
font-size: $uv-button-loading-text-font-size;
|
||||
margin-left: $uv-button-loading-text-margin-left;
|
||||
}
|
||||
|
||||
&--large {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: $uv-button-large-width;
|
||||
/* #endif */
|
||||
height: $uv-button-large-height;
|
||||
padding: $uv-button-large-padding;
|
||||
}
|
||||
|
||||
&--normal {
|
||||
padding: $uv-button-normal-padding;
|
||||
font-size: $uv-button-normal-font-size;
|
||||
}
|
||||
|
||||
&--small {
|
||||
/* #ifndef APP-NVUE */
|
||||
min-width: $uv-button-small-min-width;
|
||||
/* #endif */
|
||||
height: $uv-button-small-height;
|
||||
padding: $uv-button-small-padding;
|
||||
font-size: $uv-button-small-font-size;
|
||||
}
|
||||
|
||||
&--mini {
|
||||
height: $uv-button-mini-height;
|
||||
font-size: $uv-button-mini-font-size;
|
||||
/* #ifndef APP-NVUE */
|
||||
min-width: $uv-button-mini-min-width;
|
||||
/* #endif */
|
||||
padding: $uv-button-mini-padding;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: $uv-button-disabled-opacity;
|
||||
}
|
||||
|
||||
&--info {
|
||||
color: $uv-button-info-color;
|
||||
background-color: $uv-button-info-background-color;
|
||||
border-color: $uv-button-info-border-color;
|
||||
border-width: $uv-button-info-border-width;
|
||||
border-style: $uv-button-info-border-style;
|
||||
}
|
||||
|
||||
&--success {
|
||||
color: $uv-button-success-color;
|
||||
background-color: $uv-button-success-background-color;
|
||||
border-color: $uv-button-success-border-color;
|
||||
border-width: $uv-button-success-border-width;
|
||||
border-style: $uv-button-success-border-style;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
color: $uv-button-primary-color;
|
||||
background-color: $uv-button-primary-background-color;
|
||||
border-color: $uv-button-primary-border-color;
|
||||
border-width: $uv-button-primary-border-width;
|
||||
border-style: $uv-button-primary-border-style;
|
||||
}
|
||||
|
||||
&--error {
|
||||
color: $uv-button-error-color;
|
||||
background-color: $uv-button-error-background-color;
|
||||
border-color: $uv-button-error-border-color;
|
||||
border-width: $uv-button-error-border-width;
|
||||
border-style: $uv-button-error-border-style;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
color: $uv-button-warning-color;
|
||||
background-color: $uv-button-warning-background-color;
|
||||
border-color: $uv-button-warning-border-color;
|
||||
border-width: $uv-button-warning-border-width;
|
||||
border-style: $uv-button-warning-border-style;
|
||||
}
|
||||
|
||||
&--block {
|
||||
@include flex;
|
||||
width: $uv-button-block-width;
|
||||
}
|
||||
|
||||
&--circle {
|
||||
border-top-right-radius: $uv-button-circle-border-top-right-radius;
|
||||
border-top-left-radius: $uv-button-circle-border-top-left-radius;
|
||||
border-bottom-left-radius: $uv-button-circle-border-bottom-left-radius;
|
||||
border-bottom-right-radius: $uv-button-circle-border-bottom-right-radius;
|
||||
}
|
||||
|
||||
&--square {
|
||||
border-bottom-left-radius: $uv-button-square-border-top-right-radius;
|
||||
border-bottom-right-radius: $uv-button-square-border-top-left-radius;
|
||||
border-top-left-radius: $uv-button-square-border-bottom-left-radius;
|
||||
border-top-right-radius: $uv-button-square-border-bottom-right-radius;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
min-width: $uv-button-icon-min-width;
|
||||
line-height: inherit !important;
|
||||
vertical-align: top;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
&--plain {
|
||||
background-color: $uv-button-plain-background-color;
|
||||
}
|
||||
|
||||
&--hairline {
|
||||
border-width: $uv-button-hairline-border-width !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,93 @@
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
// nvue下hover-class无效
|
||||
$uv-button-before-top:50% !default;
|
||||
$uv-button-before-left:50% !default;
|
||||
$uv-button-before-width:100% !default;
|
||||
$uv-button-before-height:100% !default;
|
||||
$uv-button-before-transform:translate(-50%, -50%) !default;
|
||||
$uv-button-before-opacity:0 !default;
|
||||
$uv-button-before-background-color:#000 !default;
|
||||
$uv-button-before-border-color:#000 !default;
|
||||
$uv-button-active-before-opacity:.15 !default;
|
||||
$uv-button-icon-margin-left:4px !default;
|
||||
$uv-button-plain-uv-button-info-color:$uv-info;
|
||||
$uv-button-plain-uv-button-success-color:$uv-success;
|
||||
$uv-button-plain-uv-button-error-color:$uv-error;
|
||||
$uv-button-plain-uv-button-warning-color:$uv-warning;
|
||||
|
||||
.uv-button-wrapper {
|
||||
position: relative;
|
||||
&--dis {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9;
|
||||
}
|
||||
}
|
||||
|
||||
.uv-button {
|
||||
width: 100%;
|
||||
|
||||
&__text {
|
||||
white-space: nowrap;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top:$uv-button-before-top;
|
||||
left:$uv-button-before-left;
|
||||
width:$uv-button-before-width;
|
||||
height:$uv-button-before-height;
|
||||
border: inherit;
|
||||
border-radius: inherit;
|
||||
transform:$uv-button-before-transform;
|
||||
opacity:$uv-button-before-opacity;
|
||||
content: " ";
|
||||
background-color:$uv-button-before-background-color;
|
||||
border-color:$uv-button-before-border-color;
|
||||
}
|
||||
|
||||
&--active {
|
||||
&:before {
|
||||
opacity: .15
|
||||
}
|
||||
}
|
||||
|
||||
&__icon+&__text:not(:empty),
|
||||
&__loading-text {
|
||||
margin-left:$uv-button-icon-margin-left;
|
||||
}
|
||||
|
||||
&--plain {
|
||||
&.uv-button--primary {
|
||||
color: $uv-primary;
|
||||
}
|
||||
}
|
||||
|
||||
&--plain {
|
||||
&.uv-button--info {
|
||||
color:$uv-button-plain-uv-button-info-color;
|
||||
}
|
||||
}
|
||||
|
||||
&--plain {
|
||||
&.uv-button--success {
|
||||
color:$uv-button-plain-uv-button-success-color;
|
||||
}
|
||||
}
|
||||
|
||||
&--plain {
|
||||
&.uv-button--error {
|
||||
color:$uv-button-plain-uv-button-error-color;
|
||||
}
|
||||
}
|
||||
|
||||
&--plain {
|
||||
&.uv-button--warning {
|
||||
color:$uv-button-plain-uv-button-warning-color;
|
||||
}
|
||||
}
|
||||
}
|
89
x_admin_app/uni_modules/uv-button/package.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"id": "uv-button",
|
||||
"displayName": "uv-button 按钮 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.15",
|
||||
"description": "按钮组件内部实现以uni-app的button组件为基础,进行二次封装,灵活配置,功能齐全,兼容全端。",
|
||||
"keywords": [
|
||||
"uv-button",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"button",
|
||||
"按钮"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-loading-icon",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
x_admin_app/uni_modules/uv-button/readme.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## Button 按钮
|
||||
|
||||
> **组件名:uv-button**
|
||||
|
||||
该组件内部实现以`uni-app`的`button`组件为基础,进行二次封装,灵活配置,功能齐全,兼容全端。灵活配置,内置状态设置,开箱即用。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/button.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|