对比新文件 |
| | |
| | | { |
| | | "version" : "1.0", |
| | | "configurations" : [ |
| | | { |
| | | "playground" : "standard", |
| | | "type" : "uni-app:app-android" |
| | | }, |
| | | { |
| | | "app-plus" : { |
| | | "launchtype" : "local" |
| | | }, |
| | | "type" : "uniCloud" |
| | | } |
| | | ] |
| | | } |
对比新文件 |
| | |
| | | # Default ignored files |
| | | /shelf/ |
| | | /workspace.xml |
| | | # Editor-based HTTP Client requests |
| | | /httpRequests/ |
对比新文件 |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="accountSettings"> |
| | | <option name="activeRegion" value="us-east-1" /> |
| | | <option name="recentlyUsedRegions"> |
| | | <list> |
| | | <option value="us-east-1" /> |
| | | </list> |
| | | </option> |
| | | </component> |
| | | </project> |
对比新文件 |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="ProjectModuleManager"> |
| | | <modules> |
| | | <module fileurl="file://$PROJECT_DIR$/.idea/responseApp.iml" filepath="$PROJECT_DIR$/.idea/responseApp.iml" /> |
| | | </modules> |
| | | </component> |
| | | </project> |
对比新文件 |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module type="WEB_MODULE" version="4"> |
| | | <component name="NewModuleRootManager"> |
| | | <content url="file://$MODULE_DIR$"> |
| | | <excludeFolder url="file://$MODULE_DIR$/temp" /> |
| | | <excludeFolder url="file://$MODULE_DIR$/.tmp" /> |
| | | <excludeFolder url="file://$MODULE_DIR$/tmp" /> |
| | | </content> |
| | | <orderEntry type="inheritedJdk" /> |
| | | <orderEntry type="sourceFolder" forTests="false" /> |
| | | </component> |
| | | </module> |
对比新文件 |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="VcsDirectoryMappings"> |
| | | <mapping directory="$PROJECT_DIR$" vcs="Git" /> |
| | | </component> |
| | | </project> |
对比新文件 |
| | |
| | | <script> |
| | | export default { |
| | | onLaunch: function() { |
| | | console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!') |
| | | console.log('App Launch') |
| | | // uni.hideTabBar({}); |
| | | // uni.clearStorageSync(); |
| | | // uni.clearStorage(); |
| | | }, |
| | | onShow: function() { |
| | | console.log('App Show') |
| | | // uni.hideTabBar(); |
| | | // uni.clearStorageSync(); |
| | | // uni.clearStorage(); |
| | | }, |
| | | onHide: function() { |
| | | // uni.clearStorageSync(); |
| | | console.log('App Hide') |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | @import "@/uni_modules/uview-ui/index.scss"; |
| | | /*每个页面公共css */ |
| | | @import '@/uni_modules/uni-scss/index.scss'; |
| | | /* #ifndef APP-NVUE */ |
| | | @import '@/static/customicons.css'; |
| | | // 设置整个项目的背景色 |
| | | page { |
| | | background-color: #f5f5f5; |
| | | } |
| | | |
| | | /* #endif */ |
| | | .example-info { |
| | | font-size: 14px; |
| | | color: #333; |
| | | padding: 10px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | import {service} from '../common/request.js'; |
| | | |
| | | export function getExamine(data) { |
| | | return service({ |
| | | url: '/app/warninfo/review/Page', |
| | | method: 'POST', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | export function submit(data) { |
| | | return service({ |
| | | url: '/app/warninfo/review/submit', |
| | | method: 'POST', |
| | | data |
| | | }) |
| | | } |
对比新文件 |
| | |
| | | import {service} from '../common/request.js'; |
| | | |
| | | export function login(data) { |
| | | return service({ |
| | | url: '/account/auth/login', |
| | | method: 'POST', |
| | | data |
| | | }) |
| | | } |
对比新文件 |
| | |
| | | import {service} from '../common/request.js'; |
| | | |
| | | export function getNotice(data) { |
| | | return service({ |
| | | url: '/app/warninfo/receive/Page', |
| | | method: 'POST', |
| | | data |
| | | }) |
| | | } |
| | | export function confirm(data) { |
| | | return service({ |
| | | url: '/app/warninfo/responseById', |
| | | method: 'GET', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | export function update(data) { |
| | | return service({ |
| | | url: '/app/warninfo/readById', |
| | | method: 'GET', |
| | | data |
| | | }) |
| | | } |
对比新文件 |
| | |
| | | import {service} from '../common/request.js'; |
| | | |
| | | export function getResponse(data) { |
| | | return service({ |
| | | url: '/app/warninfo/person/response', |
| | | method: 'POST', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | export function getDetail(data) { |
| | | return service({ |
| | | url: '/app/warninfo/detailsByWarnLogId', |
| | | method: 'GET', |
| | | data |
| | | }) |
| | | } |
对比新文件 |
| | |
| | | |
| | | let VUE_APP_BASE_URL= null; |
| | | if (process.env.NODE_ENV == 'development') { |
| | | VUE_APP_BASE_URL = 'http://192.168.0.38:8086' |
| | | // VUE_APP_BASE_URL = 'http://121.239.169.30:13001' |
| | | }else { |
| | | VUE_APP_BASE_URL = 'http://121.239.169.30:13001' |
| | | } |
| | | |
| | | export default VUE_APP_BASE_URL |
对比新文件 |
| | |
| | | import VUE_APP_BASE_URL from './constant.js'; |
| | | |
| | | let server_url = VUE_APP_BASE_URL; |
| | | console.log("url",server_url) |
| | | let token = uni.getStorageSync('tk'); |
| | | export function service(options = {}) { |
| | | console.log(("option",options)) |
| | | options.url = `${server_url}${options.url}`; |
| | | //配置请求头 |
| | | if(uni.getStorageSync('tk')){ |
| | | options.header = { |
| | | 'Content-type': options.header || 'application/json', |
| | | 'tk':uni.getStorageSync('tk'), |
| | | 'uid': uni.getStorageSync('uid') |
| | | }; |
| | | } |
| | | else { |
| | | options.header = { |
| | | 'Content-type': options.header || 'application/json' |
| | | }; |
| | | } |
| | | return new Promise((resolved, rejected) => { |
| | | //成功 |
| | | options.success = (res) => { |
| | | if (Number(res.data.code) == 100) { |
| | | resolved(res.data); |
| | | } else { |
| | | uni.showToast({ |
| | | icon: 'none', |
| | | duration: 3000, |
| | | position: 'top', |
| | | title: `${res.data.msg}` |
| | | }); |
| | | rejected(res.data.msg); |
| | | uni.navigateTo({ |
| | | url: '/pages/index/index' |
| | | }) |
| | | } |
| | | } |
| | | options.fail = (err) => { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | title: '服务响应失败' |
| | | }); |
| | | rejected(err); |
| | | } |
| | | uni.request(options); |
| | | |
| | | }); |
| | | } |
对比新文件 |
| | |
| | | const CONFIG = { |
| | | // 开发环境配置 |
| | | development: { |
| | | // baseUrl: 'http://121.239.169.30:13001', |
| | | baseUrl: 'http://192.168.0.38:8086', |
| | | }, |
| | | // 生产环境配置 |
| | | production: { |
| | | baseUrl: 'http://192.168.0.38:8086', |
| | | |
| | | } |
| | | |
| | | }; |
| | | export default CONFIG[process.env.NODE_ENV]; |
对比新文件 |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="en"> |
| | | <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> |
对比新文件 |
| | |
| | | |
| | | // #ifndef VUE3 |
| | | import Vue from 'vue' |
| | | import App from './App' |
| | | import request from '@/common/request.js' |
| | | import uView from '@/uni_modules/uview-ui' |
| | | import store from './store/index.js' |
| | | Vue.use(uView) |
| | | Vue.config.productionTip = false |
| | | |
| | | Vue.prototype.$Z = request; |
| | | App.mpType = 'app' |
| | | |
| | | const app = new Vue({ |
| | | ...App, |
| | | store |
| | | }) |
| | | app.$mount() |
| | | // #endif |
| | | |
| | | // #ifdef VUE3 |
| | | import { createSSRApp } from 'vue' |
| | | import App from './App.vue' |
| | | import uView from '@/uni_modules/uview-ui' |
| | | import request from '@/common/request.js'; |
| | | Vue.prototype.$Z = request; |
| | | Vue.use(uView) |
| | | export function createApp() { |
| | | const app = createSSRApp(App) |
| | | return { |
| | | app |
| | | } |
| | | } |
| | | // #endif |
对比新文件 |
| | |
| | | { |
| | | "name" : "应急响应", |
| | | "appid" : "__UNI__843A1A3", |
| | | "description" : "", |
| | | "versionName" : "1.0.0", |
| | | "versionCode" : 1, |
| | | "transformPx" : false, |
| | | "app-plus" : { |
| | | /* 5+App特有相关 */ |
| | | "usingComponents" : true, |
| | | "nvueCompiler" : "uni-app", |
| | | "nvueStyleCompiler" : "uni-app", |
| | | "splashscreen" : { |
| | | "alwaysShowBeforeRender" : true, |
| | | "waiting" : true, |
| | | "autoclose" : true, |
| | | "delay" : 0 |
| | | }, |
| | | "modules" : {}, |
| | | /* 模块配置 */ |
| | | "distribute" : { |
| | | /* 应用发布信息 */ |
| | | "android" : { |
| | | /* 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\"/>" |
| | | ] |
| | | }, |
| | | "ios" : { |
| | | "dSYMs" : false |
| | | }, |
| | | /* ios打包配置 */ |
| | | "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" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | /* SDK配置 */ |
| | | "quickapp" : {}, |
| | | /* 快应用特有相关 */ |
| | | "mp-weixin" : { |
| | | /* 小程序特有相关 */ |
| | | "appid" : "", |
| | | "setting" : { |
| | | "urlCheck" : false |
| | | }, |
| | | "usingComponents" : true |
| | | }, |
| | | "vueVersion" : "2" |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "name": "responseApp", |
| | | "lockfileVersion": 3, |
| | | "requires": true, |
| | | "packages": { |
| | | "": { |
| | | "devDependencies": { |
| | | "sass": "^1.62.1", |
| | | "sass-loader": "^13.3.1" |
| | | } |
| | | }, |
| | | "node_modules/@jridgewell/gen-mapping": { |
| | | "version": "0.3.3", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", |
| | | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/set-array": "^1.0.1", |
| | | "@jridgewell/sourcemap-codec": "^1.4.10", |
| | | "@jridgewell/trace-mapping": "^0.3.9" |
| | | }, |
| | | "engines": { |
| | | "node": ">=6.0.0" |
| | | } |
| | | }, |
| | | "node_modules/@jridgewell/resolve-uri": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", |
| | | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6.0.0" |
| | | } |
| | | }, |
| | | "node_modules/@jridgewell/set-array": { |
| | | "version": "1.1.2", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", |
| | | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6.0.0" |
| | | } |
| | | }, |
| | | "node_modules/@jridgewell/source-map": { |
| | | "version": "0.3.3", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.3.tgz", |
| | | "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/gen-mapping": "^0.3.0", |
| | | "@jridgewell/trace-mapping": "^0.3.9" |
| | | } |
| | | }, |
| | | "node_modules/@jridgewell/sourcemap-codec": { |
| | | "version": "1.4.14", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", |
| | | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@jridgewell/trace-mapping": { |
| | | "version": "0.3.18", |
| | | "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", |
| | | "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/resolve-uri": "3.1.0", |
| | | "@jridgewell/sourcemap-codec": "1.4.14" |
| | | } |
| | | }, |
| | | "node_modules/@types/eslint": { |
| | | "version": "8.40.0", |
| | | "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.40.0.tgz", |
| | | "integrity": "sha512-nbq2mvc/tBrK9zQQuItvjJl++GTN5j06DaPtp3hZCpngmG6Q3xoyEmd0TwZI0gAy/G1X0zhGBbr2imsGFdFV0g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@types/estree": "*", |
| | | "@types/json-schema": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/eslint-scope": { |
| | | "version": "3.7.4", |
| | | "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", |
| | | "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@types/eslint": "*", |
| | | "@types/estree": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/estree": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.1.tgz", |
| | | "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@types/json-schema": { |
| | | "version": "7.0.12", |
| | | "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.12.tgz", |
| | | "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@types/node": { |
| | | "version": "20.2.5", |
| | | "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.2.5.tgz", |
| | | "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/ast": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.6.tgz", |
| | | "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/helper-numbers": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-bytecode": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/floating-point-hex-parser": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", |
| | | "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/helper-api-error": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", |
| | | "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/helper-buffer": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", |
| | | "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/helper-numbers": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", |
| | | "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/floating-point-hex-parser": "1.11.6", |
| | | "@webassemblyjs/helper-api-error": "1.11.6", |
| | | "@xtuc/long": "4.2.2" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/helper-wasm-bytecode": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", |
| | | "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/helper-wasm-section": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", |
| | | "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@webassemblyjs/helper-buffer": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", |
| | | "@webassemblyjs/wasm-gen": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/ieee754": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", |
| | | "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@xtuc/ieee754": "^1.2.0" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/leb128": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", |
| | | "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@xtuc/long": "4.2.2" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/utf8": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", |
| | | "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@webassemblyjs/wasm-edit": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", |
| | | "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@webassemblyjs/helper-buffer": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-section": "1.11.6", |
| | | "@webassemblyjs/wasm-gen": "1.11.6", |
| | | "@webassemblyjs/wasm-opt": "1.11.6", |
| | | "@webassemblyjs/wasm-parser": "1.11.6", |
| | | "@webassemblyjs/wast-printer": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/wasm-gen": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", |
| | | "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", |
| | | "@webassemblyjs/ieee754": "1.11.6", |
| | | "@webassemblyjs/leb128": "1.11.6", |
| | | "@webassemblyjs/utf8": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/wasm-opt": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", |
| | | "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@webassemblyjs/helper-buffer": "1.11.6", |
| | | "@webassemblyjs/wasm-gen": "1.11.6", |
| | | "@webassemblyjs/wasm-parser": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/wasm-parser": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", |
| | | "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@webassemblyjs/helper-api-error": "1.11.6", |
| | | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", |
| | | "@webassemblyjs/ieee754": "1.11.6", |
| | | "@webassemblyjs/leb128": "1.11.6", |
| | | "@webassemblyjs/utf8": "1.11.6" |
| | | } |
| | | }, |
| | | "node_modules/@webassemblyjs/wast-printer": { |
| | | "version": "1.11.6", |
| | | "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", |
| | | "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@webassemblyjs/ast": "1.11.6", |
| | | "@xtuc/long": "4.2.2" |
| | | } |
| | | }, |
| | | "node_modules/@xtuc/ieee754": { |
| | | "version": "1.2.0", |
| | | "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", |
| | | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/@xtuc/long": { |
| | | "version": "4.2.2", |
| | | "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", |
| | | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/acorn": { |
| | | "version": "8.8.2", |
| | | "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz", |
| | | "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "bin": { |
| | | "acorn": "bin/acorn" |
| | | }, |
| | | "engines": { |
| | | "node": ">=0.4.0" |
| | | } |
| | | }, |
| | | "node_modules/acorn-import-assertions": { |
| | | "version": "1.9.0", |
| | | "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", |
| | | "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "peerDependencies": { |
| | | "acorn": "^8" |
| | | } |
| | | }, |
| | | "node_modules/ajv": { |
| | | "version": "6.12.6", |
| | | "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", |
| | | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "fast-deep-equal": "^3.1.1", |
| | | "fast-json-stable-stringify": "^2.0.0", |
| | | "json-schema-traverse": "^0.4.1", |
| | | "uri-js": "^4.2.2" |
| | | } |
| | | }, |
| | | "node_modules/ajv-keywords": { |
| | | "version": "3.5.2", |
| | | "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", |
| | | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "peerDependencies": { |
| | | "ajv": "^6.9.1" |
| | | } |
| | | }, |
| | | "node_modules/anymatch": { |
| | | "version": "3.1.3", |
| | | "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", |
| | | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "normalize-path": "^3.0.0", |
| | | "picomatch": "^2.0.4" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 8" |
| | | } |
| | | }, |
| | | "node_modules/binary-extensions": { |
| | | "version": "2.2.0", |
| | | "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz", |
| | | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=8" |
| | | } |
| | | }, |
| | | "node_modules/braces": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", |
| | | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "fill-range": "^7.0.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8" |
| | | } |
| | | }, |
| | | "node_modules/browserslist": { |
| | | "version": "4.21.7", |
| | | "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.7.tgz", |
| | | "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "caniuse-lite": "^1.0.30001489", |
| | | "electron-to-chromium": "^1.4.411", |
| | | "node-releases": "^2.0.12", |
| | | "update-browserslist-db": "^1.0.11" |
| | | }, |
| | | "bin": { |
| | | "browserslist": "cli.js" |
| | | }, |
| | | "engines": { |
| | | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" |
| | | } |
| | | }, |
| | | "node_modules/buffer-from": { |
| | | "version": "1.1.2", |
| | | "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", |
| | | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/caniuse-lite": { |
| | | "version": "1.0.30001495", |
| | | "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz", |
| | | "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/chokidar": { |
| | | "version": "3.5.3", |
| | | "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz", |
| | | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "anymatch": "~3.1.2", |
| | | "braces": "~3.0.2", |
| | | "glob-parent": "~5.1.2", |
| | | "is-binary-path": "~2.1.0", |
| | | "is-glob": "~4.0.1", |
| | | "normalize-path": "~3.0.0", |
| | | "readdirp": "~3.6.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 8.10.0" |
| | | }, |
| | | "optionalDependencies": { |
| | | "fsevents": "~2.3.2" |
| | | } |
| | | }, |
| | | "node_modules/chrome-trace-event": { |
| | | "version": "1.0.3", |
| | | "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", |
| | | "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6.0" |
| | | } |
| | | }, |
| | | "node_modules/commander": { |
| | | "version": "2.20.3", |
| | | "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", |
| | | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/electron-to-chromium": { |
| | | "version": "1.4.421", |
| | | "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.421.tgz", |
| | | "integrity": "sha512-wZOyn3s/aQOtLGAwXMZfteQPN68kgls2wDAnYOA8kCjBvKVrW5RwmWVspxJYTqrcN7Y263XJVsC66VCIGzDO3g==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/enhanced-resolve": { |
| | | "version": "5.14.1", |
| | | "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", |
| | | "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "graceful-fs": "^4.2.4", |
| | | "tapable": "^2.2.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=10.13.0" |
| | | } |
| | | }, |
| | | "node_modules/es-module-lexer": { |
| | | "version": "1.2.1", |
| | | "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.2.1.tgz", |
| | | "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/escalade": { |
| | | "version": "3.1.1", |
| | | "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz", |
| | | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6" |
| | | } |
| | | }, |
| | | "node_modules/eslint-scope": { |
| | | "version": "5.1.1", |
| | | "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", |
| | | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "esrecurse": "^4.3.0", |
| | | "estraverse": "^4.1.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8.0.0" |
| | | } |
| | | }, |
| | | "node_modules/esrecurse": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", |
| | | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "estraverse": "^5.2.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=4.0" |
| | | } |
| | | }, |
| | | "node_modules/esrecurse/node_modules/estraverse": { |
| | | "version": "5.3.0", |
| | | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", |
| | | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=4.0" |
| | | } |
| | | }, |
| | | "node_modules/estraverse": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", |
| | | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=4.0" |
| | | } |
| | | }, |
| | | "node_modules/events": { |
| | | "version": "3.3.0", |
| | | "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", |
| | | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=0.8.x" |
| | | } |
| | | }, |
| | | "node_modules/fast-deep-equal": { |
| | | "version": "3.1.3", |
| | | "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", |
| | | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/fast-json-stable-stringify": { |
| | | "version": "2.1.0", |
| | | "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", |
| | | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/fill-range": { |
| | | "version": "7.0.1", |
| | | "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", |
| | | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "to-regex-range": "^5.0.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8" |
| | | } |
| | | }, |
| | | "node_modules/fsevents": { |
| | | "version": "2.3.2", |
| | | "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", |
| | | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", |
| | | "dev": true, |
| | | "hasInstallScript": true, |
| | | "optional": true, |
| | | "os": [ |
| | | "darwin" |
| | | ], |
| | | "engines": { |
| | | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" |
| | | } |
| | | }, |
| | | "node_modules/glob-parent": { |
| | | "version": "5.1.2", |
| | | "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", |
| | | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "is-glob": "^4.0.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 6" |
| | | } |
| | | }, |
| | | "node_modules/glob-to-regexp": { |
| | | "version": "0.4.1", |
| | | "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", |
| | | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/graceful-fs": { |
| | | "version": "4.2.11", |
| | | "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", |
| | | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/has-flag": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", |
| | | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=8" |
| | | } |
| | | }, |
| | | "node_modules/immutable": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.0.tgz", |
| | | "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/is-binary-path": { |
| | | "version": "2.1.0", |
| | | "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", |
| | | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "binary-extensions": "^2.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8" |
| | | } |
| | | }, |
| | | "node_modules/is-extglob": { |
| | | "version": "2.1.1", |
| | | "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", |
| | | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/is-glob": { |
| | | "version": "4.0.3", |
| | | "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", |
| | | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "is-extglob": "^2.1.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/is-number": { |
| | | "version": "7.0.0", |
| | | "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", |
| | | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=0.12.0" |
| | | } |
| | | }, |
| | | "node_modules/jest-worker": { |
| | | "version": "27.5.1", |
| | | "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", |
| | | "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@types/node": "*", |
| | | "merge-stream": "^2.0.0", |
| | | "supports-color": "^8.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 10.13.0" |
| | | } |
| | | }, |
| | | "node_modules/json-parse-even-better-errors": { |
| | | "version": "2.3.1", |
| | | "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", |
| | | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/json-schema-traverse": { |
| | | "version": "0.4.1", |
| | | "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", |
| | | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/klona": { |
| | | "version": "2.0.6", |
| | | "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", |
| | | "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">= 8" |
| | | } |
| | | }, |
| | | "node_modules/loader-runner": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", |
| | | "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6.11.5" |
| | | } |
| | | }, |
| | | "node_modules/merge-stream": { |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", |
| | | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/mime-db": { |
| | | "version": "1.52.0", |
| | | "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", |
| | | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">= 0.6" |
| | | } |
| | | }, |
| | | "node_modules/mime-types": { |
| | | "version": "2.1.35", |
| | | "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", |
| | | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "mime-db": "1.52.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 0.6" |
| | | } |
| | | }, |
| | | "node_modules/neo-async": { |
| | | "version": "2.6.2", |
| | | "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", |
| | | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/node-releases": { |
| | | "version": "2.0.12", |
| | | "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.12.tgz", |
| | | "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/normalize-path": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", |
| | | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/picocolors": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", |
| | | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/picomatch": { |
| | | "version": "2.3.1", |
| | | "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", |
| | | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=8.6" |
| | | } |
| | | }, |
| | | "node_modules/punycode": { |
| | | "version": "2.3.0", |
| | | "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz", |
| | | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6" |
| | | } |
| | | }, |
| | | "node_modules/randombytes": { |
| | | "version": "2.1.0", |
| | | "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", |
| | | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "safe-buffer": "^5.1.0" |
| | | } |
| | | }, |
| | | "node_modules/readdirp": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", |
| | | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "picomatch": "^2.2.1" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8.10.0" |
| | | } |
| | | }, |
| | | "node_modules/safe-buffer": { |
| | | "version": "5.2.1", |
| | | "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", |
| | | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | | "node_modules/sass": { |
| | | "version": "1.62.1", |
| | | "resolved": "https://registry.npmmirror.com/sass/-/sass-1.62.1.tgz", |
| | | "integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "chokidar": ">=3.0.0 <4.0.0", |
| | | "immutable": "^4.0.0", |
| | | "source-map-js": ">=0.6.2 <2.0.0" |
| | | }, |
| | | "bin": { |
| | | "sass": "sass.js" |
| | | }, |
| | | "engines": { |
| | | "node": ">=14.0.0" |
| | | } |
| | | }, |
| | | "node_modules/sass-loader": { |
| | | "version": "13.3.1", |
| | | "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.3.1.tgz", |
| | | "integrity": "sha512-cBTxmgyVA1nXPvIK4brjJMXOMJ2v2YrQEuHqLw3LylGb3gsR6jAvdjHMcy/+JGTmmIF9SauTrLLR7bsWDMWqgg==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "klona": "^2.0.6", |
| | | "neo-async": "^2.6.2" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 14.15.0" |
| | | }, |
| | | "peerDependencies": { |
| | | "fibers": ">= 3.1.0", |
| | | "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", |
| | | "sass": "^1.3.0", |
| | | "sass-embedded": "*", |
| | | "webpack": "^5.0.0" |
| | | }, |
| | | "peerDependenciesMeta": { |
| | | "fibers": { |
| | | "optional": true |
| | | }, |
| | | "node-sass": { |
| | | "optional": true |
| | | }, |
| | | "sass": { |
| | | "optional": true |
| | | }, |
| | | "sass-embedded": { |
| | | "optional": true |
| | | } |
| | | } |
| | | }, |
| | | "node_modules/schema-utils": { |
| | | "version": "3.1.2", |
| | | "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.1.2.tgz", |
| | | "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@types/json-schema": "^7.0.8", |
| | | "ajv": "^6.12.5", |
| | | "ajv-keywords": "^3.5.2" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 10.13.0" |
| | | } |
| | | }, |
| | | "node_modules/serialize-javascript": { |
| | | "version": "6.0.1", |
| | | "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz", |
| | | "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "randombytes": "^2.1.0" |
| | | } |
| | | }, |
| | | "node_modules/source-map": { |
| | | "version": "0.6.1", |
| | | "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", |
| | | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/source-map-js": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz", |
| | | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", |
| | | "dev": true, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/source-map-support": { |
| | | "version": "0.5.21", |
| | | "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", |
| | | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "buffer-from": "^1.0.0", |
| | | "source-map": "^0.6.0" |
| | | } |
| | | }, |
| | | "node_modules/supports-color": { |
| | | "version": "8.1.1", |
| | | "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", |
| | | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "has-flag": "^4.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=10" |
| | | } |
| | | }, |
| | | "node_modules/tapable": { |
| | | "version": "2.2.1", |
| | | "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz", |
| | | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=6" |
| | | } |
| | | }, |
| | | "node_modules/terser": { |
| | | "version": "5.17.7", |
| | | "resolved": "https://registry.npmmirror.com/terser/-/terser-5.17.7.tgz", |
| | | "integrity": "sha512-/bi0Zm2C6VAexlGgLlVxA0P2lru/sdLyfCVaRMfKVo9nWxbmz7f/sD8VPybPeSUJaJcwmCJis9pBIhcVcG1QcQ==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/source-map": "^0.3.3", |
| | | "acorn": "^8.8.2", |
| | | "commander": "^2.20.0", |
| | | "source-map-support": "~0.5.20" |
| | | }, |
| | | "bin": { |
| | | "terser": "bin/terser" |
| | | }, |
| | | "engines": { |
| | | "node": ">=10" |
| | | } |
| | | }, |
| | | "node_modules/terser-webpack-plugin": { |
| | | "version": "5.3.9", |
| | | "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", |
| | | "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/trace-mapping": "^0.3.17", |
| | | "jest-worker": "^27.4.5", |
| | | "schema-utils": "^3.1.1", |
| | | "serialize-javascript": "^6.0.1", |
| | | "terser": "^5.16.8" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 10.13.0" |
| | | }, |
| | | "peerDependencies": { |
| | | "webpack": "^5.1.0" |
| | | }, |
| | | "peerDependenciesMeta": { |
| | | "@swc/core": { |
| | | "optional": true |
| | | }, |
| | | "esbuild": { |
| | | "optional": true |
| | | }, |
| | | "uglify-js": { |
| | | "optional": true |
| | | } |
| | | } |
| | | }, |
| | | "node_modules/to-regex-range": { |
| | | "version": "5.0.1", |
| | | "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", |
| | | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "is-number": "^7.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=8.0" |
| | | } |
| | | }, |
| | | "node_modules/update-browserslist-db": { |
| | | "version": "1.0.11", |
| | | "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", |
| | | "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "escalade": "^3.1.1", |
| | | "picocolors": "^1.0.0" |
| | | }, |
| | | "bin": { |
| | | "update-browserslist-db": "cli.js" |
| | | }, |
| | | "peerDependencies": { |
| | | "browserslist": ">= 4.21.0" |
| | | } |
| | | }, |
| | | "node_modules/uri-js": { |
| | | "version": "4.4.1", |
| | | "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", |
| | | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "punycode": "^2.1.0" |
| | | } |
| | | }, |
| | | "node_modules/watchpack": { |
| | | "version": "2.4.0", |
| | | "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz", |
| | | "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "glob-to-regexp": "^0.4.1", |
| | | "graceful-fs": "^4.1.2" |
| | | }, |
| | | "engines": { |
| | | "node": ">=10.13.0" |
| | | } |
| | | }, |
| | | "node_modules/webpack": { |
| | | "version": "5.85.1", |
| | | "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.85.1.tgz", |
| | | "integrity": "sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@types/eslint-scope": "^3.7.3", |
| | | "@types/estree": "^1.0.0", |
| | | "@webassemblyjs/ast": "^1.11.5", |
| | | "@webassemblyjs/wasm-edit": "^1.11.5", |
| | | "@webassemblyjs/wasm-parser": "^1.11.5", |
| | | "acorn": "^8.7.1", |
| | | "acorn-import-assertions": "^1.9.0", |
| | | "browserslist": "^4.14.5", |
| | | "chrome-trace-event": "^1.0.2", |
| | | "enhanced-resolve": "^5.14.1", |
| | | "es-module-lexer": "^1.2.1", |
| | | "eslint-scope": "5.1.1", |
| | | "events": "^3.2.0", |
| | | "glob-to-regexp": "^0.4.1", |
| | | "graceful-fs": "^4.2.9", |
| | | "json-parse-even-better-errors": "^2.3.1", |
| | | "loader-runner": "^4.2.0", |
| | | "mime-types": "^2.1.27", |
| | | "neo-async": "^2.6.2", |
| | | "schema-utils": "^3.1.2", |
| | | "tapable": "^2.1.1", |
| | | "terser-webpack-plugin": "^5.3.7", |
| | | "watchpack": "^2.4.0", |
| | | "webpack-sources": "^3.2.3" |
| | | }, |
| | | "bin": { |
| | | "webpack": "bin/webpack.js" |
| | | }, |
| | | "engines": { |
| | | "node": ">=10.13.0" |
| | | }, |
| | | "peerDependenciesMeta": { |
| | | "webpack-cli": { |
| | | "optional": true |
| | | } |
| | | } |
| | | }, |
| | | "node_modules/webpack-sources": { |
| | | "version": "3.2.3", |
| | | "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", |
| | | "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "engines": { |
| | | "node": ">=10.13.0" |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "devDependencies": { |
| | | "sass": "^1.62.1", |
| | | "sass-loader": "^13.3.1" |
| | | } |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "easycom": { |
| | | "^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue" |
| | | }, |
| | | "pages": [ |
| | | { |
| | | "path" : "pages/index/index", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": false |
| | | } |
| | | }, |
| | | { |
| | | "path" : "pages/tabBar/notice/notice", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true, |
| | | "app-plus": { |
| | | "scrollIndicator": "none", |
| | | "pullToRefresh": { |
| | | "support": true, |
| | | "color": "#000000", |
| | | "style": "circle" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | "path" : "pages/tabBar/notice/detail", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": false, |
| | | "app-plus": { |
| | | "scrollIndicator": "none" |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | "path" : "pages/tabBar/response/response", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true, |
| | | "app-plus": { |
| | | "scrollIndicator": "none", |
| | | "pullToRefresh": { |
| | | "support": true, |
| | | "color": "#000000", |
| | | "style": "circle" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | "path" : "pages/tabBar/examine/examine", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true, |
| | | "app-plus": { |
| | | "scrollIndicator": "none", |
| | | "pullToRefresh": { |
| | | "support": true, |
| | | "color": "#000000", |
| | | "style": "circle" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | "path" : "pages/tabBar/count/count", |
| | | "style" : |
| | | { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true, |
| | | "app-plus": { |
| | | "scrollIndicator": "none", |
| | | "pullToRefresh": { |
| | | "support": true, |
| | | "color": "#000000", |
| | | "style": "circle" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | "globalStyle": { |
| | | "navigationBarTextStyle": "black", |
| | | "navigationBarTitleText": "uni-app", |
| | | "navigationBarBackgroundColor": "#F8F8F8", |
| | | "backgroundColor": "#F8F8F8", |
| | | "app-plus": { |
| | | "background": "#efeff4" |
| | | } |
| | | }, |
| | | "tabBar": { |
| | | "borderStyle": "black", |
| | | "selectedColor": "#48bff4", |
| | | "color": "#444444", |
| | | "custom": true, |
| | | "list": [ |
| | | { |
| | | "pagePath": "pages/tabBar/notice/notice" |
| | | // "iconPath": "static/notice1.png", |
| | | // "selectedIconPath": "static/notice1-selected.png", |
| | | // "text": "工作通知" |
| | | }, |
| | | { |
| | | "pagePath": "pages/tabBar/response/response" |
| | | // "iconPath": "static/mine1.png", |
| | | // "selectedIconPath": "static/mine1-selected.png", |
| | | // "text": "我的叫应" |
| | | }, |
| | | { |
| | | "pagePath": "pages/tabBar/examine/examine" |
| | | // "iconPath": "static/notice1.png", |
| | | // "selectedIconPath": "static/notice1-selected.png", |
| | | // "text": "通知审核" |
| | | }, |
| | | { |
| | | "pagePath": "pages/tabBar/count/count" |
| | | // "iconPath": "static/mine1.png", |
| | | // "selectedIconPath": "static/mine1-selected.png", |
| | | // "text": "信息统计" |
| | | } |
| | | |
| | | ] |
| | | } |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="box"> |
| | | <view class="header"> |
| | | <view class="titleFirst"><b>新疆维吾尔自治区自然灾害综合监测预警</b></view> |
| | | <view class="titleSecond"><b>自然灾害综合风险预警发布及响应联动系统</b></view> |
| | | </view> |
| | | <view> |
| | | <u-form :model="form" ref="uForm" class="form" > |
| | | <u-form-item ><u-input color="#fff" v-model="form.name" placeholder="请输入用户名" /></u-form-item> |
| | | <u-form-item ><u-input color="#fff" v-model="form.pwd" type="password" placeholder="请输入密码" /></u-form-item> |
| | | <!-- <view class="loginPsw"> |
| | | <u-checkbox-group > |
| | | <u-checkbox disabled="true"></u-checkbox><text style="color: #fff;">自动登录</text> |
| | | </u-checkbox-group> |
| | | <text style="color: lightblue;">忘记密码</text> |
| | | </view> --> |
| | | <u-form-item ><u-button type="primary" style="width: 100%;" @click="Login">登录</u-button></u-form-item> |
| | | <view style="color: white;margin-left:25%;margin-top: 70%;">技术支持:中国科学院</view> |
| | | </u-form> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import {login} from '../../api/index.js'; |
| | | import store from '@/store/index.js' |
| | | export default { |
| | | data() { |
| | | return { |
| | | form: { |
| | | name: '', |
| | | pwd: '' |
| | | }, |
| | | type: '' |
| | | } |
| | | }, |
| | | onShow() { |
| | | uni.clearStorageSync(); |
| | | uni.clearStorage(); |
| | | }, |
| | | methods: { |
| | | Login(){ |
| | | login(this.form).then(res => { |
| | | console.log("res",res) |
| | | if (res.code === 100) { |
| | | uni.setStorageSync("tk", res.data.tk); |
| | | uni.setStorageSync("uid",res.data.uid); |
| | | uni.setStorageSync('user', res.data); |
| | | uni.setStorageSync('roleName', res.data.role.roleName); |
| | | if(res.data.role.roleName == '工作人员'){ |
| | | this.$store.commit('setRoleId', 'user_other'); |
| | | uni.switchTab({ |
| | | url: '/pages/tabBar/notice/notice' |
| | | }); |
| | | }else if (res.data.role.roleName == '管理员'){ |
| | | this.$store.commit('setRoleId', ''); |
| | | uni.showToast({ |
| | | icon: "none", |
| | | title: '管理员请使用平台登录' |
| | | }); |
| | | }else{ |
| | | this.$store.commit('setRoleId', 'user_leader'); |
| | | uni.switchTab({ |
| | | url: '/pages/tabBar/examine/examine' |
| | | }); |
| | | } |
| | | } |
| | | }).catch(err=>{ |
| | | }) |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .box{ |
| | | width: 100%; |
| | | height: 100vh; |
| | | background: url('../../static/bg.jpeg') no-repeat; |
| | | background-size: 100% 100%; |
| | | background-attachment: fixed;/* 不设置的话页面滑动时,背景会不铺满*/ |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .titleFirst{ |
| | | text-align: center; |
| | | font-size: 18px; |
| | | color:#fff; |
| | | } |
| | | .titleSecond{ |
| | | text-align: center; |
| | | font-size: 19px; |
| | | color:#fff; |
| | | margin-top: 10px; |
| | | } |
| | | .header { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding-top:100px; |
| | | text-shadow:0 0 1px #000; |
| | | } |
| | | .form{ |
| | | width: 80%; |
| | | margin: 100px auto 0px; |
| | | |
| | | } |
| | | .loginPsw{ |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <!-- 自定义导航栏 --> |
| | | <view class="navBarBox fix"> |
| | | <!-- 状态栏占位 --> |
| | | <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view> |
| | | <!-- 真正的导航栏内容 --> |
| | | <view class="navBar"> |
| | | <view class="barText"></view> |
| | | </view> |
| | | </view> |
| | | <text>信息统计模块待呈现</text> |
| | | <tabBar :currentPagePath="page"></tabBar> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import tabBar from '../tabBarIndex.vue' |
| | | export default { |
| | | components:{ |
| | | tabBar |
| | | }, |
| | | data() { |
| | | return { |
| | | page: 'pages/tabBar/count/count', |
| | | statusBarHeight: '' |
| | | } |
| | | |
| | | }, |
| | | onLoad() { |
| | | //获取手机状态栏高度 |
| | | this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight']; |
| | | uni.hideTabBar(); |
| | | } |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style> |
| | | .navBarBox .navBar { |
| | | background-color:lightgrey; |
| | | height: 15px; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | .fix{ |
| | | position: sticky; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | z-index: 1; |
| | | } |
| | | .statusBar{ |
| | | background-color:lightgrey; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="box"> |
| | | <!-- 自定义导航栏 --> |
| | | <view class="navBarBox fix"> |
| | | <!-- 状态栏占位 --> |
| | | <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view> |
| | | <!-- 真正的导航栏内容 --> |
| | | <view class="navBar" > |
| | | <view class="barText">工作通知审核</view> |
| | | </view> |
| | | </view> |
| | | <!-- 页面内容 --> |
| | | <view class="contentList"> |
| | | <view class="buttonGroup"> |
| | | <view style="display: flex;"> |
| | | <view v-for="(button, index) in buttons" :key="index" class="buttonItem" |
| | | :class="{ 'active': selectedSaleAnalysis === button.label, |
| | | 'red': button.label === 'red', |
| | | 'orange':button.label === 'orange', |
| | | 'yellow':button.label === 'yellow', |
| | | 'blue': button.label === 'blue'}" |
| | | @click="handleButtonClick(button)"> |
| | | {{ button.name }} |
| | | </view> |
| | | </view> |
| | | <view class="switchBtn"> |
| | | <text style="margin-right: 7px;">是否紧临</text> |
| | | <u-switch v-model="checked" size="20" @change="clickSwitch"></u-switch> |
| | | </view> |
| | | </view> |
| | | <view class="examineList"> |
| | | <view class="listHead"> |
| | | <u-checkbox-group style="margin-left: 15px;"> |
| | | <u-checkbox v-model="isReadOnly" :checked="isReadOnly" @change="chooseRead"></u-checkbox>只显示待审核 |
| | | </u-checkbox-group> |
| | | </view> |
| | | <view class="listContent" v-if="examineList.length > 0"> |
| | | <view v-for="(item, index) in examineList" :key="index" class="itemContent"> |
| | | <view class="content" @click="toDetail(item)"> |
| | | <text>[{{item.colorContent}}]</text> |
| | | <text>{{item.title}},{{item.content}}</text> |
| | | <view style="float: right; width: 80px;margin-top: 3px;"> |
| | | <u-button v-if="item.buttonContent == '已审核通过'" size="mini" class="buttonCo" style="background-color:rgb(17, 204, 33);color: white"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button v-else-if="item.buttonContent == '已驳回'" size="mini" class="buttonCo" style="background-color:rgb(153, 148, 143);color: white"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button v-else type="error" size="mini" class="buttonCo"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | <view v-else> |
| | | <u-empty |
| | | mode="data" |
| | | icon="http://cdn.uviewui.com/uview/empty/data.png" |
| | | margin-top="50%"> |
| | | </u-empty> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <tabBar :currentPagePath="page"></tabBar> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import tabBar from '../tabBarIndex.vue' |
| | | import {getExamine} from '../../../api/examine.js' |
| | | export default { |
| | | components:{ |
| | | tabBar |
| | | }, |
| | | data() { |
| | | return { |
| | | data: { |
| | | pageIndex: 1, |
| | | pageSize: 1000, |
| | | searchParams: { |
| | | emergType: 1,//1-紧急;2-常规 |
| | | warningLevel: 1,//1-红色预警;2-橙色预警;3-黄色预警;4-蓝色预警 |
| | | reviewStatus: 0//1:未审核,2:已审核,3:审核已驳回 |
| | | } |
| | | }, |
| | | page: 'pages/tabBar/examine/examine', |
| | | checked: true, |
| | | isReadOnly: false, |
| | | statusBarHeight: 0, |
| | | buttons: [{ |
| | | label: 'red', |
| | | name: '红' |
| | | }, |
| | | { |
| | | label: 'orange', |
| | | name: '橙' |
| | | }, |
| | | { |
| | | label: 'yellow', |
| | | name: '黄' |
| | | }, |
| | | { |
| | | label: 'blue', |
| | | name: '蓝' |
| | | }, |
| | | ], |
| | | selectedSaleAnalysis: 'red', |
| | | examineList: [], |
| | | } |
| | | }, |
| | | onLoad() { |
| | | //获取手机状态栏高度 |
| | | this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight']; |
| | | uni.hideTabBar(); |
| | | }, |
| | | onShow() { |
| | | this.getExanineList(); |
| | | }, |
| | | methods: { |
| | | getExanineList() { |
| | | this.data.searchParams.reviewStatus = this.isReadOnly ? 1 : null; |
| | | this.data.searchParams.emergType = this.checked ? 1 : 2; |
| | | this.data.searchParams.warningLevel = this.selectedSaleAnalysis =='red' ? 1 : this.selectedSaleAnalysis =='orange' ? 2: this.selectedSaleAnalysis =='yellow'? 3 : 4; |
| | | getExamine(this.data).then(res => { |
| | | if(res.code == 100) { |
| | | this.examineList = res.data ? res.data : []; |
| | | console.log("res111111",res); |
| | | this.examineCopy = this.examineList; |
| | | if(this.examineList.length > 0) { |
| | | |
| | | this.examineList.forEach((item, index) => { |
| | | this.examineList[index].colorContent = this.data.searchParams.warningLevel == 1 ? '红色预警': this.data.searchParams.warningLevel == 2 ? '橙色预警': this.data.searchParams.warningLevel == 3 ? '黄色预警':'蓝色预警'; |
| | | this.examineList[index].buttonContent = item.reviewStatus == 1 ? '待审核': item.reviewStatus == 2 ? '已审核通过' : '已驳回'; |
| | | this.examineList[index].role = 'leader'; |
| | | this.examineList[index].warningLevel = this.data.searchParams.warningLevel; |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | handleButtonClick(button) { |
| | | this.selectedSaleAnalysis = button.label; |
| | | this.getExanineList(); |
| | | }, |
| | | chooseRead(e) { |
| | | this.isReadOnly = e; |
| | | this.getExanineList(); |
| | | // if(e) { |
| | | // this.examineList = this.examineList.filter(item => item.reviewStatus == 1); |
| | | // }else { |
| | | // this.getExanineList(); |
| | | // } |
| | | }, |
| | | toDetail(item) { |
| | | console.log("item",item) |
| | | uni.navigateTo({ |
| | | url: `/pages/tabBar/notice/detail?data=` + encodeURIComponent(JSON.stringify(item)) |
| | | }) |
| | | }, |
| | | //下拉刷新 |
| | | onPullDownRefresh() { |
| | | console.log('refresh'); |
| | | setTimeout(() => { |
| | | uni.stopPullDownRefresh(); |
| | | this.getExanineList(); |
| | | }, 1000); |
| | | }, |
| | | clickSwitch(e) { |
| | | this.getExanineList(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style> |
| | | .box { |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .fix{ |
| | | position: sticky; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | z-index: 1; |
| | | } |
| | | .navBarBox .navBar { |
| | | background-color:lightgrey; |
| | | height: 25px; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | .barText{ |
| | | text-align: center; |
| | | width: 85%; |
| | | font-size: 16px; |
| | | /* text-align: center; */ |
| | | font-weight: 600; |
| | | } |
| | | .statusBar{ |
| | | background-color:lightgrey; |
| | | } |
| | | .contentList{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .buttonGroup{ |
| | | margin: 18px 12px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | .buttonItem{ |
| | | margin-left:5px; |
| | | color: white; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 47px; |
| | | height: 30px; |
| | | border-radius: 5px; |
| | | } |
| | | .active { |
| | | border: 1px solid gray; |
| | | } |
| | | .red { |
| | | background-color: red; |
| | | } |
| | | .orange { |
| | | background-color: rgb(251, 158, 13); |
| | | } |
| | | .yellow { |
| | | background-color: rgb(255, 223, 37); |
| | | } |
| | | .blue { |
| | | background-color: rgb(2, 167, 240); |
| | | } |
| | | .switchBtn{ |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .listHead{ |
| | | display: flex; |
| | | align-items: center; |
| | | background-color:lightgrey; |
| | | height: 35px; |
| | | } |
| | | .listContent{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 10px 10px; |
| | | } |
| | | .itemContent{ |
| | | font-size: 16px; |
| | | color: gray; |
| | | margin-top: 10px; |
| | | border-bottom: 1px solid lightgrey; |
| | | |
| | | } |
| | | .content{ |
| | | text-overflow: ellipsis; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | } |
| | | .buttonCo{ |
| | | margin-top: 5px; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <!-- 自定义导航栏 --> |
| | | <view class="navBarBox"> |
| | | <!-- 状态栏占位 --> |
| | | <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view> |
| | | <!-- 真正的导航栏内容 --> |
| | | <view style="display: flex; flex-direction: column;"> |
| | | <view class="navBar"> |
| | | <u-icon name="arrow-left" color="black" size="17" @click="goBack" /> |
| | | <view class="barText">信息详情</view> |
| | | </view> |
| | | |
| | | <view class="divider"></view> |
| | | </view> |
| | | </view> |
| | | <!-- 页面内容 --> |
| | | <view style="padding: 10px 15px;display: flex;flex-direction: column;"> |
| | | <text style="font-size: 18px;"><b>标题:</b>{{detailData.title}}</text> |
| | | <text class="textTop"><b>类别:</b>{{detailData.disaster}}</text> |
| | | <view style="display: flex;align-items: center;" class="textTop"> |
| | | <text><b>级别:</b></text> |
| | | <u-tag |
| | | :color="detailData.warningLevel === 3 ? 'rgb(255, 244, 88)' :detailData.warningLevel === 2 ? 'orange':detailData.warningLevel === 1 ?'red':'blue'" |
| | | :text="detailData.warningLevel === 3 ? '黄色' : detailData.warningLevel === 2 ? '橙色': detailData.warningLevel === 1 ?'红色':'蓝色'" |
| | | :bg-color="detailData.warningLevel === 3 ? 'rgb(254, 255, 230)' :detailData.warningLevel === 2 ? 'rgb(255, 210, 179)':detailData.warningLevel === 1 ?'rgb(255, 128, 128)':'rgb(121, 150, 255)'" |
| | | border-color="white"> |
| | | </u-tag> |
| | | </view> |
| | | <text class="textTop"><b>发布单位:</b>{{detailData.publishingUnit}}</text> |
| | | <text class="textTop"><b>短信内容:</b><i style="background-color: rgb(240, 248, 255);">{{detailData.content}}发布单位:{{detailData.publishingUnit}}</i></text> |
| | | <view style="display: flex;"> |
| | | <text class="textTop" style="width: 76px;" ><b>附件内容:</b></text> |
| | | <view class="attache"> |
| | | <view v-for="(item, index) in detailData.attachments" :key="index" > |
| | | |
| | | <view style="display: flex;margin-top: 10px;" @click="openFile(item)"> |
| | | <u-icon name="attach" color="#2979ff" size="20"></u-icon> {{item.attachementName}} |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <text class="textTop" v-if="detailData.role == 'leader'"><b>信息提交人:</b>{{detailData.infoSubmitter}}</text> |
| | | <view class="textTop" v-if="detailData.role == 'leader'"> |
| | | <text ><b>审核状态:</b></text> |
| | | <text v-if="detailData.reviewStatus == 1" class="responseStatus" |
| | | style='color: red;'>待审核</text> |
| | | <text v-else-if="detailData.reviewStatus == 2" class="responseStatus" |
| | | style='color: rgb(17, 204, 33);'>已审核通过</text> |
| | | <text v-else class="responseStatus" |
| | | style='color: rgb(153, 148, 143);'>已驳回</text> |
| | | </view> |
| | | <view class="textTop" v-else> |
| | | <text ><b>响应状态:</b></text> |
| | | <text v-if="detailData.responseStatus == 1" class="responseStatus" |
| | | style='background-color:rgb(247, 108, 125);color: white;'>待叫应</text> |
| | | <text v-else-if="detailData.responseStatus == 2" class="responseStatus" |
| | | style='background-color:limegreen'>已叫应</text> |
| | | <text v-else class="responseStatus" |
| | | style='background-color:rgb(247, 108, 125); color: white;'>超时未叫应</text> |
| | | </view> |
| | | <view v-if="detailData.role == 'leader' && detailData.reviewStatus == 1" class="btn"> |
| | | <u-button |
| | | style="background-color:rgb(6, 202, 23);color: white;width: 180px;" |
| | | @click="approved" |
| | | >审核通过</u-button> |
| | | <u-button |
| | | style="background-color:rgb(247, 108, 125);color: white;width: 180px;" |
| | | @click="reject" |
| | | >审核驳回</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import VUE_APP_BASE_URL from '../../../common/constant.js' |
| | | import { submit } from '../../../api/examine.js' |
| | | export default { |
| | | data() { |
| | | return { |
| | | // 状态栏高度 |
| | | statusBarHeight: 0, |
| | | key: 1, |
| | | detailData: { |
| | | id: null, |
| | | warnInfoId: null, |
| | | disasterType: null, |
| | | warningLevel: null, |
| | | title: "", |
| | | content: "", |
| | | publishingUnit: "", |
| | | attachments: [], |
| | | responseStatus: null |
| | | }, |
| | | submitData: { |
| | | id: null, |
| | | reviewStatus: null |
| | | } |
| | | } |
| | | }, |
| | | onLoad:function(options){ |
| | | //获取手机状态栏高度 |
| | | this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight']; |
| | | let test = options.data && JSON.parse(decodeURIComponent(options.data)); |
| | | this.detailData = test; |
| | | console.log("wwwwwwww",this.detailData) |
| | | if(this.detailData.role == 'leader') { |
| | | this.detailData.attachments = this.detailData.attachment; |
| | | if (this.detailData.attachments){ |
| | | this.detailData.attachments.forEach((item,index) => { |
| | | item.attachementName = this.detailData.attachment[index].attachmentName; |
| | | }) |
| | | } |
| | | |
| | | |
| | | } |
| | | this.detailData.disaster = test.disasterType == 1 ? '地震': test.disasterType == 2 ? '洪涝' : test.disasterType == 3 ? '气象' : test.disasterType == 4 ? '泥石流': test.disasterType == 5 ? '水旱': '森林草原火灾'; |
| | | }, |
| | | methods: { |
| | | goBack() { |
| | | console.log("1111") |
| | | uni.navigateBack({ |
| | | url:'./notice/notice' |
| | | }); |
| | | }, |
| | | //审核通过 |
| | | approved() { |
| | | this.submitData.id = this.detailData.id; |
| | | this.submitData.reviewStatus = 2; |
| | | submit(this.submitData).then(res => { |
| | | if(res.code==100) { |
| | | this.goBack(); |
| | | } |
| | | }); |
| | | }, |
| | | //审核驳回 |
| | | reject() { |
| | | this.submitData.id = this.detailData.id; |
| | | this.submitData.reviewStatus = 3; |
| | | submit(this.submitData).then(res => { |
| | | if(res.code==100) { |
| | | this.goBack(); |
| | | } |
| | | }) |
| | | }, |
| | | openFile(item) { |
| | | let fileUrl = ''; |
| | | console.log("iiii",item) |
| | | if(item.role == 'leader'){ |
| | | fileUrl = VUE_APP_BASE_URL + item.attachment; |
| | | console.log("url",fileUrl) |
| | | }else { |
| | | fileUrl = VUE_APP_BASE_URL + item.attachement; |
| | | console.log("url",VUE_APP_BASE_URL + item.attachement) |
| | | } |
| | | |
| | | uni.downloadFile({ |
| | | url: encodeURI('http://192.168.0.38:8086/uploadtest/2023/naturalDisaster/Warninginfo/0620/abc051b6ee66402d98e7b27216662d17.pdf'), |
| | | header: { |
| | | 'Content-type': 'application/json', |
| | | 'tk':uni.getStorageSync('tk'), |
| | | 'uid': uni.getStorageSync('uid') |
| | | }, |
| | | success:function(res){ |
| | | console.log("下载res",res); |
| | | var filePath = res.tempFilePath; |
| | | const sidx = filePath.lastIndexOf('('); |
| | | const eidx = filePath.lastIndexOf(')'); |
| | | // 用于处理文档打开问题(ps:第一次打开 第二次无法打开问题) |
| | | if (sidx > -1 && eidx > -1) { |
| | | const restr = filePath.substr(sidx, eidx - sidx + 1); |
| | | filePath = filePath.replace(restr, ''); |
| | | } |
| | | // plus.runtime.openFile(filePath) |
| | | uni.openDocument({ |
| | | filePath: escape(filePath), |
| | | success:function(){ |
| | | console.log('成功') |
| | | }, |
| | | fail:function(){ |
| | | uni.showToast({ |
| | | icon: 'none', |
| | | title: '暂不支持此类型', |
| | | duration: 2000 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | a{ |
| | | text-decoration: none; |
| | | } |
| | | .navBarBox .navBar { |
| | | /* background-color:lightgrey; */ |
| | | height: 30px; |
| | | display: flex; |
| | | flex-direction: row; |
| | | /* justify-content: center; */ |
| | | align-items: center; |
| | | /* padding-top:5px ; */ |
| | | padding: 5px 8px; |
| | | } |
| | | .barText{ |
| | | margin-left: 36%; |
| | | font-weight: 600; |
| | | font-size: 18px; |
| | | |
| | | } |
| | | .navBarBox .navBar .logo { |
| | | width: 82rpx; |
| | | height: 82rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | .textTop{ |
| | | margin-top: 20px; |
| | | font-size: 15px; |
| | | |
| | | } |
| | | .attache{ |
| | | margin-top: 10px; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .responseStatus{ |
| | | padding:5px; |
| | | color:#2a2a2a; |
| | | border-radius: 5px; |
| | | } |
| | | .divider{ |
| | | height: 1px; |
| | | width: 93%; |
| | | background-color: lightgray; |
| | | margin-left: 15px; |
| | | } |
| | | .btn{ |
| | | margin-top: 80px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-around; |
| | | width: 100%; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <u-popup :show="show" @open="open" mode="center" customStyle="border-radius: 16rpx"> |
| | | <view class="dialog"> |
| | | <view class="head"> |
| | | <text><b>回执</b></text> |
| | | <u-icon name="close" color="#black" size="18" @click="close" ></u-icon> |
| | | </view> |
| | | <text class="content">确认已经安排部署?</text> |
| | | <view class="bottom"> |
| | | <u-button @click="close" style="width: 70px; margin-left: 40px;">取消</u-button> |
| | | <u-button style="width: 130px" type="primary" @click="confirm">确认已安全部署</u-button> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { confirm } from '../../../api/notice'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | show:false, |
| | | id: '' |
| | | } |
| | | }, |
| | | |
| | | methods: { |
| | | open() { |
| | | this.show = true; |
| | | console.log("id",this.id); |
| | | }, |
| | | close(){ |
| | | this.$emit('close'); |
| | | this.show = false; |
| | | }, |
| | | confirm() { |
| | | //确认调接口 |
| | | confirm({id: this.id}).then(res => { |
| | | if(res.code == 100) { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | title: '部署成功' |
| | | }); |
| | | this.$emit('close'); |
| | | this.show = false; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .dialog{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 250px; |
| | | height: 170px; |
| | | } |
| | | .head{ |
| | | font-size: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 10px 10px; |
| | | } |
| | | .content{ |
| | | padding: 20px 10px; |
| | | } |
| | | .bottom{ |
| | | margin-top: 10px; |
| | | display: flex; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="box" > |
| | | <!-- 自定义导航栏 --> |
| | | <view class="navBarBox fix"> |
| | | <!-- 状态栏占位 --> |
| | | <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view> |
| | | <!-- 真正的导航栏内容 --> |
| | | <view class="navBar" > |
| | | <view class="barText">{{user.name}}收到的工作通知</view> |
| | | <!-- <view style="flex: 1;" @click="loginOut">退出</view> --> |
| | | </view> |
| | | </view> |
| | | <!-- 页面内容 --> |
| | | <view style="display: flex;flex-direction: column;"> |
| | | <view class="buttonGroup"> |
| | | <view style="display: flex;"> |
| | | <view v-for="(button, index) in buttons" :key="index" class="buttonItem" |
| | | :class="{ 'active': selectedSaleAnalysis === button.label, |
| | | 'red': button.label === 'red', |
| | | 'orange':button.label === 'orange', |
| | | 'yellow':button.label === 'yellow', |
| | | 'blue': button.label === 'blue'}" |
| | | @click="handleButtonClick(button)"> |
| | | {{ button.name }} |
| | | </view> |
| | | </view> |
| | | <view class="switchBtn"> |
| | | <text style="margin-right: 7px;">是否紧临</text> |
| | | <u-switch v-model="checked" size="20" @change="clickSwitch"></u-switch> |
| | | </view> |
| | | </view> |
| | | <view class="noticeList"> |
| | | <view class="listHead"> |
| | | <u-checkbox-group style="margin-left: 15px;"> |
| | | <u-checkbox v-model="isReadOnly" @change="chooseRead"></u-checkbox>只显示未读 |
| | | </u-checkbox-group> |
| | | </view> |
| | | <view class="listContent" v-if="noticeList.length > 0" > |
| | | <view v-for="(item, index) in noticeList" :key="index" class="itemContent" > |
| | | <view class="content" v-if="item.isRead" > |
| | | <text style="color:rgb(17, 204, 33);" @click="toDetail(item)">[已读]</text> |
| | | <text @click="toDetail(item)">[{{item.colorContent}}]</text> |
| | | <text @click="toDetail(item)">{{item.title}},{{item.content}}</text> |
| | | <view v-if="item.isRead" style="float: right; width: 80px;margin-top: 3px;"> |
| | | <u-button @click="toDetail(item)"v-if="item.buttonContent == '已叫应'" size="mini" style="margin-bottom: 10px;background-color:rgb(17, 204, 33);color: white;"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button v-else-if="item.buttonContent == '未叫应'" type="error" size="mini" style="margin-bottom: 10px;" @click="openDialog(item)"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button @click="toDetail(item)" v-else type="error" size="mini" style="margin-bottom: 10px;"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | <view class="contentNoRead" v-else> |
| | | <u-badge :is-dot="true" type="error" style="position: absolute;"></u-badge> |
| | | <text style="color: red;margin-left:10px;" @click="toDetail(item)">[未读]</text> |
| | | <text @click="toDetail(item)">[{{item.colorContent}}]</text> |
| | | <text @click="toDetail(item)">{{item.title}},{{item.content}}</text> |
| | | <view style="float: right; width: 80px;margin-top: 3px;"> |
| | | <u-button @click="toDetail(item)" v-if="item.buttonContent == '已叫应'" size="mini" style="margin-bottom: 10px;background-color:rgb(17, 204, 33);color: white;"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button v-else-if="item.buttonContent == '未叫应'" type="error" size="mini" style="margin-bottom: 10px;" @click="openDialog(item)"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | <u-button @click="toDetail(item)" v-else type="error" size="mini" style="margin-bottom: 10px;"> |
| | | {{item.buttonContent}} |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else> |
| | | <u-empty |
| | | mode="data" |
| | | icon="http://cdn.uviewui.com/uview/empty/data.png" |
| | | margin-top="50%"> |
| | | </u-empty> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <dia ref="showDialog" @close="close"></dia> |
| | | <tabBar :currentPagePath="page" :tabBarList="tabBarLists"></tabBar> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getNotice, update } from '../../../api/notice'; |
| | | import dia from './dialog.vue'; |
| | | import tabBar from '../tabBarIndex.vue' |
| | | export default { |
| | | components:{ |
| | | dia, |
| | | tabBar |
| | | }, |
| | | data() { |
| | | return { |
| | | tabBarLists: [], |
| | | // 状态栏高度 |
| | | statusBarHeight: 0, |
| | | checked: true, |
| | | isReadOnly: false, |
| | | showDialog: false, |
| | | data: { |
| | | pageIndex: 1, |
| | | pageSize: 1000, |
| | | searchParams: { |
| | | emergType: 1,//1-紧急;2-常规 |
| | | warningLevel: 1,//1-红色预警;2-橙色预警;3-黄色预警;4-蓝色预警 |
| | | readStatus: null//0-未读,1-已读 |
| | | } |
| | | }, |
| | | buttons: [{ |
| | | label: 'red', |
| | | name: '红' |
| | | }, |
| | | { |
| | | label: 'orange', |
| | | name: '橙' |
| | | }, |
| | | { |
| | | label: 'yellow', |
| | | name: '黄' |
| | | }, |
| | | { |
| | | label: 'blue', |
| | | name: '蓝' |
| | | }, |
| | | ], |
| | | selectedSaleAnalysis: 'red', |
| | | noticeListCopy: [], |
| | | noticeListCopyRead:[], |
| | | noticeList: [], |
| | | user: { |
| | | name: '' |
| | | }, |
| | | page: 'pages/tabBar/notice/notice' |
| | | } |
| | | }, |
| | | onShow () { |
| | | this.tabBarLists = uni.getStorageSync('tabBarList'); |
| | | this.user.name = uni.getStorageSync('user').realName + uni.getStorageSync('user').name; |
| | | // this.selectedSaleAnalysis = 'red', |
| | | this.getNoticeList(); |
| | | // this.page = this.$route.meta.pagePath; |
| | | }, |
| | | onLoad() { |
| | | //获取手机状态栏高度 |
| | | this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight']; |
| | | uni.hideTabBar(); |
| | | // uni.startPullDownRefresh(); |
| | | }, |
| | | methods: { |
| | | getNoticeList() { |
| | | this.data.searchParams.readStatus = this.isReadOnly ? 0 : null; |
| | | this.data.searchParams.emergType = this.checked ? 1 : 2; |
| | | this.data.searchParams.warningLevel = this.selectedSaleAnalysis =='red' ? 1 : this.selectedSaleAnalysis =='orange' ? 2: this.selectedSaleAnalysis =='yellow'? 3 : 4; |
| | | getNotice(this.data).then(res => { |
| | | console.log("res",res); |
| | | if (res.code == 100) { |
| | | this.noticeList = res.data ? res.data : []; |
| | | this.noticeListCopy = this.noticeList; |
| | | if (this.noticeList.length > 0) { |
| | | this.noticeList.forEach((item, index) => { |
| | | this.noticeList[index].isRead = item.readStatus == 1 ? true : false; |
| | | this.noticeList[index].colorContent = item.warningLevel == 1 ? '红色预警': item.warningLevel == 2 ? '橙色预警': item.warningLevel == 3 ? '黄色预警':'蓝色预警'; |
| | | this.noticeList[index].buttonContent = item.responseStatus == 1 ? '待叫应': item.responseStatus == 2 ? '已叫应' : '超时未叫应'; |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | handleButtonClick(button) { |
| | | this.selectedSaleAnalysis = button.label; |
| | | this.getNoticeList(); |
| | | }, |
| | | chooseRead(e) { |
| | | this.isReadOnly = e; |
| | | this.getNoticeList(); |
| | | // if(e) { |
| | | // this.noticeList = this.noticeList.filter(item => item.isRead == false); |
| | | // }else { |
| | | // this.getNoticeList(); |
| | | // } |
| | | }, |
| | | toDetail(item) { |
| | | console.log("item",item) |
| | | if (item.readStatus === 0) { |
| | | this.updateReadStatus(item); |
| | | } |
| | | uni.navigateTo({ |
| | | url: `/pages/tabBar/notice/detail?data=` + encodeURIComponent(JSON.stringify(item)) |
| | | }) |
| | | }, |
| | | updateReadStatus(item) { |
| | | update({id: item.id}).then(res => {}); |
| | | }, |
| | | openDialog(item){ |
| | | this.$refs.showDialog.id = item.id; |
| | | this.$refs.showDialog.open(); |
| | | console.log("点击",this.showDialog) |
| | | }, |
| | | close(){ |
| | | console.log("触发close") |
| | | this.getNoticeList(); |
| | | }, |
| | | loginOut() { |
| | | uni.removeStorageSync('tk'); |
| | | uni.removeStorageSync('uid'); |
| | | uni.removeStorageSync('user'); |
| | | uni.navigateTo({ |
| | | url: `/pages/index/index` |
| | | }) |
| | | }, |
| | | //下拉刷新 |
| | | onPullDownRefresh() { |
| | | console.log('refresh'); |
| | | setTimeout(() => { |
| | | uni.stopPullDownRefresh(); |
| | | this.getNoticeList(); |
| | | }, 1000); |
| | | }, |
| | | clickSwitch(e) { |
| | | this.getNoticeList(); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .box { |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .fix{ |
| | | position: sticky; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | z-index: 1; |
| | | } |
| | | .navBarBox .navBar { |
| | | background-color:lightgrey; |
| | | height: 40px; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | .barText{ |
| | | /* margin-left: 20px; */ |
| | | text-align: center; |
| | | width: 85%; |
| | | font-size: 16px; |
| | | /* text-align: center; */ |
| | | font-weight: 600; |
| | | } |
| | | .statusBar{ |
| | | background-color:lightgrey; |
| | | } |
| | | /* .navBarBox .navBar .logo { |
| | | width: 82rpx; |
| | | height: 82rpx; |
| | | margin-right: 10rpx; |
| | | } */ |
| | | .buttonGroup{ |
| | | margin: 18px 12px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | .buttonItem{ |
| | | margin-left:5px; |
| | | color: white; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 47px; |
| | | height: 30px; |
| | | border-radius: 5px; |
| | | } |
| | | .active { |
| | | border: 1px solid gray; |
| | | } |
| | | .red { |
| | | background-color: red; |
| | | } |
| | | .orange { |
| | | background-color: rgb(251, 158, 13); |
| | | } |
| | | .yellow { |
| | | background-color: rgb(255, 223, 37); |
| | | } |
| | | .blue { |
| | | background-color: rgb(2, 167, 240); |
| | | } |
| | | .switchBtn{ |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .listHead{ |
| | | display: flex; |
| | | align-items: center; |
| | | background-color:lightgrey; |
| | | height: 35px; |
| | | } |
| | | .listContent{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 10px 10px; |
| | | } |
| | | .itemContent{ |
| | | font-size: 16px; |
| | | color: gray; |
| | | margin-top: 10px; |
| | | border-bottom: 1px solid lightgrey; |
| | | |
| | | } |
| | | .content{ |
| | | text-overflow: ellipsis; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | } |
| | | .contentNoRead{ |
| | | font-size: 14px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <!-- 自定义导航栏 --> |
| | | <view class="navBarBox fix"> |
| | | <!-- 状态栏占位 --> |
| | | <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view> |
| | | <!-- 真正的导航栏内容 --> |
| | | <view class="navBar"> |
| | | <view class="barText"></view> |
| | | </view> |
| | | </view> |
| | | <!-- 页面内容 --> |
| | | <view class="responseList" v-if="responseList.length > 0"> |
| | | <view v-for="(item, index) in responseList" :key="index" class="itemContent"> |
| | | <view class="timeLeft"> |
| | | <text>{{item.time}}</text> |
| | | <text>{{item.timeMin}}</text> |
| | | </view> |
| | | <view class="contentRight"> |
| | | <text>{{item.content}}</text> |
| | | <text style="color: rgb(76, 197, 248);" @click="toDetail(item)">[查看信息详情]</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else> |
| | | <u-empty |
| | | mode="data" |
| | | icon="http://cdn.uviewui.com/uview/empty/data.png" |
| | | margin-top="50%"> |
| | | </u-empty> |
| | | </view> |
| | | <tabBar :currentPagePath="page"></tabBar> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getResponse, getDetail } from '../../../api/response.js' |
| | | import tabBar from '../tabBarIndex.vue' |
| | | export default { |
| | | components:{ |
| | | tabBar |
| | | }, |
| | | data() { |
| | | return { |
| | | data: { |
| | | pageIndex: 1, |
| | | pageSize: 1000 |
| | | }, |
| | | // 状态栏高度 |
| | | statusBarHeight: 0, |
| | | responseList: [], |
| | | page: 'pages/tabBar/response/response' |
| | | } |
| | | }, |
| | | onShow () { |
| | | this.getResponseList(); |
| | | }, |
| | | onLoad() { |
| | | //获取手机状态栏高度 |
| | | this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight']; |
| | | uni.hideTabBar(); |
| | | }, |
| | | methods: { |
| | | getResponseList() { |
| | | getResponse(this.data).then(res => { |
| | | console.log("res",res); |
| | | if (res.code === 100) { |
| | | this.responseList = res.data ? res.data : []; |
| | | if (this.responseList.length > 0) { |
| | | this.responseList.forEach((item, index) => { |
| | | this.responseList[index].time = item.responseTime.substring(0,10); |
| | | this.responseList[index].timeMin = item.responseTime.substring(10,19); |
| | | this.responseList[index].content = item.receiveUnit + " " + item.recipienterName + " " + "在" + item.title + ' 进行了“已安排部署”叫应。'; |
| | | }) |
| | | } |
| | | }else { |
| | | this.responseList = []; |
| | | } |
| | | }).catch(err=>{}) |
| | | }, |
| | | toDetail(item) { |
| | | console.log("de",item) |
| | | getDetail({id: item.id}).then(res => { |
| | | if(res.code == 100) { |
| | | uni.navigateTo({ |
| | | url: `/pages/tabBar/notice/detail?data=` + encodeURIComponent(JSON.stringify(res.data)) |
| | | }) |
| | | } |
| | | }); |
| | | }, |
| | | //下拉刷新 |
| | | onPullDownRefresh() { |
| | | console.log('refresh'); |
| | | setTimeout(() => { |
| | | uni.stopPullDownRefresh(); |
| | | this.getResponseList(); |
| | | }, 1000); |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .navBarBox .navBar { |
| | | background-color:lightgrey; |
| | | height: 15px; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | .fix{ |
| | | position: sticky; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | z-index: 1; |
| | | } |
| | | .statusBar{ |
| | | background-color:lightgrey; |
| | | } |
| | | .responseList{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 20px 15px; |
| | | } |
| | | .itemContent{ |
| | | display: flex; |
| | | border-bottom: 1px lightgrey solid; |
| | | margin-top: 15px; |
| | | } |
| | | .timeLeft{ |
| | | border-radius: 13px; |
| | | padding: 15px 15px; |
| | | background-color: rgb(174, 228, 255) ; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | .contentRight{ |
| | | flex: 1; |
| | | font-size: 18px; |
| | | margin: 0 5px 15px 8px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <view class="tabBar_css"> |
| | | <u-tabbar |
| | | :value="currentPagePath" |
| | | :fixed="false" |
| | | :placeholder="false" |
| | | :safeAreaInsetBottom="false" |
| | | activeColor="#48bff4" |
| | | > |
| | | <u-tabbar-item v-for="(item, index) in tabBarList" |
| | | :key="index" |
| | | :text="item.text" |
| | | :name="item.pagePath" |
| | | @click="click_page" |
| | | > |
| | | <image class="u-page__item__slot-icon" slot="inactive-icon" :src="item.iconPath"></image> |
| | | <image class="u-page__item__slot-icon" slot="active-icon" :src="item.selectedIconPath"></image> |
| | | </u-tabbar-item> |
| | | </u-tabbar> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import {mapGetters} from 'vuex' |
| | | import store from '@/store/index.js' |
| | | export default { |
| | | name:"tabBar", |
| | | props: { |
| | | currentPagePath: String, |
| | | tabBarList: { |
| | | default: function() { |
| | | return uni.getStorageSync('tabBarList') |
| | | } |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | } |
| | | }, |
| | | methods: { |
| | | click_page(item){ |
| | | let page = '/' + item; |
| | | uni.switchTab({ |
| | | url: page, |
| | | success:function(res){ |
| | | console.log(res); |
| | | console.log("成功") |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .tabBar_css{ |
| | | position: fixed; |
| | | bottom: 0; |
| | | background-color: red; |
| | | z-index: 9999; |
| | | width: 100%; |
| | | } |
| | | .u-page__item__slot-icon{ |
| | | width: 24px; |
| | | height: 24px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | const user_leader = [ |
| | | { |
| | | "pagePath": "pages/tabBar/examine/examine", |
| | | "iconPath": "/static/notice1.png", |
| | | "selectedIconPath": "/static/notice1-selected.png", |
| | | "text": "通知审核" |
| | | }, |
| | | { |
| | | "pagePath": "pages/tabBar/count/count", |
| | | "iconPath": "/static/notice1.png", |
| | | "selectedIconPath": "/static/notice1-selected.png", |
| | | "text": "信息统计" |
| | | } |
| | | ] |
| | | |
| | | const user_other = [ |
| | | { |
| | | "pagePath": "pages/tabBar/notice/notice", |
| | | "iconPath": "/static/notice1.png", |
| | | "selectedIconPath": "/static/notice1-selected.png", |
| | | "text": "工作通知" |
| | | }, |
| | | { |
| | | "pagePath": "pages/tabBar/response/response", |
| | | "iconPath": "/static/mine1.png", |
| | | "selectedIconPath": "/static/mine1-selected.png", |
| | | "text": "我的叫应" |
| | | } |
| | | ] |
| | | |
| | | export default { |
| | | user_leader, |
| | | user_other |
| | | } |
对比新文件 |
| | |
| | | @font-face { |
| | | font-family: "customicons"; /* Project id 2878519 */ |
| | | src:url('/static/customicons.ttf') format('truetype'); |
| | | } |
| | | |
| | | .customicons { |
| | | font-family: "customicons" !important; |
| | | } |
| | | |
| | | .youxi:before { |
| | | content: "\e60e"; |
| | | } |
| | | |
| | | .wenjian:before { |
| | | content: "\e60f"; |
| | | } |
| | | |
| | | .zhuanfa:before { |
| | | content: "\e610"; |
| | | } |
对比新文件 |
| | |
| | | // import tabBar from './modules/tabBar.js' |
| | | // const getters = { |
| | | // tabBarList : state => state.tabBar.list |
| | | // } |
| | | |
| | | // export default getters |
对比新文件 |
| | |
| | | // import Vue from 'vue' |
| | | // import Vuex from 'vuex' |
| | | // import tabBar from './modules/tabBar.js' |
| | | // import getters from './getters.js' |
| | | |
| | | // Vue.use(Vuex) |
| | | |
| | | // const store = new Vuex.Store({ |
| | | // modules: { |
| | | // tabBar |
| | | // }, |
| | | // getters |
| | | // }) |
| | | |
| | | // export default store |
| | | import Vue from 'vue' |
| | | import Vuex from 'vuex' |
| | | Vue.use(Vuex) |
| | | import tabBar from '@/pages/tabBar/utils/tabBar.js' // 引入刚刚创建的tabBar.js |
| | | const store = new Vuex.Store({ |
| | | state: { |
| | | tabBarList: [], |
| | | }, |
| | | getters: { |
| | | getTabBarList(state) { |
| | | console.log("state",state) |
| | | return state; |
| | | } |
| | | }, |
| | | mutations:{ |
| | | // 底部tabbar |
| | | setRoleId(state,data){ |
| | | state.tabBarList = tabBar[data]; |
| | | uni.setStorageSync('tabBarList', tabBar[data]) // 根据登录时传过来的值,存储对应的tabbarlist |
| | | }, |
| | | } |
| | | }) |
| | | export default store |
对比新文件 |
| | |
| | | // import tabBar from '../../pages/tabBar/utils/tabBar.js'; |
| | | |
| | | // // //测试 |
| | | |
| | | // let temp = ''; |
| | | // temp = uni.getStorageSync('roleName') == '工作人员' ? 'user_other': 'user_leader'; |
| | | |
| | | // // let temp = 'user_leader'; |
| | | // // let temp = 'user_other'; |
| | | // let type = temp; |
| | | // console.log("typeeeeeeeeeeeeeeeeeeeeeeeeeeeeexxxxxxxxx",type) |
| | | // const state = { |
| | | // list: tabBar[type] |
| | | // } |
| | | |
| | | // export default{ |
| | | // namespaced: true, |
| | | // state |
| | | // } |
对比新文件 |
| | |
| | | @import '@/uni_modules/uni-scss/variables.scss'; |
| | | @import '@/uni_modules/uview-ui/theme.scss'; |
对比新文件 |
| | |
| | | ## 1.2.2(2023-01-28) |
| | | - 修复 运行/打包 控制台警告问题 |
| | | ## 1.2.1(2022-09-05) |
| | | - 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473) |
| | | ## 1.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge) |
| | | ## 1.1.7(2021-11-08) |
| | | - 优化 升级ui |
| | | - 修改 size 属性默认值调整为 small |
| | | - 修改 type 属性,默认值调整为 error,info 替换 default |
| | | ## 1.1.6(2021-09-22) |
| | | - 修复 在字节小程序上样式不生效的 bug |
| | | ## 1.1.5(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.1.4(2021-07-29) |
| | | - 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性 |
| | | ## 1.1.3(2021-06-24) |
| | | - 优化 示例项目 |
| | | ## 1.1.1(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.1.0(2021-05-12) |
| | | - 新增 uni-badge 的 absolute 属性,支持定位 |
| | | - 新增 uni-badge 的 offset 属性,支持定位偏移 |
| | | - 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 |
| | | - 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ |
| | | - 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 |
| | | ## 1.0.7(2021-05-07) |
| | | - 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug |
| | | - 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug |
| | | - 新增 uni-badge 属性 custom-style, 支持自定义样式 |
| | | ## 1.0.6(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-badge--x"> |
| | | <slot /> |
| | | <text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]" |
| | | class="uni-badge" @click="onClick()">{{displayValue}}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * Badge 数字角标 |
| | | * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=21 |
| | | * @property {String} text 角标内容 |
| | | * @property {String} size = [normal|small] 角标内容 |
| | | * @property {String} type = [info|primary|success|warning|error] 颜色类型 |
| | | * @value info 灰色 |
| | | * @value primary 蓝色 |
| | | * @value success 绿色 |
| | | * @value warning 黄色 |
| | | * @value error 红色 |
| | | * @property {String} inverted = [true|false] 是否无需背景颜色 |
| | | * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+ |
| | | * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上 |
| | | * @value rightTop 右上 |
| | | * @value rightBottom 右下 |
| | | * @value leftTop 左上 |
| | | * @value leftBottom 左下 |
| | | * @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px |
| | | * @property {String} isDot = [true|false] 是否显示为一个小点 |
| | | * @event {Function} click 点击 Badge 触发事件 |
| | | * @example <uni-badge text="1"></uni-badge> |
| | | */ |
| | | |
| | | export default { |
| | | name: 'UniBadge', |
| | | emits: ['click'], |
| | | props: { |
| | | type: { |
| | | type: String, |
| | | default: 'error' |
| | | }, |
| | | inverted: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | isDot: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | maxNum: { |
| | | type: Number, |
| | | default: 99 |
| | | }, |
| | | absolute: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | offset: { |
| | | type: Array, |
| | | default () { |
| | | return [0, 0] |
| | | } |
| | | }, |
| | | text: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | size: { |
| | | type: String, |
| | | default: 'small' |
| | | }, |
| | | customStyle: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return {}; |
| | | }, |
| | | computed: { |
| | | width() { |
| | | return String(this.text).length * 8 + 12 |
| | | }, |
| | | classNames() { |
| | | const { |
| | | inverted, |
| | | type, |
| | | size, |
| | | absolute |
| | | } = this |
| | | return [ |
| | | inverted ? 'uni-badge--' + type + '-inverted' : '', |
| | | 'uni-badge--' + type, |
| | | 'uni-badge--' + size, |
| | | absolute ? 'uni-badge--absolute' : '' |
| | | ].join(' ') |
| | | }, |
| | | positionStyle() { |
| | | if (!this.absolute) return {} |
| | | let w = this.width / 2, |
| | | h = 10 |
| | | if (this.isDot) { |
| | | w = 5 |
| | | h = 5 |
| | | } |
| | | const x = `${- w + this.offset[0]}px` |
| | | const y = `${- h + this.offset[1]}px` |
| | | |
| | | const whiteList = { |
| | | rightTop: { |
| | | right: x, |
| | | top: y |
| | | }, |
| | | rightBottom: { |
| | | right: x, |
| | | bottom: y |
| | | }, |
| | | leftBottom: { |
| | | left: x, |
| | | bottom: y |
| | | }, |
| | | leftTop: { |
| | | left: x, |
| | | top: y |
| | | } |
| | | } |
| | | const match = whiteList[this.absolute] |
| | | return match ? match : whiteList['rightTop'] |
| | | }, |
| | | dotStyle() { |
| | | if (!this.isDot) return {} |
| | | return { |
| | | width: '10px', |
| | | minWidth: '0', |
| | | height: '10px', |
| | | padding: '0', |
| | | borderRadius: '10px' |
| | | } |
| | | }, |
| | | displayValue() { |
| | | const { |
| | | isDot, |
| | | text, |
| | | maxNum |
| | | } = this |
| | | return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text) |
| | | } |
| | | }, |
| | | methods: { |
| | | onClick() { |
| | | this.$emit('click'); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $uni-primary: #2979ff !default; |
| | | $uni-success: #4cd964 !default; |
| | | $uni-warning: #f0ad4e !default; |
| | | $uni-error: #dd524d !default; |
| | | $uni-info: #909399 !default; |
| | | |
| | | |
| | | $bage-size: 12px; |
| | | $bage-small: scale(0.8); |
| | | |
| | | .uni-badge--x { |
| | | /* #ifdef APP-NVUE */ |
| | | // align-self: flex-start; |
| | | /* #endif */ |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-block; |
| | | /* #endif */ |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-badge--absolute { |
| | | position: absolute; |
| | | } |
| | | |
| | | .uni-badge--small { |
| | | transform: $bage-small; |
| | | transform-origin: center center; |
| | | } |
| | | |
| | | .uni-badge { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | overflow: hidden; |
| | | box-sizing: border-box; |
| | | font-feature-settings: "tnum"; |
| | | min-width: 20px; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | flex-direction: row; |
| | | height: 20px; |
| | | padding: 0 4px; |
| | | line-height: 18px; |
| | | color: #fff; |
| | | border-radius: 100px; |
| | | background-color: $uni-info; |
| | | background-color: transparent; |
| | | border: 1px solid #fff; |
| | | text-align: center; |
| | | font-family: 'Helvetica Neue', Helvetica, sans-serif; |
| | | font-size: $bage-size; |
| | | /* #ifdef H5 */ |
| | | z-index: 999; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | |
| | | &--info { |
| | | color: #fff; |
| | | background-color: $uni-info; |
| | | } |
| | | |
| | | &--primary { |
| | | background-color: $uni-primary; |
| | | } |
| | | |
| | | &--success { |
| | | background-color: $uni-success; |
| | | } |
| | | |
| | | &--warning { |
| | | background-color: $uni-warning; |
| | | } |
| | | |
| | | &--error { |
| | | background-color: $uni-error; |
| | | } |
| | | |
| | | &--inverted { |
| | | padding: 0 5px 0 0; |
| | | color: $uni-info; |
| | | } |
| | | |
| | | &--info-inverted { |
| | | color: $uni-info; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | &--primary-inverted { |
| | | color: $uni-primary; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | &--success-inverted { |
| | | color: $uni-success; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | &--warning-inverted { |
| | | color: $uni-warning; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | &--error-inverted { |
| | | color: $uni-error; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-badge", |
| | | "displayName": "uni-badge 数字角标", |
| | | "version": "1.2.2", |
| | | "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", |
| | | "keywords": [ |
| | | "", |
| | | "badge", |
| | | "uni-ui", |
| | | "uniui", |
| | | "数字角标", |
| | | "徽章" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "快应用": { |
| | | "华为": "y", |
| | | "联盟": "y" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | ## Badge 数字角标 |
| | | > **组件名:uni-badge** |
| | | > 代码块: `uBadge` |
| | | |
| | | 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
| | | |
| | | |
对比新文件 |
| | |
| | | ## 0.1.2(2022-06-08) |
| | | - 修复 微信小程序 separator 不显示的Bug |
| | | ## 0.1.1(2022-06-02) |
| | | - 新增 支持 uni.scss 修改颜色 |
| | | ## 0.1.0(2022-04-21) |
| | | - 初始化 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-breadcrumb-item"> |
| | | <view :class="{ |
| | | 'uni-breadcrumb-item--slot': true, |
| | | 'uni-breadcrumb-item--slot-link': to && currentPage !== to |
| | | }" @click="navTo"> |
| | | <slot /> |
| | | </view> |
| | | <i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" /> |
| | | <text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | /** |
| | | * BreadcrumbItem 面包屑导航子组件 |
| | | * @property {String/Object} to 路由跳转页面路径/对象 |
| | | * @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) |
| | | */ |
| | | export default { |
| | | data() { |
| | | return { |
| | | currentPage: "" |
| | | } |
| | | }, |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | props: { |
| | | to: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | replace:{ |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | inject: { |
| | | uniBreadcrumb: { |
| | | from: "uniBreadcrumb", |
| | | default: null |
| | | } |
| | | }, |
| | | created(){ |
| | | const pages = getCurrentPages() |
| | | const page = pages[pages.length-1] |
| | | |
| | | if(page){ |
| | | this.currentPage = `/${page.route}` |
| | | } |
| | | }, |
| | | computed: { |
| | | separator() { |
| | | return this.uniBreadcrumb.separator |
| | | }, |
| | | separatorClass() { |
| | | return this.uniBreadcrumb.separatorClass |
| | | } |
| | | }, |
| | | methods: { |
| | | navTo() { |
| | | const { to } = this |
| | | |
| | | if (!to || this.currentPage === to){ |
| | | return |
| | | } |
| | | |
| | | if(this.replace){ |
| | | uni.redirectTo({ |
| | | url:to |
| | | }) |
| | | }else{ |
| | | uni.navigateTo({ |
| | | url:to |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | $uni-primary: #2979ff !default; |
| | | $uni-base-color: #6a6a6a !default; |
| | | $uni-main-color: #3a3a3a !default; |
| | | .uni-breadcrumb-item { |
| | | display: flex; |
| | | align-items: center; |
| | | white-space: nowrap; |
| | | font-size: 14px; |
| | | |
| | | &--slot { |
| | | color: $uni-base-color; |
| | | padding: 0 10px; |
| | | |
| | | &-link { |
| | | color: $uni-main-color; |
| | | font-weight: bold; |
| | | /* #ifndef APP-NVUE */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | |
| | | &:hover { |
| | | color: $uni-primary; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &--separator { |
| | | font-size: 12px; |
| | | color: $uni-base-color; |
| | | } |
| | | |
| | | &:first-child &--slot { |
| | | padding-left: 0; |
| | | } |
| | | |
| | | &:last-child &--separator { |
| | | display: none; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-breadcrumb"> |
| | | <slot /> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | /** |
| | | * Breadcrumb 面包屑导航父组件 |
| | | * @description 显示当前页面的路径,快速返回之前的任意页面 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx |
| | | * @property {String} separator 分隔符,默认为斜杠'/' |
| | | * @property {String} separatorClass 图标分隔符 class |
| | | */ |
| | | export default { |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | props: { |
| | | separator: { |
| | | type: String, |
| | | default: '/' |
| | | }, |
| | | separatorClass: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | |
| | | provide() { |
| | | return { |
| | | uniBreadcrumb: this |
| | | } |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | .uni-breadcrumb { |
| | | display: flex; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-breadcrumb", |
| | | "displayName": "uni-breadcrumb 面包屑", |
| | | "version": "0.1.2", |
| | | "description": "Breadcrumb 面包屑", |
| | | "keywords": [ |
| | | "uni-breadcrumb", |
| | | "breadcrumb", |
| | | "uni-ui", |
| | | "面包屑导航", |
| | | "面包屑" |
| | | ], |
| | | "repository": "", |
| | | "engines": { |
| | | "HBuilderX": "^3.1.0" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | }, |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "n" |
| | | }, |
| | | "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", |
| | | "阿里": "u", |
| | | "百度": "u", |
| | | "字节跳动": "u", |
| | | "QQ": "u", |
| | | "京东": "u" |
| | | }, |
| | | "快应用": { |
| | | "华为": "u", |
| | | "联盟": "u" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | ## breadcrumb 面包屑导航 |
| | | > **组件名:uni-breadcrumb** |
| | | > 代码块: `ubreadcrumb` |
| | | |
| | | 显示当前页面的路径,快速返回之前的任意页面。 |
| | | |
| | | ### 安装方式 |
| | | |
| | | 本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 |
| | | |
| | | 如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) |
| | | |
| | | ### 基本用法 |
| | | |
| | | 在 ``template`` 中使用组件 |
| | | |
| | | ```html |
| | | <uni-breadcrumb separator="/"> |
| | | <uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item> |
| | | </uni-breadcrumb> |
| | | ``` |
| | | |
| | | ```js |
| | | export default { |
| | | name: "uni-stat-breadcrumb", |
| | | data() { |
| | | return { |
| | | routes: [{ |
| | | to: '/A', |
| | | name: 'A页面' |
| | | }, { |
| | | to: '/B', |
| | | name: 'B页面' |
| | | }, { |
| | | to: '/C', |
| | | name: 'C页面' |
| | | }] |
| | | }; |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | |
| | | ## API |
| | | |
| | | ### Breadcrumb Props |
| | | |
| | | |属性名 |类型 |默认值 |说明 | |
| | | |:-: |:-: |:-: |:-: | |
| | | |separator |String |斜杠'/' |分隔符 | |
| | | |separatorClass |String | |图标分隔符 class | |
| | | |
| | | ### Breadcrumb Item Props |
| | | |
| | | |属性名 |类型 |默认值 |说明 | |
| | | |:-: |:-: |:-: |:-: | |
| | | |to |String | |路由跳转页面路径 | |
| | | |replace|Boolean | |在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) | |
| | | |
| | | |
| | | |
| | | |
| | | ## 组件示例 |
| | | |
| | | 点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb) |
对比新文件 |
| | |
| | | ## 1.4.10(2023-04-10) |
| | | - 修复 某些情况 monthSwitch 未触发的Bug |
| | | ## 1.4.9(2023-02-02) |
| | | - 修复 某些情况切换月份错误的Bug |
| | | ## 1.4.8(2023-01-30) |
| | | - 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964) |
| | | ## 1.4.7(2022-09-16) |
| | | - 优化 支持使用 uni-scss 控制主题色 |
| | | ## 1.4.6(2022-09-08) |
| | | - 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug |
| | | ## 1.4.5(2022-02-25) |
| | | - 修复 条件编译 nvue 不支持的 css 样式的Bug |
| | | ## 1.4.4(2022-02-25) |
| | | - 修复 条件编译 nvue 不支持的 css 样式的Bug |
| | | ## 1.4.3(2021-09-22) |
| | | - 修复 startDate、 endDate 属性失效的Bug |
| | | ## 1.4.2(2021-08-24) |
| | | - 新增 支持国际化 |
| | | ## 1.4.1(2021-08-05) |
| | | - 修复 弹出层被 tabbar 遮盖的Bug |
| | | ## 1.4.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.3.16(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.3.15(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | /** |
| | | * @1900-2100区间内的公历、农历互转 |
| | | * @charset UTF-8 |
| | | * @github https://github.com/jjonline/calendar.js |
| | | * @Author Jea杨(JJonline@JJonline.Cn) |
| | | * @Time 2014-7-21 |
| | | * @Time 2016-8-13 Fixed 2033hex、Attribution Annals |
| | | * @Time 2016-9-25 Fixed lunar LeapMonth Param Bug |
| | | * @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year |
| | | * @Version 1.0.3 |
| | | * @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] |
| | | * @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0] |
| | | */ |
| | | /* eslint-disable */ |
| | | var calendar = { |
| | | |
| | | /** |
| | | * 农历1900-2100的润大小信息表 |
| | | * @Array Of Property |
| | | * @return Hex |
| | | */ |
| | | lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909 |
| | | 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919 |
| | | 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929 |
| | | 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939 |
| | | 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949 |
| | | 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959 |
| | | 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969 |
| | | 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979 |
| | | 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989 |
| | | 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999 |
| | | 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009 |
| | | 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019 |
| | | 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029 |
| | | 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039 |
| | | 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049 |
| | | /** Add By JJonline@JJonline.Cn**/ |
| | | 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059 |
| | | 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069 |
| | | 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079 |
| | | 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089 |
| | | 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099 |
| | | 0x0d520], // 2100 |
| | | |
| | | /** |
| | | * 公历每个月份的天数普通表 |
| | | * @Array Of Property |
| | | * @return Number |
| | | */ |
| | | solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], |
| | | |
| | | /** |
| | | * 天干地支之天干速查表 |
| | | * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] |
| | | * @return Cn string |
| | | */ |
| | | Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'], |
| | | |
| | | /** |
| | | * 天干地支之地支速查表 |
| | | * @Array Of Property |
| | | * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] |
| | | * @return Cn string |
| | | */ |
| | | Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'], |
| | | |
| | | /** |
| | | * 天干地支之地支速查表<=>生肖 |
| | | * @Array Of Property |
| | | * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] |
| | | * @return Cn string |
| | | */ |
| | | Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'], |
| | | |
| | | /** |
| | | * 24节气速查表 |
| | | * @Array Of Property |
| | | * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] |
| | | * @return Cn string |
| | | */ |
| | | solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'], |
| | | |
| | | /** |
| | | * 1900-2100各年的24节气日期速查表 |
| | | * @Array Of Property |
| | | * @return 0x string For splice |
| | | */ |
| | | sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', |
| | | '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
| | | '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', |
| | | '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', |
| | | 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f', |
| | | '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa', |
| | | '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', |
| | | '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f', |
| | | '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
| | | '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', |
| | | '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', |
| | | '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
| | | '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722', |
| | | '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f', |
| | | '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', |
| | | '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', |
| | | '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722', |
| | | '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
| | | '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
| | | '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722', |
| | | '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
| | | '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
| | | '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', |
| | | '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', |
| | | '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', |
| | | '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', |
| | | '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', |
| | | '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
| | | '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
| | | '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', |
| | | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
| | | '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
| | | '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
| | | '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721', |
| | | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2', |
| | | '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', |
| | | '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
| | | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd', |
| | | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
| | | '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
| | | '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
| | | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', |
| | | '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
| | | '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
| | | '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721', |
| | | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5', |
| | | '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722', |
| | | '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
| | | '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', |
| | | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', |
| | | '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
| | | '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721', |
| | | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd', |
| | | '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35', |
| | | '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
| | | '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721', |
| | | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5', |
| | | '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35', |
| | | '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
| | | '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', |
| | | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35', |
| | | '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'], |
| | | |
| | | /** |
| | | * 数字转中文速查表 |
| | | * @Array Of Property |
| | | * @trans ['日','一','二','三','四','五','六','七','八','九','十'] |
| | | * @return Cn string |
| | | */ |
| | | nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'], |
| | | |
| | | /** |
| | | * 日期转农历称呼速查表 |
| | | * @Array Of Property |
| | | * @trans ['初','十','廿','卅'] |
| | | * @return Cn string |
| | | */ |
| | | nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'], |
| | | |
| | | /** |
| | | * 月份转农历称呼速查表 |
| | | * @Array Of Property |
| | | * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] |
| | | * @return Cn string |
| | | */ |
| | | nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'], |
| | | |
| | | /** |
| | | * 返回农历y年一整年的总天数 |
| | | * @param lunar Year |
| | | * @return Number |
| | | * @eg:var count = calendar.lYearDays(1987) ;//count=387 |
| | | */ |
| | | lYearDays: function (y) { |
| | | var i; var sum = 348 |
| | | for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 } |
| | | return (sum + this.leapDays(y)) |
| | | }, |
| | | |
| | | /** |
| | | * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 |
| | | * @param lunar Year |
| | | * @return Number (0-12) |
| | | * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 |
| | | */ |
| | | leapMonth: function (y) { // 闰字编码 \u95f0 |
| | | return (this.lunarInfo[y - 1900] & 0xf) |
| | | }, |
| | | |
| | | /** |
| | | * 返回农历y年闰月的天数 若该年没有闰月则返回0 |
| | | * @param lunar Year |
| | | * @return Number (0、29、30) |
| | | * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 |
| | | */ |
| | | leapDays: function (y) { |
| | | if (this.leapMonth(y)) { |
| | | return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29) |
| | | } |
| | | return (0) |
| | | }, |
| | | |
| | | /** |
| | | * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 |
| | | * @param lunar Year |
| | | * @return Number (-1、29、30) |
| | | * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 |
| | | */ |
| | | monthDays: function (y, m) { |
| | | if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1 |
| | | return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29) |
| | | }, |
| | | |
| | | /** |
| | | * 返回公历(!)y年m月的天数 |
| | | * @param solar Year |
| | | * @return Number (-1、28、29、30、31) |
| | | * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 |
| | | */ |
| | | solarDays: function (y, m) { |
| | | if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1 |
| | | var ms = m - 1 |
| | | if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29 |
| | | return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28) |
| | | } else { |
| | | return (this.solarMonth[ms]) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 农历年份转换为干支纪年 |
| | | * @param lYear 农历年的年份数 |
| | | * @return Cn string |
| | | */ |
| | | toGanZhiYear: function (lYear) { |
| | | var ganKey = (lYear - 3) % 10 |
| | | var zhiKey = (lYear - 3) % 12 |
| | | if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干 |
| | | if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支 |
| | | return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1] |
| | | }, |
| | | |
| | | /** |
| | | * 公历月、日判断所属星座 |
| | | * @param cMonth [description] |
| | | * @param cDay [description] |
| | | * @return Cn string |
| | | */ |
| | | toAstro: function (cMonth, cDay) { |
| | | var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf' |
| | | var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] |
| | | return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座 |
| | | }, |
| | | |
| | | /** |
| | | * 传入offset偏移量返回干支 |
| | | * @param offset 相对甲子的偏移量 |
| | | * @return Cn string |
| | | */ |
| | | toGanZhi: function (offset) { |
| | | return this.Gan[offset % 10] + this.Zhi[offset % 12] |
| | | }, |
| | | |
| | | /** |
| | | * 传入公历(!)y年获得该年第n个节气的公历日期 |
| | | * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 |
| | | * @return day Number |
| | | * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 |
| | | */ |
| | | getTerm: function (y, n) { |
| | | if (y < 1900 || y > 2100) { return -1 } |
| | | if (n < 1 || n > 24) { return -1 } |
| | | var _table = this.sTermInfo[y - 1900] |
| | | var _info = [ |
| | | parseInt('0x' + _table.substr(0, 5)).toString(), |
| | | parseInt('0x' + _table.substr(5, 5)).toString(), |
| | | parseInt('0x' + _table.substr(10, 5)).toString(), |
| | | parseInt('0x' + _table.substr(15, 5)).toString(), |
| | | parseInt('0x' + _table.substr(20, 5)).toString(), |
| | | parseInt('0x' + _table.substr(25, 5)).toString() |
| | | ] |
| | | var _calday = [ |
| | | _info[0].substr(0, 1), |
| | | _info[0].substr(1, 2), |
| | | _info[0].substr(3, 1), |
| | | _info[0].substr(4, 2), |
| | | |
| | | _info[1].substr(0, 1), |
| | | _info[1].substr(1, 2), |
| | | _info[1].substr(3, 1), |
| | | _info[1].substr(4, 2), |
| | | |
| | | _info[2].substr(0, 1), |
| | | _info[2].substr(1, 2), |
| | | _info[2].substr(3, 1), |
| | | _info[2].substr(4, 2), |
| | | |
| | | _info[3].substr(0, 1), |
| | | _info[3].substr(1, 2), |
| | | _info[3].substr(3, 1), |
| | | _info[3].substr(4, 2), |
| | | |
| | | _info[4].substr(0, 1), |
| | | _info[4].substr(1, 2), |
| | | _info[4].substr(3, 1), |
| | | _info[4].substr(4, 2), |
| | | |
| | | _info[5].substr(0, 1), |
| | | _info[5].substr(1, 2), |
| | | _info[5].substr(3, 1), |
| | | _info[5].substr(4, 2) |
| | | ] |
| | | return parseInt(_calday[n - 1]) |
| | | }, |
| | | |
| | | /** |
| | | * 传入农历数字月份返回汉语通俗表示法 |
| | | * @param lunar month |
| | | * @return Cn string |
| | | * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' |
| | | */ |
| | | toChinaMonth: function (m) { // 月 => \u6708 |
| | | if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1 |
| | | var s = this.nStr3[m - 1] |
| | | s += '\u6708'// 加上月字 |
| | | return s |
| | | }, |
| | | |
| | | /** |
| | | * 传入农历日期数字返回汉字表示法 |
| | | * @param lunar day |
| | | * @return Cn string |
| | | * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' |
| | | */ |
| | | toChinaDay: function (d) { // 日 => \u65e5 |
| | | var s |
| | | switch (d) { |
| | | case 10: |
| | | s = '\u521d\u5341'; break |
| | | case 20: |
| | | s = '\u4e8c\u5341'; break |
| | | break |
| | | case 30: |
| | | s = '\u4e09\u5341'; break |
| | | break |
| | | default : |
| | | s = this.nStr2[Math.floor(d / 10)] |
| | | s += this.nStr1[d % 10] |
| | | } |
| | | return (s) |
| | | }, |
| | | |
| | | /** |
| | | * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” |
| | | * @param y year |
| | | * @return Cn string |
| | | * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' |
| | | */ |
| | | getAnimal: function (y) { |
| | | return this.Animals[(y - 4) % 12] |
| | | }, |
| | | |
| | | /** |
| | | * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON |
| | | * @param y solar year |
| | | * @param m solar month |
| | | * @param d solar day |
| | | * @return JSON object |
| | | * @eg:console.log(calendar.solar2lunar(1987,11,01)); |
| | | */ |
| | | solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31 |
| | | // 年份限定、上限 |
| | | if (y < 1900 || y > 2100) { |
| | | return -1// undefined转换为数字变为NaN |
| | | } |
| | | // 公历传参最下限 |
| | | if (y == 1900 && m == 1 && d < 31) { |
| | | return -1 |
| | | } |
| | | // 未传参 获得当天 |
| | | if (!y) { |
| | | var objDate = new Date() |
| | | } else { |
| | | var objDate = new Date(y, parseInt(m) - 1, d) |
| | | } |
| | | var i; var leap = 0; var temp = 0 |
| | | // 修正ymd参数 |
| | | var y = objDate.getFullYear() |
| | | var m = objDate.getMonth() + 1 |
| | | var d = objDate.getDate() |
| | | var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000 |
| | | for (i = 1900; i < 2101 && offset > 0; i++) { |
| | | temp = this.lYearDays(i) |
| | | offset -= temp |
| | | } |
| | | if (offset < 0) { |
| | | offset += temp; i-- |
| | | } |
| | | |
| | | // 是否今天 |
| | | var isTodayObj = new Date() |
| | | var isToday = false |
| | | if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) { |
| | | isToday = true |
| | | } |
| | | // 星期几 |
| | | var nWeek = objDate.getDay() |
| | | var cWeek = this.nStr1[nWeek] |
| | | // 数字表示周几顺应天朝周一开始的惯例 |
| | | if (nWeek == 0) { |
| | | nWeek = 7 |
| | | } |
| | | // 农历年 |
| | | var year = i |
| | | var leap = this.leapMonth(i) // 闰哪个月 |
| | | var isLeap = false |
| | | |
| | | // 效验闰月 |
| | | for (i = 1; i < 13 && offset > 0; i++) { |
| | | // 闰月 |
| | | if (leap > 0 && i == (leap + 1) && isLeap == false) { |
| | | --i |
| | | isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数 |
| | | } else { |
| | | temp = this.monthDays(year, i)// 计算农历普通月天数 |
| | | } |
| | | // 解除闰月 |
| | | if (isLeap == true && i == (leap + 1)) { isLeap = false } |
| | | offset -= temp |
| | | } |
| | | // 闰月导致数组下标重叠取反 |
| | | if (offset == 0 && leap > 0 && i == leap + 1) { |
| | | if (isLeap) { |
| | | isLeap = false |
| | | } else { |
| | | isLeap = true; --i |
| | | } |
| | | } |
| | | if (offset < 0) { |
| | | offset += temp; --i |
| | | } |
| | | // 农历月 |
| | | var month = i |
| | | // 农历日 |
| | | var day = offset + 1 |
| | | // 天干地支处理 |
| | | var sm = m - 1 |
| | | var gzY = this.toGanZhiYear(year) |
| | | |
| | | // 当月的两个节气 |
| | | // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` |
| | | var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始 |
| | | var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始 |
| | | |
| | | // 依据12节气修正干支月 |
| | | var gzM = this.toGanZhi((y - 1900) * 12 + m + 11) |
| | | if (d >= firstNode) { |
| | | gzM = this.toGanZhi((y - 1900) * 12 + m + 12) |
| | | } |
| | | |
| | | // 传入的日期的节气与否 |
| | | var isTerm = false |
| | | var Term = null |
| | | if (firstNode == d) { |
| | | isTerm = true |
| | | Term = this.solarTerm[m * 2 - 2] |
| | | } |
| | | if (secondNode == d) { |
| | | isTerm = true |
| | | Term = this.solarTerm[m * 2 - 1] |
| | | } |
| | | // 日柱 当月一日与 1900/1/1 相差天数 |
| | | var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 |
| | | var gzD = this.toGanZhi(dayCyclical + d - 1) |
| | | // 该日期所属的星座 |
| | | var astro = this.toAstro(m, d) |
| | | |
| | | return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro } |
| | | }, |
| | | |
| | | /** |
| | | * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON |
| | | * @param y lunar year |
| | | * @param m lunar month |
| | | * @param d lunar day |
| | | * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] |
| | | * @return JSON object |
| | | * @eg:console.log(calendar.lunar2solar(1987,9,10)); |
| | | */ |
| | | lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1 |
| | | var isLeapMonth = !!isLeapMonth |
| | | var leapOffset = 0 |
| | | var leapMonth = this.leapMonth(y) |
| | | var leapDay = this.leapDays(y) |
| | | if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 |
| | | if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值 |
| | | var day = this.monthDays(y, m) |
| | | var _day = day |
| | | // bugFix 2016-9-25 |
| | | // if month is leap, _day use leapDays method |
| | | if (isLeapMonth) { |
| | | _day = this.leapDays(y, m) |
| | | } |
| | | if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验 |
| | | |
| | | // 计算农历的时间差 |
| | | var offset = 0 |
| | | for (var i = 1900; i < y; i++) { |
| | | offset += this.lYearDays(i) |
| | | } |
| | | var leap = 0; var isAdd = false |
| | | for (var i = 1; i < m; i++) { |
| | | leap = this.leapMonth(y) |
| | | if (!isAdd) { // 处理闰月 |
| | | if (leap <= i && leap > 0) { |
| | | offset += this.leapDays(y); isAdd = true |
| | | } |
| | | } |
| | | offset += this.monthDays(y, i) |
| | | } |
| | | // 转换闰月农历 需补充该年闰月的前一个月的时差 |
| | | if (isLeapMonth) { offset += day } |
| | | // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) |
| | | var stmap = Date.UTC(1900, 1, 30, 0, 0, 0) |
| | | var calObj = new Date((offset + d - 31) * 86400000 + stmap) |
| | | var cY = calObj.getUTCFullYear() |
| | | var cM = calObj.getUTCMonth() + 1 |
| | | var cD = calObj.getUTCDate() |
| | | |
| | | return this.solar2lunar(cY, cM, cD) |
| | | } |
| | | } |
| | | |
| | | export default calendar |
对比新文件 |
| | |
| | | { |
| | | "uni-calender.ok": "ok", |
| | | "uni-calender.cancel": "cancel", |
| | | "uni-calender.today": "today", |
| | | "uni-calender.MON": "MON", |
| | | "uni-calender.TUE": "TUE", |
| | | "uni-calender.WED": "WED", |
| | | "uni-calender.THU": "THU", |
| | | "uni-calender.FRI": "FRI", |
| | | "uni-calender.SAT": "SAT", |
| | | "uni-calender.SUN": "SUN" |
| | | } |
对比新文件 |
| | |
| | | import en from './en.json' |
| | | import zhHans from './zh-Hans.json' |
| | | import zhHant from './zh-Hant.json' |
| | | export default { |
| | | en, |
| | | 'zh-Hans': zhHans, |
| | | 'zh-Hant': zhHant |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-calender.ok": "确定", |
| | | "uni-calender.cancel": "取消", |
| | | "uni-calender.today": "今日", |
| | | "uni-calender.SUN": "日", |
| | | "uni-calender.MON": "一", |
| | | "uni-calender.TUE": "二", |
| | | "uni-calender.WED": "三", |
| | | "uni-calender.THU": "四", |
| | | "uni-calender.FRI": "五", |
| | | "uni-calender.SAT": "六" |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-calender.ok": "確定", |
| | | "uni-calender.cancel": "取消", |
| | | "uni-calender.today": "今日", |
| | | "uni-calender.SUN": "日", |
| | | "uni-calender.MON": "一", |
| | | "uni-calender.TUE": "二", |
| | | "uni-calender.WED": "三", |
| | | "uni-calender.THU": "四", |
| | | "uni-calender.FRI": "五", |
| | | "uni-calender.SAT": "六" |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-calendar-item__weeks-box" :class="{ |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
| | | 'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) , |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | }" |
| | | @click="choiceDate(weeks)"> |
| | | <view class="uni-calendar-item__weeks-box-item"> |
| | | <text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text> |
| | | <text class="uni-calendar-item__weeks-box-text" :class="{ |
| | | 'uni-calendar-item--isDay-text': weeks.isDay, |
| | | 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
| | | 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | }">{{weeks.date}}</text> |
| | | <text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{ |
| | | 'uni-calendar-item--isDay-text':weeks.isDay, |
| | | 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
| | | 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | }">{{todayText}}</text> |
| | | <text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{ |
| | | 'uni-calendar-item--isDay-text':weeks.isDay, |
| | | 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
| | | 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | }">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text> |
| | | <text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{ |
| | | 'uni-calendar-item--extra':weeks.extraInfo.info, |
| | | 'uni-calendar-item--isDay-text':weeks.isDay, |
| | | 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
| | | 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | }">{{weeks.extraInfo.info}}</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { initVueI18n } from '@dcloudio/uni-i18n' |
| | | import i18nMessages from './i18n/index.js' |
| | | const { t } = initVueI18n(i18nMessages) |
| | | |
| | | export default { |
| | | emits:['change'], |
| | | props: { |
| | | weeks: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | calendar: { |
| | | type: Object, |
| | | default: () => { |
| | | return {} |
| | | } |
| | | }, |
| | | selected: { |
| | | type: Array, |
| | | default: () => { |
| | | return [] |
| | | } |
| | | }, |
| | | lunar: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | todayText() { |
| | | return t("uni-calender.today") |
| | | }, |
| | | }, |
| | | methods: { |
| | | choiceDate(weeks) { |
| | | this.$emit('change', weeks) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | $uni-font-size-base:14px; |
| | | $uni-text-color:#333; |
| | | $uni-font-size-sm:12px; |
| | | $uni-color-error: #e43d33; |
| | | $uni-opacity-disabled: 0.3; |
| | | $uni-text-color-disable:#c0c0c0; |
| | | $uni-primary: #2979ff !default; |
| | | .uni-calendar-item__weeks-box { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box-text { |
| | | font-size: $uni-font-size-base; |
| | | color: $uni-text-color; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-lunar-text { |
| | | font-size: $uni-font-size-sm; |
| | | color: $uni-text-color; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box-item { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 100rpx; |
| | | height: 100rpx; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box-circle { |
| | | position: absolute; |
| | | top: 5px; |
| | | right: 5px; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 8px; |
| | | background-color: $uni-color-error; |
| | | |
| | | } |
| | | |
| | | .uni-calendar-item--disable { |
| | | background-color: rgba(249, 249, 249, $uni-opacity-disabled); |
| | | color: $uni-text-color-disable; |
| | | } |
| | | |
| | | .uni-calendar-item--isDay-text { |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .uni-calendar-item--isDay { |
| | | background-color: $uni-primary; |
| | | opacity: 0.8; |
| | | color: #fff; |
| | | } |
| | | |
| | | .uni-calendar-item--extra { |
| | | color: $uni-color-error; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .uni-calendar-item--checked { |
| | | background-color: $uni-primary; |
| | | color: #fff; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .uni-calendar-item--multiple { |
| | | background-color: $uni-primary; |
| | | color: #fff; |
| | | opacity: 0.8; |
| | | } |
| | | .uni-calendar-item--before-checked { |
| | | background-color: #ff5a5f; |
| | | color: #fff; |
| | | } |
| | | .uni-calendar-item--after-checked { |
| | | background-color: #ff5a5f; |
| | | color: #fff; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-calendar"> |
| | | <view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view> |
| | | <view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}"> |
| | | <view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top"> |
| | | <view class="uni-calendar__header-btn-box" @click="close"> |
| | | <text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__header-btn-box" @click="confirm"> |
| | | <text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text> |
| | | </view> |
| | | </view> |
| | | <view class="uni-calendar__header"> |
| | | <view class="uni-calendar__header-btn-box" @click.stop="pre"> |
| | | <view class="uni-calendar__header-btn uni-calendar--left"></view> |
| | | </view> |
| | | <picker mode="date" :value="date" fields="month" @change="bindDateChange"> |
| | | <text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text> |
| | | </picker> |
| | | <view class="uni-calendar__header-btn-box" @click.stop="next"> |
| | | <view class="uni-calendar__header-btn uni-calendar--right"></view> |
| | | </view> |
| | | <text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text> |
| | | |
| | | </view> |
| | | <view class="uni-calendar__box"> |
| | | <view v-if="showMonth" class="uni-calendar__box-bg"> |
| | | <text class="uni-calendar__box-bg-text">{{nowDate.month}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks"> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{SUNText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{monText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{TUEText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{WEDText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{THUText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{FRIText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{SATText}}</text> |
| | | </view> |
| | | </view> |
| | | <view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex"> |
| | | <view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex"> |
| | | <calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Calendar from './util.js'; |
| | | import CalendarItem from './uni-calendar-item.vue' |
| | | |
| | | import { initVueI18n } from '@dcloudio/uni-i18n' |
| | | import i18nMessages from './i18n/index.js' |
| | | const { t } = initVueI18n(i18nMessages) |
| | | |
| | | /** |
| | | * Calendar 日历 |
| | | * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=56 |
| | | * @property {String} date 自定义当前时间,默认为今天 |
| | | * @property {Boolean} lunar 显示农历 |
| | | * @property {String} startDate 日期选择范围-开始日期 |
| | | * @property {String} endDate 日期选择范围-结束日期 |
| | | * @property {Boolean} range 范围选择 |
| | | * @property {Boolean} insert = [true|false] 插入模式,默认为false |
| | | * @value true 弹窗模式 |
| | | * @value false 插入模式 |
| | | * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容 |
| | | * @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
| | | * @property {Boolean} showMonth 是否选择月份为背景 |
| | | * @event {Function} change 日期改变,`insert :ture` 时生效 |
| | | * @event {Function} confirm 确认选择`insert :false` 时生效 |
| | | * @event {Function} monthSwitch 切换月份时触发 |
| | | * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" /> |
| | | */ |
| | | export default { |
| | | components: { |
| | | CalendarItem |
| | | }, |
| | | emits:['close','confirm','change','monthSwitch'], |
| | | props: { |
| | | date: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | selected: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | lunar: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | startDate: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | endDate: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | range: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | insert: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | showMonth: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | clearDate: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | show: false, |
| | | weeks: [], |
| | | calendar: {}, |
| | | nowDate: '', |
| | | aniMaskShow: false |
| | | } |
| | | }, |
| | | computed:{ |
| | | /** |
| | | * for i18n |
| | | */ |
| | | |
| | | okText() { |
| | | return t("uni-calender.ok") |
| | | }, |
| | | cancelText() { |
| | | return t("uni-calender.cancel") |
| | | }, |
| | | todayText() { |
| | | return t("uni-calender.today") |
| | | }, |
| | | monText() { |
| | | return t("uni-calender.MON") |
| | | }, |
| | | TUEText() { |
| | | return t("uni-calender.TUE") |
| | | }, |
| | | WEDText() { |
| | | return t("uni-calender.WED") |
| | | }, |
| | | THUText() { |
| | | return t("uni-calender.THU") |
| | | }, |
| | | FRIText() { |
| | | return t("uni-calender.FRI") |
| | | }, |
| | | SATText() { |
| | | return t("uni-calender.SAT") |
| | | }, |
| | | SUNText() { |
| | | return t("uni-calender.SUN") |
| | | }, |
| | | }, |
| | | watch: { |
| | | date(newVal) { |
| | | // this.cale.setDate(newVal) |
| | | this.init(newVal) |
| | | }, |
| | | startDate(val){ |
| | | this.cale.resetSatrtDate(val) |
| | | this.cale.setDate(this.nowDate.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | }, |
| | | endDate(val){ |
| | | this.cale.resetEndDate(val) |
| | | this.cale.setDate(this.nowDate.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | }, |
| | | selected(newVal) { |
| | | this.cale.setSelectInfo(this.nowDate.fullDate, newVal) |
| | | this.weeks = this.cale.weeks |
| | | } |
| | | }, |
| | | created() { |
| | | this.cale = new Calendar({ |
| | | selected: this.selected, |
| | | startDate: this.startDate, |
| | | endDate: this.endDate, |
| | | range: this.range, |
| | | }) |
| | | this.init(this.date) |
| | | }, |
| | | methods: { |
| | | // 取消穿透 |
| | | clean() {}, |
| | | bindDateChange(e) { |
| | | const value = e.detail.value + '-1' |
| | | this.setDate(value) |
| | | |
| | | const { year,month } = this.cale.getDate(value) |
| | | this.$emit('monthSwitch', { |
| | | year, |
| | | month |
| | | }) |
| | | }, |
| | | /** |
| | | * 初始化日期显示 |
| | | * @param {Object} date |
| | | */ |
| | | init(date) { |
| | | this.cale.setDate(date) |
| | | this.weeks = this.cale.weeks |
| | | this.nowDate = this.calendar = this.cale.getInfo(date) |
| | | }, |
| | | /** |
| | | * 打开日历弹窗 |
| | | */ |
| | | open() { |
| | | // 弹窗模式并且清理数据 |
| | | if (this.clearDate && !this.insert) { |
| | | this.cale.cleanMultipleStatus() |
| | | // this.cale.setDate(this.date) |
| | | this.init(this.date) |
| | | } |
| | | this.show = true |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.aniMaskShow = true |
| | | }, 50) |
| | | }) |
| | | }, |
| | | /** |
| | | * 关闭日历弹窗 |
| | | */ |
| | | close() { |
| | | this.aniMaskShow = false |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.show = false |
| | | this.$emit('close') |
| | | }, 300) |
| | | }) |
| | | }, |
| | | /** |
| | | * 确认按钮 |
| | | */ |
| | | confirm() { |
| | | this.setEmit('confirm') |
| | | this.close() |
| | | }, |
| | | /** |
| | | * 变化触发 |
| | | */ |
| | | change() { |
| | | if (!this.insert) return |
| | | this.setEmit('change') |
| | | }, |
| | | /** |
| | | * 选择月份触发 |
| | | */ |
| | | monthSwitch() { |
| | | let { |
| | | year, |
| | | month |
| | | } = this.nowDate |
| | | this.$emit('monthSwitch', { |
| | | year, |
| | | month: Number(month) |
| | | }) |
| | | }, |
| | | /** |
| | | * 派发事件 |
| | | * @param {Object} name |
| | | */ |
| | | setEmit(name) { |
| | | let { |
| | | year, |
| | | month, |
| | | date, |
| | | fullDate, |
| | | lunar, |
| | | extraInfo |
| | | } = this.calendar |
| | | this.$emit(name, { |
| | | range: this.cale.multipleStatus, |
| | | year, |
| | | month, |
| | | date, |
| | | fulldate: fullDate, |
| | | lunar, |
| | | extraInfo: extraInfo || {} |
| | | }) |
| | | }, |
| | | /** |
| | | * 选择天触发 |
| | | * @param {Object} weeks |
| | | */ |
| | | choiceDate(weeks) { |
| | | if (weeks.disable) return |
| | | this.calendar = weeks |
| | | // 设置多选 |
| | | this.cale.setMultiple(this.calendar.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | this.change() |
| | | }, |
| | | /** |
| | | * 回到今天 |
| | | */ |
| | | backToday() { |
| | | const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}` |
| | | const date = this.cale.getDate(new Date()) |
| | | const todayYearMonth = `${date.year}-${date.month}` |
| | | |
| | | if(nowYearMonth !== todayYearMonth) { |
| | | this.monthSwitch() |
| | | } |
| | | |
| | | this.init(date.fullDate) |
| | | this.change() |
| | | }, |
| | | /** |
| | | * 上个月 |
| | | */ |
| | | pre() { |
| | | const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate |
| | | this.setDate(preDate) |
| | | this.monthSwitch() |
| | | |
| | | }, |
| | | /** |
| | | * 下个月 |
| | | */ |
| | | next() { |
| | | const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate |
| | | this.setDate(nextDate) |
| | | this.monthSwitch() |
| | | }, |
| | | /** |
| | | * 设置日期 |
| | | * @param {Object} date |
| | | */ |
| | | setDate(date) { |
| | | this.cale.setDate(date) |
| | | this.weeks = this.cale.weeks |
| | | this.nowDate = this.cale.getInfo(date) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | $uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4); |
| | | $uni-border-color: #EDEDED; |
| | | $uni-text-color: #333; |
| | | $uni-bg-color-hover:#f1f1f1; |
| | | $uni-font-size-base:14px; |
| | | $uni-text-color-placeholder: #808080; |
| | | $uni-color-subtitle: #555555; |
| | | $uni-text-color-grey:#999; |
| | | .uni-calendar { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .uni-calendar__mask { |
| | | position: fixed; |
| | | bottom: 0; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: $uni-bg-color-mask; |
| | | transition-property: opacity; |
| | | transition-duration: 0.3s; |
| | | opacity: 0; |
| | | /* #ifndef APP-NVUE */ |
| | | z-index: 99; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-calendar--mask-show { |
| | | opacity: 1 |
| | | } |
| | | |
| | | .uni-calendar--fixed { |
| | | position: fixed; |
| | | /* #ifdef APP-NVUE */ |
| | | bottom: 0; |
| | | /* #endif */ |
| | | left: 0; |
| | | right: 0; |
| | | transition-property: transform; |
| | | transition-duration: 0.3s; |
| | | transform: translateY(460px); |
| | | /* #ifndef APP-NVUE */ |
| | | bottom: calc(var(--window-bottom)); |
| | | z-index: 99; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-calendar--ani-show { |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | .uni-calendar__content { |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .uni-calendar__header { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 50px; |
| | | border-bottom-color: $uni-border-color; |
| | | border-bottom-style: solid; |
| | | border-bottom-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar--fixed-top { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | border-top-color: $uni-border-color; |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar--fixed-width { |
| | | width: 50px; |
| | | } |
| | | |
| | | .uni-calendar__backtoday { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 25rpx; |
| | | padding: 0 5px; |
| | | padding-left: 10px; |
| | | height: 25px; |
| | | line-height: 25px; |
| | | font-size: 12px; |
| | | border-top-left-radius: 25px; |
| | | border-bottom-left-radius: 25px; |
| | | color: $uni-text-color; |
| | | background-color: $uni-bg-color-hover; |
| | | } |
| | | |
| | | .uni-calendar__header-text { |
| | | text-align: center; |
| | | width: 100px; |
| | | font-size: $uni-font-size-base; |
| | | color: $uni-text-color; |
| | | } |
| | | |
| | | .uni-calendar__header-btn-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 50px; |
| | | height: 50px; |
| | | } |
| | | |
| | | .uni-calendar__header-btn { |
| | | width: 10px; |
| | | height: 10px; |
| | | border-left-color: $uni-text-color-placeholder; |
| | | border-left-style: solid; |
| | | border-left-width: 2px; |
| | | border-top-color: $uni-color-subtitle; |
| | | border-top-style: solid; |
| | | border-top-width: 2px; |
| | | } |
| | | |
| | | .uni-calendar--left { |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .uni-calendar--right { |
| | | transform: rotate(135deg); |
| | | } |
| | | |
| | | |
| | | .uni-calendar__weeks { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .uni-calendar__weeks-item { |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-calendar__weeks-day { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 45px; |
| | | border-bottom-color: #F5F5F5; |
| | | border-bottom-style: solid; |
| | | border-bottom-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar__weeks-day-text { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .uni-calendar__box { |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-calendar__box-bg { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | } |
| | | |
| | | .uni-calendar__box-bg-text { |
| | | font-size: 200px; |
| | | font-weight: bold; |
| | | color: $uni-text-color-grey; |
| | | opacity: 0.1; |
| | | text-align: center; |
| | | /* #ifndef APP-NVUE */ |
| | | line-height: 1; |
| | | /* #endif */ |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | import CALENDAR from './calendar.js' |
| | | |
| | | class Calendar { |
| | | constructor({ |
| | | date, |
| | | selected, |
| | | startDate, |
| | | endDate, |
| | | range |
| | | } = {}) { |
| | | // 当前日期 |
| | | this.date = this.getDate(new Date()) // 当前初入日期 |
| | | // 打点信息 |
| | | this.selected = selected || []; |
| | | // 范围开始 |
| | | this.startDate = startDate |
| | | // 范围结束 |
| | | this.endDate = endDate |
| | | this.range = range |
| | | // 多选状态 |
| | | this.cleanMultipleStatus() |
| | | // 每周日期 |
| | | this.weeks = {} |
| | | // this._getWeek(this.date.fullDate) |
| | | } |
| | | /** |
| | | * 设置日期 |
| | | * @param {Object} date |
| | | */ |
| | | setDate(date) { |
| | | this.selectDate = this.getDate(date) |
| | | this._getWeek(this.selectDate.fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 清理多选状态 |
| | | */ |
| | | cleanMultipleStatus() { |
| | | this.multipleStatus = { |
| | | before: '', |
| | | after: '', |
| | | data: [] |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 重置开始日期 |
| | | */ |
| | | resetSatrtDate(startDate) { |
| | | // 范围开始 |
| | | this.startDate = startDate |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 重置结束日期 |
| | | */ |
| | | resetEndDate(endDate) { |
| | | // 范围结束 |
| | | this.endDate = endDate |
| | | } |
| | | |
| | | /** |
| | | * 获取任意时间 |
| | | */ |
| | | getDate(date, AddDayCount = 0, str = 'day') { |
| | | if (!date) { |
| | | date = new Date() |
| | | } |
| | | if (typeof date !== 'object') { |
| | | date = date.replace(/-/g, '/') |
| | | } |
| | | const dd = new Date(date) |
| | | switch (str) { |
| | | case 'day': |
| | | dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期 |
| | | break |
| | | case 'month': |
| | | if (dd.getDate() === 31 && AddDayCount>0) { |
| | | dd.setDate(dd.getDate() + AddDayCount) |
| | | } else { |
| | | const preMonth = dd.getMonth() |
| | | dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期 |
| | | const nextMonth = dd.getMonth() |
| | | // 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题 |
| | | if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){ |
| | | dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount)) |
| | | } |
| | | // 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题 |
| | | if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){ |
| | | dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount)) |
| | | } |
| | | } |
| | | break |
| | | case 'year': |
| | | dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期 |
| | | break |
| | | } |
| | | const y = dd.getFullYear() |
| | | const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0 |
| | | const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0 |
| | | return { |
| | | fullDate: y + '-' + m + '-' + d, |
| | | year: y, |
| | | month: m, |
| | | date: d, |
| | | day: dd.getDay() |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取上月剩余天数 |
| | | */ |
| | | _getLastMonthDays(firstDay, full) { |
| | | let dateArr = [] |
| | | for (let i = firstDay; i > 0; i--) { |
| | | const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() |
| | | dateArr.push({ |
| | | date: beforeDate, |
| | | month: full.month - 1, |
| | | lunar: this.getlunar(full.year, full.month - 1, beforeDate), |
| | | disable: true |
| | | }) |
| | | } |
| | | return dateArr |
| | | } |
| | | /** |
| | | * 获取本月天数 |
| | | */ |
| | | _currentMonthDys(dateData, full) { |
| | | let dateArr = [] |
| | | let fullDate = this.date.fullDate |
| | | for (let i = 1; i <= dateData; i++) { |
| | | let nowDate = full.year + '-' + (full.month < 10 ? |
| | | full.month : full.month) + '-' + (i < 10 ? |
| | | '0' + i : i) |
| | | // 是否今天 |
| | | let isDay = fullDate === nowDate |
| | | // 获取打点信息 |
| | | let info = this.selected && this.selected.find((item) => { |
| | | if (this.dateEqual(nowDate, item.date)) { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | // 日期禁用 |
| | | let disableBefore = true |
| | | let disableAfter = true |
| | | if (this.startDate) { |
| | | // let dateCompBefore = this.dateCompare(this.startDate, fullDate) |
| | | // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate) |
| | | disableBefore = this.dateCompare(this.startDate, nowDate) |
| | | } |
| | | |
| | | if (this.endDate) { |
| | | // let dateCompAfter = this.dateCompare(fullDate, this.endDate) |
| | | // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate) |
| | | disableAfter = this.dateCompare(nowDate, this.endDate) |
| | | } |
| | | let multiples = this.multipleStatus.data |
| | | let checked = false |
| | | let multiplesStatus = -1 |
| | | if (this.range) { |
| | | if (multiples) { |
| | | multiplesStatus = multiples.findIndex((item) => { |
| | | return this.dateEqual(item, nowDate) |
| | | }) |
| | | } |
| | | if (multiplesStatus !== -1) { |
| | | checked = true |
| | | } |
| | | } |
| | | let data = { |
| | | fullDate: nowDate, |
| | | year: full.year, |
| | | date: i, |
| | | multiple: this.range ? checked : false, |
| | | beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate), |
| | | afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate), |
| | | month: full.month, |
| | | lunar: this.getlunar(full.year, full.month, i), |
| | | disable: !(disableBefore && disableAfter), |
| | | isDay |
| | | } |
| | | if (info) { |
| | | data.extraInfo = info |
| | | } |
| | | |
| | | dateArr.push(data) |
| | | } |
| | | return dateArr |
| | | } |
| | | /** |
| | | * 获取下月天数 |
| | | */ |
| | | _getNextMonthDays(surplus, full) { |
| | | let dateArr = [] |
| | | for (let i = 1; i < surplus + 1; i++) { |
| | | dateArr.push({ |
| | | date: i, |
| | | month: Number(full.month) + 1, |
| | | lunar: this.getlunar(full.year, Number(full.month) + 1, i), |
| | | disable: true |
| | | }) |
| | | } |
| | | return dateArr |
| | | } |
| | | |
| | | /** |
| | | * 获取当前日期详情 |
| | | * @param {Object} date |
| | | */ |
| | | getInfo(date) { |
| | | if (!date) { |
| | | date = new Date() |
| | | } |
| | | const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) |
| | | return dateInfo |
| | | } |
| | | |
| | | /** |
| | | * 比较时间大小 |
| | | */ |
| | | dateCompare(startDate, endDate) { |
| | | // 计算截止时间 |
| | | startDate = new Date(startDate.replace('-', '/').replace('-', '/')) |
| | | // 计算详细项的截止时间 |
| | | endDate = new Date(endDate.replace('-', '/').replace('-', '/')) |
| | | if (startDate <= endDate) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 比较时间是否相等 |
| | | */ |
| | | dateEqual(before, after) { |
| | | // 计算截止时间 |
| | | before = new Date(before.replace('-', '/').replace('-', '/')) |
| | | // 计算详细项的截止时间 |
| | | after = new Date(after.replace('-', '/').replace('-', '/')) |
| | | if (before.getTime() - after.getTime() === 0) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取日期范围内所有日期 |
| | | * @param {Object} begin |
| | | * @param {Object} end |
| | | */ |
| | | geDateAll(begin, end) { |
| | | var arr = [] |
| | | var ab = begin.split('-') |
| | | var ae = end.split('-') |
| | | var db = new Date() |
| | | db.setFullYear(ab[0], ab[1] - 1, ab[2]) |
| | | var de = new Date() |
| | | de.setFullYear(ae[0], ae[1] - 1, ae[2]) |
| | | var unixDb = db.getTime() - 24 * 60 * 60 * 1000 |
| | | var unixDe = de.getTime() - 24 * 60 * 60 * 1000 |
| | | for (var k = unixDb; k <= unixDe;) { |
| | | k = k + 24 * 60 * 60 * 1000 |
| | | arr.push(this.getDate(new Date(parseInt(k))).fullDate) |
| | | } |
| | | return arr |
| | | } |
| | | /** |
| | | * 计算阴历日期显示 |
| | | */ |
| | | getlunar(year, month, date) { |
| | | return CALENDAR.solar2lunar(year, month, date) |
| | | } |
| | | /** |
| | | * 设置打点 |
| | | */ |
| | | setSelectInfo(data, value) { |
| | | this.selected = value |
| | | this._getWeek(data) |
| | | } |
| | | |
| | | /** |
| | | * 获取多选状态 |
| | | */ |
| | | setMultiple(fullDate) { |
| | | let { |
| | | before, |
| | | after |
| | | } = this.multipleStatus |
| | | |
| | | if (!this.range) return |
| | | if (before && after) { |
| | | this.multipleStatus.before = '' |
| | | this.multipleStatus.after = '' |
| | | this.multipleStatus.data = [] |
| | | } else { |
| | | if (!before) { |
| | | this.multipleStatus.before = fullDate |
| | | } else { |
| | | this.multipleStatus.after = fullDate |
| | | if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); |
| | | } else { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); |
| | | } |
| | | } |
| | | } |
| | | this._getWeek(fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 获取每周数据 |
| | | * @param {Object} dateData |
| | | */ |
| | | _getWeek(dateData) { |
| | | const { |
| | | year, |
| | | month |
| | | } = this.getDate(dateData) |
| | | let firstDay = new Date(year, month - 1, 1).getDay() |
| | | let currentDay = new Date(year, month, 0).getDate() |
| | | let dates = { |
| | | lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天 |
| | | currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数 |
| | | nextMonthDays: [], // 下个月开始几天 |
| | | weeks: [] |
| | | } |
| | | let canlender = [] |
| | | const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) |
| | | dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) |
| | | canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) |
| | | let weeks = {} |
| | | // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天 |
| | | for (let i = 0; i < canlender.length; i++) { |
| | | if (i % 7 === 0) { |
| | | weeks[parseInt(i / 7)] = new Array(7) |
| | | } |
| | | weeks[parseInt(i / 7)][i % 7] = canlender[i] |
| | | } |
| | | this.canlender = canlender |
| | | this.weeks = weeks |
| | | } |
| | | |
| | | //静态方法 |
| | | // static init(date) { |
| | | // if (!this.instance) { |
| | | // this.instance = new Calendar(date); |
| | | // } |
| | | // return this.instance; |
| | | // } |
| | | } |
| | | |
| | | |
| | | export default Calendar |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-calendar", |
| | | "displayName": "uni-calendar 日历", |
| | | "version": "1.4.10", |
| | | "description": "日历组件", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "日历", |
| | | "", |
| | | "打卡", |
| | | "日历选择" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Calendar 日历 |
| | | > **组件名:uni-calendar** |
| | | > 代码块: `uCalendar` |
| | | |
| | | |
| | | 日历组件 |
| | | |
| | | > **注意事项** |
| | | > 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 |
| | | > - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js) |
| | | > - 仅支持自定义组件模式 |
| | | > - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date() |
| | | > - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意 |
| | | > - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动 |
| | | |
| | | |
| | | ### 安装方式 |
| | | |
| | | 本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 |
| | | |
| | | 如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) |
| | | |
| | | ### 基本用法 |
| | | |
| | | 在 ``template`` 中使用组件 |
| | | |
| | | ```html |
| | | <view> |
| | | <uni-calendar |
| | | :insert="true" |
| | | :lunar="true" |
| | | :start-date="'2019-3-2'" |
| | | :end-date="'2019-5-20'" |
| | | @change="change" |
| | | /> |
| | | </view> |
| | | ``` |
| | | |
| | | ### 通过方法打开日历 |
| | | |
| | | 需要设置 `insert` 为 `false` |
| | | |
| | | ```html |
| | | <view> |
| | | <uni-calendar |
| | | ref="calendar" |
| | | :insert="false" |
| | | @confirm="confirm" |
| | | /> |
| | | <button @click="open">打开日历</button> |
| | | </view> |
| | | ``` |
| | | |
| | | ```javascript |
| | | |
| | | export default { |
| | | data() { |
| | | return {}; |
| | | }, |
| | | methods: { |
| | | open(){ |
| | | this.$refs.calendar.open(); |
| | | }, |
| | | confirm(e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | ``` |
| | | |
| | | |
| | | ## API |
| | | |
| | | ### Calendar Props |
| | | |
| | | | 属性名 | 类型 | 默认值| 说明 | |
| | | | - | - | - | - | |
| | | | date | String |- | 自定义当前时间,默认为今天 | |
| | | | lunar | Boolean | false | 显示农历 | |
| | | | startDate | String |- | 日期选择范围-开始日期 | |
| | | | endDate | String |- | 日期选择范围-结束日期 | |
| | | | range | Boolean | false | 范围选择 | |
| | | | insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 | |
| | | |clearDate |Boolean |true |弹窗模式是否清空上次选择内容 | |
| | | | selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] | |
| | | |showMonth | Boolean | true | 是否显示月份为背景 | |
| | | |
| | | ### Calendar Events |
| | | |
| | | | 事件名 | 说明 |返回值| |
| | | | - | - | - | |
| | | | open | 弹出日历组件,`insert :false` 时生效|- | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | ## 组件示例 |
| | | |
| | | 点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar) |
对比新文件 |
| | |
| | | ## 1.3.1(2021-12-20) |
| | | - 修复 在vue页面下略缩图显示不正常的bug |
| | | ## 1.3.0(2021-11-19) |
| | | - 重构插槽的用法 ,header 替换为 title |
| | | - 新增 actions 插槽 |
| | | - 新增 cover 封面图属性和插槽 |
| | | - 新增 padding 内容默认内边距离 |
| | | - 新增 margin 卡片默认外边距离 |
| | | - 新增 spacing 卡片默认内边距 |
| | | - 新增 shadow 卡片阴影属性 |
| | | - 取消 mode 属性,可使用组合插槽代替 |
| | | - 取消 note 属性 ,使用actions插槽代替 |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card) |
| | | ## 1.2.1(2021-07-30) |
| | | - 优化 vue3下事件警告的问题 |
| | | ## 1.2.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.1.8(2021-07-01) |
| | | - 优化 图文卡片无图片加载时,提供占位图标 |
| | | - 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持) |
| | | - 修复 thumbnail 不存在仍然占位的 bug |
| | | ## 1.1.7(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.1.6(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}" |
| | | :style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}"> |
| | | <!-- 封面 --> |
| | | <slot name="cover"> |
| | | <view v-if="cover" class="uni-card__cover"> |
| | | <image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image> |
| | | </view> |
| | | </slot> |
| | | <slot name="title"> |
| | | <view v-if="title || extra" class="uni-card__header"> |
| | | <!-- 卡片标题 --> |
| | | <view class="uni-card__header-box" @click="onClick('title')"> |
| | | <view v-if="thumbnail" class="uni-card__header-avatar"> |
| | | <image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" /> |
| | | </view> |
| | | <view class="uni-card__header-content"> |
| | | <text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text> |
| | | <text v-if="title&&subTitle" |
| | | class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="uni-card__header-extra" @click="onClick('extra')"> |
| | | <slot name="extra"> |
| | | <text class="uni-card__header-extra-text">{{ extra }}</text> |
| | | </slot> |
| | | </view> |
| | | </view> |
| | | </slot> |
| | | <!-- 卡片内容 --> |
| | | <view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')"> |
| | | <slot></slot> |
| | | </view> |
| | | <view class="uni-card__actions" @click="onClick('actions')"> |
| | | <slot name="actions"></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * Card 卡片 |
| | | * @description 卡片视图组件 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=22 |
| | | * @property {String} title 标题文字 |
| | | * @property {String} subTitle 副标题 |
| | | * @property {Number} padding 内容内边距 |
| | | * @property {Number} margin 卡片外边距 |
| | | * @property {Number} spacing 卡片内边距 |
| | | * @property {String} extra 标题额外信息 |
| | | * @property {String} cover 封面图(本地路径需要引入) |
| | | * @property {String} thumbnail 标题左侧缩略图 |
| | | * @property {Boolean} is-full = [true | false] 卡片内容是否通栏,为 true 时将去除padding值 |
| | | * @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影 |
| | | * @property {String} shadow 卡片阴影 |
| | | * @property {Boolean} border 卡片边框 |
| | | * @event {Function} click 点击 Card 触发事件 |
| | | */ |
| | | export default { |
| | | name: 'UniCard', |
| | | emits: ['click'], |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | subTitle: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | padding: { |
| | | type: String, |
| | | default: '10px' |
| | | }, |
| | | margin: { |
| | | type: String, |
| | | default: '15px' |
| | | }, |
| | | spacing: { |
| | | type: String, |
| | | default: '0 10px' |
| | | }, |
| | | extra: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | cover: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | thumbnail: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | isFull: { |
| | | // 内容区域是否通栏 |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | isShadow: { |
| | | // 是否开启阴影 |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | shadow: { |
| | | type: String, |
| | | default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)' |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | methods: { |
| | | onClick(type) { |
| | | this.$emit('click', type) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-border-3: #EBEEF5 !default; |
| | | $uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; |
| | | $uni-main-color: #3a3a3a !default; |
| | | $uni-base-color: #6a6a6a !default; |
| | | $uni-secondary-color: #909399 !default; |
| | | $uni-spacing-sm: 8px !default; |
| | | $uni-border-color:$uni-border-3; |
| | | $uni-shadow: $uni-shadow-base; |
| | | $uni-card-title: 15px; |
| | | $uni-cart-title-color:$uni-main-color; |
| | | $uni-card-subtitle: 12px; |
| | | $uni-cart-subtitle-color:$uni-secondary-color; |
| | | $uni-card-spacing: 10px; |
| | | $uni-card-content-color: $uni-base-color; |
| | | |
| | | .uni-card { |
| | | margin: $uni-card-spacing; |
| | | padding: 0 $uni-spacing-sm; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; |
| | | background-color: #fff; |
| | | flex: 1; |
| | | |
| | | .uni-card__cover { |
| | | position: relative; |
| | | margin-top: $uni-card-spacing; |
| | | flex-direction: row; |
| | | overflow: hidden; |
| | | border-radius: 4px; |
| | | .uni-card__cover-image { |
| | | flex: 1; |
| | | // width: 100%; |
| | | /* #ifndef APP-PLUS */ |
| | | vertical-align: middle; |
| | | /* #endif */ |
| | | } |
| | | } |
| | | |
| | | .uni-card__header { |
| | | display: flex; |
| | | border-bottom: 1px $uni-border-color solid; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | padding: $uni-card-spacing; |
| | | overflow: hidden; |
| | | |
| | | .uni-card__header-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex: 1; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .uni-card__header-avatar { |
| | | width: 40px; |
| | | height: 40px; |
| | | overflow: hidden; |
| | | border-radius: 5px; |
| | | margin-right: $uni-card-spacing; |
| | | .uni-card__header-avatar-image { |
| | | flex: 1; |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | } |
| | | |
| | | .uni-card__header-content { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | flex: 1; |
| | | // height: 40px; |
| | | overflow: hidden; |
| | | |
| | | .uni-card__header-content-title { |
| | | font-size: $uni-card-title; |
| | | color: $uni-cart-title-color; |
| | | // line-height: 22px; |
| | | } |
| | | |
| | | .uni-card__header-content-subtitle { |
| | | font-size: $uni-card-subtitle; |
| | | margin-top: 5px; |
| | | color: $uni-cart-subtitle-color; |
| | | } |
| | | } |
| | | |
| | | .uni-card__header-extra { |
| | | line-height: 12px; |
| | | |
| | | .uni-card__header-extra-text { |
| | | font-size: 12px; |
| | | color: $uni-cart-subtitle-color; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .uni-card__content { |
| | | padding: $uni-card-spacing; |
| | | font-size: 14px; |
| | | color: $uni-card-content-color; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .uni-card__actions { |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | .uni-card--border { |
| | | border: 1px solid $uni-border-color; |
| | | } |
| | | |
| | | .uni-card--shadow { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | box-shadow: $uni-shadow; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-card--full { |
| | | margin: 0; |
| | | border-left-width: 0; |
| | | border-left-width: 0; |
| | | border-radius: 0; |
| | | } |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | .uni-card--full:after { |
| | | border-radius: 0; |
| | | } |
| | | |
| | | /* #endif */ |
| | | .uni-ellipsis { |
| | | /* #ifndef APP-NVUE */ |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | lines: 1; |
| | | /* #endif */ |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-card", |
| | | "displayName": "uni-card 卡片", |
| | | "version": "1.3.1", |
| | | "description": "Card 组件,提供常见的卡片样式。", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "card", |
| | | "", |
| | | "卡片" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-icons", |
| | | "uni-scss" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Card 卡片 |
| | | > **组件名:uni-card** |
| | | > 代码块: `uCard` |
| | | |
| | | 卡片视图组件。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
| | | |
| | | |
对比新文件 |
| | |
| | | ## 1.4.3(2022-01-25) |
| | | - 修复 初始化的时候 ,open 属性失效的bug |
| | | ## 1.4.2(2022-01-21) |
| | | - 修复 微信小程序resize后组件收起的bug |
| | | ## 1.4.1(2021-11-22) |
| | | - 修复 vue3中个别scss变量无法找到的问题 |
| | | ## 1.4.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse) |
| | | ## 1.3.3(2021-08-17) |
| | | - 优化 show-arrow 属性默认为true |
| | | ## 1.3.2(2021-08-17) |
| | | - 新增 show-arrow 属性,控制是否显示右侧箭头 |
| | | ## 1.3.1(2021-07-30) |
| | | - 优化 vue3下小程序事件警告的问题 |
| | | ## 1.3.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.2.2(2021-07-21) |
| | | - 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug |
| | | ## 1.2.1(2021-07-21) |
| | | - 优化 组件示例 |
| | | ## 1.2.0(2021-07-21) |
| | | - 新增 组件折叠动画 |
| | | - 新增 value\v-model 属性 ,动态修改面板折叠状态 |
| | | - 新增 title 插槽 ,可定义面板标题 |
| | | - 新增 border 属性 ,显示隐藏面板内容分隔线 |
| | | - 新增 title-border 属性 ,显示隐藏面板标题分隔线 |
| | | - 修复 resize 方法失效的Bug |
| | | - 修复 change 事件返回参数不正确的Bug |
| | | - 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法 |
| | | ## 1.1.7(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.1.6(2021-02-05) |
| | | - 优化 组件引用关系,通过uni_modules引用组件 |
| | | ## 1.1.5(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-collapse-item"> |
| | | <!-- onClick(!isOpen) --> |
| | | <view @click="onClick(!isOpen)" class="uni-collapse-item__title" |
| | | :class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}"> |
| | | <view class="uni-collapse-item__title-wrap"> |
| | | <slot name="title"> |
| | | <view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}"> |
| | | <image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" /> |
| | | <text class="uni-collapse-item__title-text">{{ title }}</text> |
| | | </view> |
| | | </slot> |
| | | </view> |
| | | <view v-if="showArrow" |
| | | :class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }" |
| | | class="uni-collapse-item__title-arrow"> |
| | | <uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" /> |
| | | </view> |
| | | </view> |
| | | <view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}" |
| | | :style="{height: (isOpen?height:0) +'px'}"> |
| | | <view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content" |
| | | :class="{open:isheight,'uni-collapse-item--border':border&&isOpen}"> |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // #ifdef APP-NVUE |
| | | const dom = weex.requireModule('dom') |
| | | // #endif |
| | | /** |
| | | * CollapseItem 折叠面板子组件 |
| | | * @description 折叠面板子组件 |
| | | * @property {String} title 标题文字 |
| | | * @property {String} thumb 标题左侧缩略图 |
| | | * @property {String} name 唯一标志符 |
| | | * @property {Boolean} open = [true|false] 是否展开组件 |
| | | * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线 |
| | | * @property {Boolean} border = [true|false] 是否显示分隔线 |
| | | * @property {Boolean} disabled = [true|false] 是否展开面板 |
| | | * @property {Boolean} showAnimation = [true|false] 开启动画 |
| | | * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头 |
| | | */ |
| | | export default { |
| | | name: 'uniCollapseItem', |
| | | props: { |
| | | // 列表标题 |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | name: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | // 是否禁用 |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // #ifdef APP-PLUS |
| | | // 是否显示动画,app 端默认不开启动画,卡顿严重 |
| | | showAnimation: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // #endif |
| | | // #ifndef APP-PLUS |
| | | // 是否显示动画 |
| | | showAnimation: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // #endif |
| | | // 是否展开 |
| | | open: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 缩略图 |
| | | thumb: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 标题分隔线显示类型 |
| | | titleBorder: { |
| | | type: String, |
| | | default: 'auto' |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | showArrow: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | // TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug |
| | | const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}` |
| | | return { |
| | | isOpen: false, |
| | | isheight: null, |
| | | height: 0, |
| | | elId, |
| | | nameSync: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | open(val) { |
| | | this.isOpen = val |
| | | this.onClick(val, 'init') |
| | | } |
| | | }, |
| | | updated(e) { |
| | | this.$nextTick(() => { |
| | | this.init(true) |
| | | }) |
| | | }, |
| | | created() { |
| | | this.collapse = this.getCollapse() |
| | | this.oldHeight = 0 |
| | | this.onClick(this.open, 'init') |
| | | }, |
| | | // #ifndef VUE3 |
| | | // TODO vue2 |
| | | destroyed() { |
| | | if (this.__isUnmounted) return |
| | | this.uninstall() |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | // TODO vue3 |
| | | unmounted() { |
| | | this.__isUnmounted = true |
| | | this.uninstall() |
| | | }, |
| | | // #endif |
| | | mounted() { |
| | | if (!this.collapse) return |
| | | if (this.name !== '') { |
| | | this.nameSync = this.name |
| | | } else { |
| | | this.nameSync = this.collapse.childrens.length + '' |
| | | } |
| | | if (this.collapse.names.indexOf(this.nameSync) === -1) { |
| | | this.collapse.names.push(this.nameSync) |
| | | } else { |
| | | console.warn(`name 值 ${this.nameSync} 重复`); |
| | | } |
| | | if (this.collapse.childrens.indexOf(this) === -1) { |
| | | this.collapse.childrens.push(this) |
| | | } |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | init(type) { |
| | | // #ifndef APP-NVUE |
| | | this.getCollapseHeight(type) |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | this.getNvueHwight(type) |
| | | // #endif |
| | | }, |
| | | uninstall() { |
| | | if (this.collapse) { |
| | | this.collapse.childrens.forEach((item, index) => { |
| | | if (item === this) { |
| | | this.collapse.childrens.splice(index, 1) |
| | | } |
| | | }) |
| | | this.collapse.names.forEach((item, index) => { |
| | | if (item === this.nameSync) { |
| | | this.collapse.names.splice(index, 1) |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | onClick(isOpen, type) { |
| | | if (this.disabled) return |
| | | this.isOpen = isOpen |
| | | if (this.isOpen && this.collapse) { |
| | | this.collapse.setAccordion(this) |
| | | } |
| | | if (type !== 'init') { |
| | | this.collapse.onChange(isOpen, this) |
| | | } |
| | | }, |
| | | getCollapseHeight(type, index = 0) { |
| | | const views = uni.createSelectorQuery().in(this) |
| | | views |
| | | .select(`#${this.elId}`) |
| | | .fields({ |
| | | size: true |
| | | }, data => { |
| | | // TODO 百度中可能获取不到节点信息 ,需要循环获取 |
| | | if (index >= 10) return |
| | | if (!data) { |
| | | index++ |
| | | this.getCollapseHeight(false, index) |
| | | return |
| | | } |
| | | // #ifdef APP-NVUE |
| | | this.height = data.height + 1 |
| | | // #endif |
| | | // #ifndef APP-NVUE |
| | | this.height = data.height |
| | | // #endif |
| | | this.isheight = true |
| | | if (type) return |
| | | this.onClick(this.isOpen, 'init') |
| | | }) |
| | | .exec() |
| | | }, |
| | | getNvueHwight(type) { |
| | | const result = dom.getComponentRect(this.$refs['collapse--hook'], option => { |
| | | if (option && option.result && option.size) { |
| | | // #ifdef APP-NVUE |
| | | this.height = option.size.height + 1 |
| | | // #endif |
| | | // #ifndef APP-NVUE |
| | | this.height = option.size.height |
| | | // #endif |
| | | this.isheight = true |
| | | if (type) return |
| | | this.onClick(this.open, 'init') |
| | | } |
| | | }) |
| | | }, |
| | | /** |
| | | * 获取父元素实例 |
| | | */ |
| | | getCollapse(name = 'uniCollapse') { |
| | | let parent = this.$parent; |
| | | let parentName = parent.$options.name; |
| | | while (parentName !== name) { |
| | | parent = parent.$parent; |
| | | if (!parent) return false; |
| | | parentName = parent.$options.name; |
| | | } |
| | | return parent; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-collapse-item { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | |
| | | /* #endif */ |
| | | &__title { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | transition: border-bottom-color .3s; |
| | | |
| | | // transition-property: border-bottom-color; |
| | | // transition-duration: 5s; |
| | | &-wrap { |
| | | width: 100%; |
| | | flex: 1; |
| | | |
| | | } |
| | | |
| | | &-box { |
| | | padding: 0 15px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 48px; |
| | | line-height: 48px; |
| | | background-color: #fff; |
| | | color: #303133; |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | outline: none; |
| | | |
| | | /* #endif */ |
| | | &.is-disabled { |
| | | .uni-collapse-item__title-text { |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | &.uni-collapse-item-border { |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | &.is-open { |
| | | border-bottom-color: transparent; |
| | | } |
| | | |
| | | &-img { |
| | | height: 22px; |
| | | width: 22px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | &-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | /* #ifndef APP-NVUE */ |
| | | white-space: nowrap; |
| | | color: inherit; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | lines: 1; |
| | | /* #endif */ |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | &-arrow { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 10px; |
| | | transform: rotate(0deg); |
| | | |
| | | &-active { |
| | | transform: rotate(-180deg); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | &__wrap { |
| | | /* #ifndef APP-NVUE */ |
| | | will-change: height; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | background-color: #fff; |
| | | overflow: hidden; |
| | | position: relative; |
| | | height: 0; |
| | | |
| | | &.is--transition { |
| | | // transition: all 0.3s; |
| | | transition-property: height, border-bottom-width; |
| | | transition-duration: 0.3s; |
| | | /* #ifndef APP-NVUE */ |
| | | will-change: height; |
| | | /* #endif */ |
| | | } |
| | | |
| | | |
| | | |
| | | &-content { |
| | | position: absolute; |
| | | font-size: 13px; |
| | | color: #303133; |
| | | // transition: height 0.3s; |
| | | border-bottom-color: transparent; |
| | | border-bottom-style: solid; |
| | | border-bottom-width: 0; |
| | | |
| | | &.uni-collapse-item--border { |
| | | border-bottom-width: 1px; |
| | | border-bottom-color: red; |
| | | border-bottom-color: #ebeef5; |
| | | } |
| | | |
| | | &.open { |
| | | position: relative; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &--animation { |
| | | transition-property: transform; |
| | | transition-duration: 0.3s; |
| | | transition-timing-function: ease; |
| | | } |
| | | |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-collapse"> |
| | | <slot /> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | /** |
| | | * Collapse 折叠面板 |
| | | * @description 展示可以折叠 / 展开的内容区域 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=23 |
| | | * @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array) |
| | | * @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果 |
| | | * @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array |
| | | */ |
| | | export default { |
| | | name: 'uniCollapse', |
| | | emits:['change','activeItem','input','update:modelValue'], |
| | | props: { |
| | | value: { |
| | | type: [String, Array], |
| | | default: '' |
| | | }, |
| | | modelValue: { |
| | | type: [String, Array], |
| | | default: '' |
| | | }, |
| | | accordion: { |
| | | // 是否开启手风琴效果 |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | }, |
| | | data() { |
| | | return {} |
| | | }, |
| | | computed: { |
| | | // TODO 兼容 vue2 和 vue3 |
| | | dataValue() { |
| | | let value = (typeof this.value === 'string' && this.value === '') || |
| | | (Array.isArray(this.value) && this.value.length === 0) |
| | | let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') || |
| | | (Array.isArray(this.modelValue) && this.modelValue.length === 0) |
| | | if (value) { |
| | | return this.modelValue |
| | | } |
| | | if (modelValue) { |
| | | return this.value |
| | | } |
| | | |
| | | return this.value |
| | | } |
| | | }, |
| | | watch: { |
| | | dataValue(val) { |
| | | this.setOpen(val) |
| | | } |
| | | }, |
| | | created() { |
| | | this.childrens = [] |
| | | this.names = [] |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(()=>{ |
| | | this.setOpen(this.dataValue) |
| | | }) |
| | | }, |
| | | methods: { |
| | | setOpen(val) { |
| | | let str = typeof val === 'string' |
| | | let arr = Array.isArray(val) |
| | | this.childrens.forEach((vm, index) => { |
| | | if (str) { |
| | | if (val === vm.nameSync) { |
| | | if (!this.accordion) { |
| | | console.warn('accordion 属性为 false ,v-model 类型应该为 array') |
| | | return |
| | | } |
| | | vm.isOpen = true |
| | | } |
| | | } |
| | | if (arr) { |
| | | val.forEach(v => { |
| | | if (v === vm.nameSync) { |
| | | if (this.accordion) { |
| | | console.warn('accordion 属性为 true ,v-model 类型应该为 string') |
| | | return |
| | | } |
| | | vm.isOpen = true |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | this.emit(val) |
| | | }, |
| | | setAccordion(self) { |
| | | if (!this.accordion) return |
| | | this.childrens.forEach((vm, index) => { |
| | | if (self !== vm) { |
| | | vm.isOpen = false |
| | | } |
| | | }) |
| | | }, |
| | | resize() { |
| | | this.childrens.forEach((vm, index) => { |
| | | // #ifndef APP-NVUE |
| | | vm.getCollapseHeight() |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | vm.getNvueHwight() |
| | | // #endif |
| | | }) |
| | | }, |
| | | onChange(isOpen, self) { |
| | | let activeItem = [] |
| | | |
| | | if (this.accordion) { |
| | | activeItem = isOpen ? self.nameSync : '' |
| | | } else { |
| | | this.childrens.forEach((vm, index) => { |
| | | if (vm.isOpen) { |
| | | activeItem.push(vm.nameSync) |
| | | } |
| | | }) |
| | | } |
| | | this.$emit('change', activeItem) |
| | | this.emit(activeItem) |
| | | }, |
| | | emit(val){ |
| | | this.$emit('input', val) |
| | | this.$emit('update:modelValue', val) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss" > |
| | | .uni-collapse { |
| | | /* #ifndef APP-NVUE */ |
| | | width: 100%; |
| | | display: flex; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | flex: 1; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | background-color: #fff; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-collapse", |
| | | "displayName": "uni-collapse 折叠面板", |
| | | "version": "1.4.3", |
| | | "description": "Collapse 组件,可以折叠 / 展开的内容区域。", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "折叠", |
| | | "折叠面板", |
| | | "手风琴" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-icons" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Collapse 折叠面板 |
| | | > **组件名:uni-collapse** |
| | | > 代码块: `uCollapse` |
| | | > 关联组件:`uni-collapse-item`、`uni-icons`。 |
| | | |
| | | |
| | | 折叠面板用来折叠/显示过长的内容或者是列表。通常是在多内容分类项使用,折叠不重要的内容,显示重要内容。点击可以展开折叠部分。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-collapse) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.0.1(2021-11-23) |
| | | - 优化 label、label-width 属性 |
| | | ## 1.0.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-combox](https://uniapp.dcloud.io/component/uniui/uni-combox) |
| | | ## 0.1.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 0.0.6(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 0.0.5(2021-04-21) |
| | | - 优化 添加依赖 uni-icons, 导入后自动下载依赖 |
| | | ## 0.0.4(2021-02-05) |
| | | - 优化 组件引用关系,通过uni_modules引用组件 |
| | | ## 0.0.3(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'"> |
| | | <view v-if="label" class="uni-combox__label" :style="labelStyle"> |
| | | <text>{{label}}</text> |
| | | </view> |
| | | <view class="uni-combox__input-box"> |
| | | <input class="uni-combox__input" type="text" :placeholder="placeholder" |
| | | placeholder-class="uni-combox__input-plac" v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" /> |
| | | <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector"> |
| | | </uni-icons> |
| | | </view> |
| | | <view class="uni-combox__selector" v-if="showSelector"> |
| | | <view class="uni-popper__arrow"></view> |
| | | <scroll-view scroll-y="true" class="uni-combox__selector-scroll" @scroll="onScroll"> |
| | | <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0"> |
| | | <text>{{emptyTips}}</text> |
| | | </view> |
| | | <view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index" @click="onSelectorClick(index)"> |
| | | <text>{{item}}</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | <!-- 新增蒙层,点击蒙层时关闭选项显示 --> |
| | | <view class="uni-combox__mask" v-show="showSelector" @click="showSelector = false"></view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * Combox 组合输入框 |
| | | * @description 组合输入框一般用于既可以输入也可以选择的场景 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=1261 |
| | | * @property {String} label 左侧文字 |
| | | * @property {String} labelWidth 左侧内容宽度 |
| | | * @property {String} placeholder 输入框占位符 |
| | | * @property {Array} candidates 候选项列表 |
| | | * @property {String} emptyTips 筛选结果为空时显示的文字 |
| | | * @property {String} value 组合框的值 |
| | | */ |
| | | export default { |
| | | name: 'uniCombox', |
| | | emits: ['input', 'update:modelValue'], |
| | | props: { |
| | | border: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | label: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | labelWidth: { |
| | | type: String, |
| | | default: 'auto' |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | candidates: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | emptyTips: { |
| | | type: String, |
| | | default: '无匹配项' |
| | | }, |
| | | // #ifndef VUE3 |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // #endif |
| | | }, |
| | | data() { |
| | | return { |
| | | showSelector: false, |
| | | inputVal: '', |
| | | blurTimer:null, |
| | | } |
| | | }, |
| | | computed: { |
| | | labelStyle() { |
| | | if (this.labelWidth === 'auto') { |
| | | return "" |
| | | } |
| | | return `width: ${this.labelWidth}` |
| | | }, |
| | | filterCandidates() { |
| | | if (this.inputVal !== 0 && !this.inputVal) { |
| | | return this.candidates |
| | | } |
| | | return this.candidates.filter((item) => { |
| | | return item.toString().indexOf(this.inputVal) > -1 |
| | | }) |
| | | }, |
| | | filterCandidatesLength() { |
| | | return this.filterCandidates.length |
| | | } |
| | | }, |
| | | watch: { |
| | | // #ifndef VUE3 |
| | | value: { |
| | | handler(newVal) { |
| | | this.inputVal = newVal |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | handler(newVal) { |
| | | this.inputVal = newVal |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | }, |
| | | methods: { |
| | | toggleSelector() { |
| | | this.showSelector = !this.showSelector |
| | | }, |
| | | onFocus() { |
| | | this.showSelector = true |
| | | }, |
| | | onBlur() { |
| | | this.blurTimer = setTimeout(() => { |
| | | this.showSelector = false |
| | | }, 153) |
| | | }, |
| | | onScroll(){ // 滚动时将blur的定时器关掉 |
| | | if(this.blurTimer) { |
| | | clearTimeout(this.blurTimer) |
| | | this.blurTimer = null |
| | | } |
| | | }, |
| | | onSelectorClick(index) { |
| | | this.inputVal = this.filterCandidates[index] |
| | | this.showSelector = false |
| | | this.$emit('input', this.inputVal) |
| | | this.$emit('update:modelValue', this.inputVal) |
| | | }, |
| | | onInput() { |
| | | setTimeout(() => { |
| | | this.$emit('input', this.inputVal) |
| | | this.$emit('update:modelValue', this.inputVal) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-combox { |
| | | font-size: 14px; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | padding: 6px 10px; |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | // height: 40px; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | // border-bottom: solid 1px #DDDDDD; |
| | | } |
| | | |
| | | .uni-combox__label { |
| | | font-size: 16px; |
| | | line-height: 22px; |
| | | padding-right: 10px; |
| | | color: #999999; |
| | | } |
| | | |
| | | .uni-combox__input-box { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex: 1; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-combox__input { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | height: 22px; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .uni-combox__input-plac { |
| | | font-size: 14px; |
| | | color: #999; |
| | | } |
| | | |
| | | .uni-combox__selector { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | position: absolute; |
| | | top: calc(100% + 12px); |
| | | left: 0; |
| | | width: 100%; |
| | | background-color: #FFFFFF; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 6px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | z-index: 3; |
| | | padding: 4px 0; |
| | | } |
| | | |
| | | .uni-combox__selector-scroll { |
| | | /* #ifndef APP-NVUE */ |
| | | max-height: 200px; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-combox__selector-empty, |
| | | .uni-combox__selector-item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | line-height: 36px; |
| | | font-size: 14px; |
| | | text-align: center; |
| | | // border-bottom: solid 1px #DDDDDD; |
| | | padding: 0px 10px; |
| | | } |
| | | |
| | | .uni-combox__selector-item:hover { |
| | | background-color: #f9f9f9; |
| | | } |
| | | |
| | | .uni-combox__selector-empty:last-child, |
| | | .uni-combox__selector-item:last-child { |
| | | /* #ifndef APP-NVUE */ |
| | | border-bottom: none; |
| | | /* #endif */ |
| | | } |
| | | |
| | | // picker 弹出层通用的指示小三角 |
| | | .uni-popper__arrow, |
| | | .uni-popper__arrow::after { |
| | | position: absolute; |
| | | display: block; |
| | | width: 0; |
| | | height: 0; |
| | | border-color: transparent; |
| | | border-style: solid; |
| | | border-width: 6px; |
| | | } |
| | | |
| | | .uni-popper__arrow { |
| | | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
| | | top: -6px; |
| | | left: 10%; |
| | | margin-right: 3px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #EBEEF5; |
| | | } |
| | | |
| | | .uni-popper__arrow::after { |
| | | content: " "; |
| | | top: 1px; |
| | | margin-left: -6px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #fff; |
| | | } |
| | | |
| | | .uni-combox__no-border { |
| | | border: none; |
| | | } |
| | | |
| | | .uni-combox__mask { |
| | | width:100%; |
| | | height:100%; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | z-index: 1; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-combox", |
| | | "displayName": "uni-combox 组合框", |
| | | "version": "1.0.1", |
| | | "description": "可以选择也可以输入的表单项 ", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "combox", |
| | | "组合框", |
| | | "select" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-icons" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "n" |
| | | }, |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Combox 组合框 |
| | | > **组件名:uni-combox** |
| | | > 代码块: `uCombox` |
| | | |
| | | |
| | | 组合框组件。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-combox) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.2.2(2022-01-19) |
| | | - 修复 在微信小程序中样式不生效的bug |
| | | ## 1.2.1(2022-01-18) |
| | | - 新增 update 方法 ,在动态更新时间后,刷新组件 |
| | | ## 1.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown) |
| | | ## 1.1.3(2021-10-18) |
| | | - 重构 |
| | | - 新增 font-size 支持自定义字体大小 |
| | | ## 1.1.2(2021-08-24) |
| | | - 新增 支持国际化 |
| | | ## 1.1.1(2021-07-30) |
| | | - 优化 vue3下小程序事件警告的问题 |
| | | ## 1.1.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.0.5(2021-06-18) |
| | | - 修复 uni-countdown 重复赋值跳两秒的 bug |
| | | ## 1.0.4(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.0.3(2021-05-08) |
| | | - 修复 uni-countdown 不能控制倒计时的 bug |
| | | ## 1.0.2(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | { |
| | | "uni-countdown.day": "day", |
| | | "uni-countdown.h": "h", |
| | | "uni-countdown.m": "m", |
| | | "uni-countdown.s": "s" |
| | | } |
对比新文件 |
| | |
| | | import en from './en.json' |
| | | import zhHans from './zh-Hans.json' |
| | | import zhHant from './zh-Hant.json' |
| | | export default { |
| | | en, |
| | | 'zh-Hans': zhHans, |
| | | 'zh-Hant': zhHant |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-countdown.day": "天", |
| | | "uni-countdown.h": "时", |
| | | "uni-countdown.m": "分", |
| | | "uni-countdown.s": "秒" |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-countdown.day": "天", |
| | | "uni-countdown.h": "時", |
| | | "uni-countdown.m": "分", |
| | | "uni-countdown.s": "秒" |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-countdown"> |
| | | <text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text> |
| | | <text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text> |
| | | <text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text> |
| | | <text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text> |
| | | <text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text> |
| | | <text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text> |
| | | <text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text> |
| | | <text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | import { |
| | | initVueI18n |
| | | } from '@dcloudio/uni-i18n' |
| | | import messages from './i18n/index.js' |
| | | const { |
| | | t |
| | | } = initVueI18n(messages) |
| | | /** |
| | | * Countdown 倒计时 |
| | | * @description 倒计时组件 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=25 |
| | | * @property {String} backgroundColor 背景色 |
| | | * @property {String} color 文字颜色 |
| | | * @property {Number} day 天数 |
| | | * @property {Number} hour 小时 |
| | | * @property {Number} minute 分钟 |
| | | * @property {Number} second 秒 |
| | | * @property {Number} timestamp 时间戳 |
| | | * @property {Boolean} showDay = [true|false] 是否显示天数 |
| | | * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符 |
| | | * @property {String} splitorColor 分割符号颜色 |
| | | * @event {Function} timeup 倒计时时间到触发事件 |
| | | * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown> |
| | | */ |
| | | export default { |
| | | name: 'UniCountdown', |
| | | emits: ['timeup'], |
| | | props: { |
| | | showDay: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | showColon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | start: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | backgroundColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | color: { |
| | | type: String, |
| | | default: '#333' |
| | | }, |
| | | fontSize: { |
| | | type: Number, |
| | | default: 14 |
| | | }, |
| | | splitorColor: { |
| | | type: String, |
| | | default: '#333' |
| | | }, |
| | | day: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | hour: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | minute: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | second: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | timestamp: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | zeroPad: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | timer: null, |
| | | syncFlag: false, |
| | | d: '00', |
| | | h: '00', |
| | | i: '00', |
| | | s: '00', |
| | | leftTime: 0, |
| | | seconds: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | dayText() { |
| | | return t("uni-countdown.day") |
| | | }, |
| | | hourText(val) { |
| | | return t("uni-countdown.h") |
| | | }, |
| | | minuteText(val) { |
| | | return t("uni-countdown.m") |
| | | }, |
| | | secondText(val) { |
| | | return t("uni-countdown.s") |
| | | }, |
| | | timeStyle() { |
| | | const { |
| | | color, |
| | | backgroundColor, |
| | | fontSize |
| | | } = this |
| | | return { |
| | | color, |
| | | backgroundColor, |
| | | fontSize: `${fontSize}px`, |
| | | width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放 |
| | | lineHeight: `${fontSize * 20 / 14}px`, |
| | | borderRadius: `${fontSize * 3 / 14}px`, |
| | | } |
| | | }, |
| | | splitorStyle() { |
| | | const { splitorColor, fontSize, backgroundColor } = this |
| | | return { |
| | | color: splitorColor, |
| | | fontSize: `${fontSize * 12 / 14}px`, |
| | | margin: backgroundColor ? `${fontSize * 4 / 14}px` : '' |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | day(val) { |
| | | this.changeFlag() |
| | | }, |
| | | hour(val) { |
| | | this.changeFlag() |
| | | }, |
| | | minute(val) { |
| | | this.changeFlag() |
| | | }, |
| | | second(val) { |
| | | this.changeFlag() |
| | | }, |
| | | start: { |
| | | immediate: true, |
| | | handler(newVal, oldVal) { |
| | | if (newVal) { |
| | | this.startData(); |
| | | } else { |
| | | if (!oldVal) return |
| | | clearInterval(this.timer) |
| | | } |
| | | } |
| | | |
| | | } |
| | | }, |
| | | created: function(e) { |
| | | this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
| | | this.countDown() |
| | | }, |
| | | // #ifndef VUE3 |
| | | destroyed() { |
| | | clearInterval(this.timer) |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | unmounted() { |
| | | clearInterval(this.timer) |
| | | }, |
| | | // #endif |
| | | methods: { |
| | | toSeconds(timestamp, day, hours, minutes, seconds) { |
| | | if (timestamp) { |
| | | return timestamp - parseInt(new Date().getTime() / 1000, 10) |
| | | } |
| | | return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds |
| | | }, |
| | | timeUp() { |
| | | clearInterval(this.timer) |
| | | this.$emit('timeup') |
| | | }, |
| | | countDown() { |
| | | let seconds = this.seconds |
| | | let [day, hour, minute, second] = [0, 0, 0, 0] |
| | | if (seconds > 0) { |
| | | day = Math.floor(seconds / (60 * 60 * 24)) |
| | | hour = Math.floor(seconds / (60 * 60)) - (day * 24) |
| | | minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60) |
| | | second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60) |
| | | } else { |
| | | this.timeUp() |
| | | } |
| | | day = (day < 10 && this.zeroPad) ? `0${day}` : day |
| | | hour = (hour < 10 && this.zeroPad) ? `0${hour}` : hour |
| | | minute = (minute < 10 && this.zeroPad) ? `0${minute}` : minute |
| | | second = (second < 10 && this.zeroPad) ? `0${second}` : second |
| | | this.d = day |
| | | this.h = hour |
| | | this.i = minute |
| | | this.s = second |
| | | }, |
| | | startData() { |
| | | this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
| | | if (this.seconds <= 0) { |
| | | this.seconds = this.toSeconds(0, 0, 0, 0, 0) |
| | | this.countDown() |
| | | return |
| | | } |
| | | clearInterval(this.timer) |
| | | this.countDown() |
| | | this.timer = setInterval(() => { |
| | | this.seconds-- |
| | | if (this.seconds < 0) { |
| | | this.timeUp() |
| | | return |
| | | } |
| | | this.countDown() |
| | | }, 1000) |
| | | }, |
| | | update(){ |
| | | this.startData(); |
| | | }, |
| | | changeFlag() { |
| | | if (!this.syncFlag) { |
| | | this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
| | | this.startData(); |
| | | this.syncFlag = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | $font-size: 14px; |
| | | |
| | | .uni-countdown { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | |
| | | &__splitor { |
| | | margin: 0 2px; |
| | | font-size: $font-size; |
| | | color: #333; |
| | | } |
| | | |
| | | &__number { |
| | | border-radius: 3px; |
| | | text-align: center; |
| | | font-size: $font-size; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-countdown", |
| | | "displayName": "uni-countdown 倒计时", |
| | | "version": "1.2.2", |
| | | "description": "CountDown 倒计时组件", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "countdown", |
| | | "倒计时" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## CountDown 倒计时 |
| | | > **组件名:uni-countdown** |
| | | > 代码块: `uCountDown` |
| | | |
| | | 倒计时组件。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.0.3(2022-09-16) |
| | | - 可以使用 uni-scss 控制主题色 |
| | | ## 1.0.2(2022-06-30) |
| | | - 优化 在 uni-forms 中的依赖注入方式 |
| | | ## 1.0.1(2022-02-07) |
| | | - 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug |
| | | ## 1.0.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) |
| | | ## 0.2.5(2021-08-23) |
| | | - 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题 |
| | | ## 0.2.4(2021-08-17) |
| | | - 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 |
| | | ## 0.2.3(2021-08-11) |
| | | - 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 |
| | | ## 0.2.2(2021-07-30) |
| | | - 优化 在uni-forms组件,与label不对齐的问题 |
| | | ## 0.2.1(2021-07-27) |
| | | - 修复 单选默认值为0不能选中的Bug |
| | | ## 0.2.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 0.1.11(2021-07-06) |
| | | - 优化 删除无用日志 |
| | | ## 0.1.10(2021-07-05) |
| | | - 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题 |
| | | ## 0.1.9(2021-07-05) |
| | | - 修复 nvue 黑框样式问题 |
| | | ## 0.1.8(2021-06-28) |
| | | - 修复 selectedTextColor 属性不生效的Bug |
| | | ## 0.1.7(2021-06-02) |
| | | - 新增 map 属性,可以方便映射text/value属性 |
| | | ## 0.1.6(2021-05-26) |
| | | - 修复 不关联服务空间的情况下组件报错的Bug |
| | | ## 0.1.5(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 0.1.4(2021-04-09) |
| | | - 修复 nvue 下无法选中的问题 |
| | | ## 0.1.3(2021-03-22) |
| | | - 新增 disabled属性 |
| | | ## 0.1.2(2021-02-24) |
| | | - 优化 默认颜色显示 |
| | | ## 0.1.1(2021-02-24) |
| | | - 新增 支持nvue |
| | | ## 0.1.0(2021-02-18) |
| | | - “暂无数据”显示居中 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-data-checklist" :style="{'margin-top':isTop+'px'}"> |
| | | <template v-if="!isLocal"> |
| | | <view class="uni-data-loading"> |
| | | <uni-load-more v-if="!mixinDatacomErrorMessage" status="loading" iconType="snow" :iconSize="18" :content-text="contentText"></uni-load-more> |
| | | <text v-else>{{mixinDatacomErrorMessage}}</text> |
| | | </view> |
| | | </template> |
| | | <template v-else> |
| | | <checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="chagne"> |
| | | <label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']" |
| | | :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index"> |
| | | <checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" :checked="item.selected" /> |
| | | <view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="checkbox__inner" :style="item.styleIcon"> |
| | | <view class="checkbox__inner-icon"></view> |
| | | </view> |
| | | <view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}"> |
| | | <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text> |
| | | <view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view> |
| | | </view> |
| | | </label> |
| | | </checkbox-group> |
| | | <radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="chagne"> |
| | | <!-- --> |
| | | <label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']" |
| | | :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index"> |
| | | <radio class="hidden" hidden :disabled="disabled || item.disabled" :value="item[map.value]+''" :checked="item.selected" /> |
| | | <view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner" |
| | | :style="item.styleBackgroud"> |
| | | <view class="radio__inner-icon" :style="item.styleIcon"></view> |
| | | </view> |
| | | <view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}"> |
| | | <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text> |
| | | <view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view> |
| | | </view> |
| | | </label> |
| | | </radio-group> |
| | | </template> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * DataChecklist 数据选择器 |
| | | * @description 通过数据渲染 checkbox 和 radio |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx |
| | | * @property {String} mode = [default| list | button | tag] 显示模式 |
| | | * @value default 默认横排模式 |
| | | * @value list 列表模式 |
| | | * @value button 按钮模式 |
| | | * @value tag 标签模式 |
| | | * @property {Boolean} multiple = [true|false] 是否多选 |
| | | * @property {Array|String|Number} value 默认值 |
| | | * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}] |
| | | * @property {Number|String} min 最小选择个数 ,multiple为true时生效 |
| | | * @property {Number|String} max 最大选择个数 ,multiple为true时生效 |
| | | * @property {Boolean} wrap 是否换行显示 |
| | | * @property {String} icon = [left|right] list 列表模式下icon显示位置 |
| | | * @property {Boolean} selectedColor 选中颜色 |
| | | * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效 |
| | | * @property {Boolean} selectedTextColor 选中文本颜色,如不填写则自动显示 |
| | | * @property {Object} map 字段映射, 默认 map={text:'text',value:'value'} |
| | | * @value left 左侧显示 |
| | | * @value right 右侧显示 |
| | | * @event {Function} change 选中发生变化触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: 'uniDataChecklist', |
| | | mixins: [uniCloud.mixinDatacom || {}], |
| | | emits:['input','update:modelValue','change'], |
| | | props: { |
| | | mode: { |
| | | type: String, |
| | | default: 'default' |
| | | }, |
| | | |
| | | multiple: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | value: { |
| | | type: [Array, String, Number], |
| | | default () { |
| | | return '' |
| | | } |
| | | }, |
| | | // TODO vue3 |
| | | modelValue: { |
| | | type: [Array, String, Number], |
| | | default() { |
| | | return ''; |
| | | } |
| | | }, |
| | | localdata: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | min: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | max: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | wrap: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | icon: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | selectedColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | selectedTextColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | emptyText:{ |
| | | type: String, |
| | | default: '暂无数据' |
| | | }, |
| | | disabled:{ |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | map:{ |
| | | type: Object, |
| | | default(){ |
| | | return { |
| | | text:'text', |
| | | value:'value' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | localdata: { |
| | | handler(newVal) { |
| | | this.range = newVal |
| | | this.dataList = this.getDataList(this.getSelectedValue(newVal)) |
| | | }, |
| | | deep: true |
| | | }, |
| | | mixinDatacomResData(newVal) { |
| | | this.range = newVal |
| | | this.dataList = this.getDataList(this.getSelectedValue(newVal)) |
| | | }, |
| | | value(newVal) { |
| | | this.dataList = this.getDataList(newVal) |
| | | // fix by mehaotian is_reset 在 uni-forms 中定义 |
| | | // if(!this.is_reset){ |
| | | // this.is_reset = false |
| | | // this.formItem && this.formItem.setValue(newVal) |
| | | // } |
| | | }, |
| | | modelValue(newVal) { |
| | | this.dataList = this.getDataList(newVal); |
| | | // if(!this.is_reset){ |
| | | // this.is_reset = false |
| | | // this.formItem && this.formItem.setValue(newVal) |
| | | // } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dataList: [], |
| | | range: [], |
| | | contentText: { |
| | | contentdown: '查看更多', |
| | | contentrefresh: '加载中', |
| | | contentnomore: '没有更多' |
| | | }, |
| | | isLocal:true, |
| | | styles: { |
| | | selectedColor: '#2979ff', |
| | | selectedTextColor: '#666', |
| | | }, |
| | | isTop:0 |
| | | }; |
| | | }, |
| | | computed:{ |
| | | dataValue(){ |
| | | if(this.value === '')return this.modelValue |
| | | if(this.modelValue === '') return this.value |
| | | return this.value |
| | | } |
| | | }, |
| | | created() { |
| | | // this.form = this.getForm('uniForms') |
| | | // this.formItem = this.getForm('uniFormsItem') |
| | | // this.formItem && this.formItem.setValue(this.value) |
| | | |
| | | // if (this.formItem) { |
| | | // this.isTop = 6 |
| | | // if (this.formItem.name) { |
| | | // // 如果存在name添加默认值,否则formData 中不存在这个字段不校验 |
| | | // if(!this.is_reset){ |
| | | // this.is_reset = false |
| | | // this.formItem.setValue(this.dataValue) |
| | | // } |
| | | // this.rename = this.formItem.name |
| | | // this.form.inputChildrens.push(this) |
| | | // } |
| | | // } |
| | | |
| | | if (this.localdata && this.localdata.length !== 0) { |
| | | this.isLocal = true |
| | | this.range = this.localdata |
| | | this.dataList = this.getDataList(this.getSelectedValue(this.range)) |
| | | } else { |
| | | if (this.collection) { |
| | | this.isLocal = false |
| | | this.loadData() |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | loadData() { |
| | | this.mixinDatacomGet().then(res=>{ |
| | | this.mixinDatacomResData = res.result.data |
| | | if(this.mixinDatacomResData.length === 0){ |
| | | this.isLocal = false |
| | | this.mixinDatacomErrorMessage = this.emptyText |
| | | }else{ |
| | | this.isLocal = true |
| | | } |
| | | }).catch(err=>{ |
| | | this.mixinDatacomErrorMessage = err.message |
| | | }) |
| | | }, |
| | | /** |
| | | * 获取父元素实例 |
| | | */ |
| | | getForm(name = 'uniForms') { |
| | | let parent = this.$parent; |
| | | let parentName = parent.$options.name; |
| | | while (parentName !== name) { |
| | | parent = parent.$parent; |
| | | if (!parent) return false |
| | | parentName = parent.$options.name; |
| | | } |
| | | return parent; |
| | | }, |
| | | chagne(e) { |
| | | const values = e.detail.value |
| | | |
| | | let detail = { |
| | | value: [], |
| | | data: [] |
| | | } |
| | | |
| | | if (this.multiple) { |
| | | this.range.forEach(item => { |
| | | |
| | | if (values.includes(item[this.map.value] + '')) { |
| | | detail.value.push(item[this.map.value]) |
| | | detail.data.push(item) |
| | | } |
| | | }) |
| | | } else { |
| | | const range = this.range.find(item => (item[this.map.value] + '') === values) |
| | | if (range) { |
| | | detail = { |
| | | value: range[this.map.value], |
| | | data: range |
| | | } |
| | | } |
| | | } |
| | | // this.formItem && this.formItem.setValue(detail.value) |
| | | // TODO 兼容 vue2 |
| | | this.$emit('input', detail.value); |
| | | // // TOTO 兼容 vue3 |
| | | this.$emit('update:modelValue', detail.value); |
| | | this.$emit('change', { |
| | | detail |
| | | }) |
| | | if (this.multiple) { |
| | | // 如果 v-model 没有绑定 ,则走内部逻辑 |
| | | // if (this.value.length === 0) { |
| | | this.dataList = this.getDataList(detail.value, true) |
| | | // } |
| | | } else { |
| | | this.dataList = this.getDataList(detail.value) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 获取渲染的新数组 |
| | | * @param {Object} value 选中内容 |
| | | */ |
| | | getDataList(value) { |
| | | // 解除引用关系,破坏原引用关系,避免污染源数据 |
| | | let dataList = JSON.parse(JSON.stringify(this.range)) |
| | | let list = [] |
| | | if (this.multiple) { |
| | | if (!Array.isArray(value)) { |
| | | value = [] |
| | | } |
| | | } |
| | | dataList.forEach((item, index) => { |
| | | item.disabled = item.disable || item.disabled || false |
| | | if (this.multiple) { |
| | | if (value.length > 0) { |
| | | let have = value.find(val => val === item[this.map.value]) |
| | | item.selected = have !== undefined |
| | | } else { |
| | | item.selected = false |
| | | } |
| | | } else { |
| | | item.selected = value === item[this.map.value] |
| | | } |
| | | |
| | | list.push(item) |
| | | }) |
| | | return this.setRange(list) |
| | | }, |
| | | /** |
| | | * 处理最大最小值 |
| | | * @param {Object} list |
| | | */ |
| | | setRange(list) { |
| | | let selectList = list.filter(item => item.selected) |
| | | let min = Number(this.min) || 0 |
| | | let max = Number(this.max) || '' |
| | | list.forEach((item, index) => { |
| | | if (this.multiple) { |
| | | if (selectList.length <= min) { |
| | | let have = selectList.find(val => val[this.map.value] === item[this.map.value]) |
| | | if (have !== undefined) { |
| | | item.disabled = true |
| | | } |
| | | } |
| | | |
| | | if (selectList.length >= max && max !== '') { |
| | | let have = selectList.find(val => val[this.map.value] === item[this.map.value]) |
| | | if (have === undefined) { |
| | | item.disabled = true |
| | | } |
| | | } |
| | | } |
| | | this.setStyles(item, index) |
| | | list[index] = item |
| | | }) |
| | | return list |
| | | }, |
| | | /** |
| | | * 设置 class |
| | | * @param {Object} item |
| | | * @param {Object} index |
| | | */ |
| | | setStyles(item, index) { |
| | | // 设置自定义样式 |
| | | item.styleBackgroud = this.setStyleBackgroud(item) |
| | | item.styleIcon = this.setStyleIcon(item) |
| | | item.styleIconText = this.setStyleIconText(item) |
| | | item.styleRightIcon = this.setStyleRightIcon(item) |
| | | }, |
| | | |
| | | /** |
| | | * 获取选中值 |
| | | * @param {Object} range |
| | | */ |
| | | getSelectedValue(range) { |
| | | if (!this.multiple) return this.dataValue |
| | | let selectedArr = [] |
| | | range.forEach((item) => { |
| | | if (item.selected) { |
| | | selectedArr.push(item[this.map.value]) |
| | | } |
| | | }) |
| | | return this.dataValue.length > 0 ? this.dataValue : selectedArr |
| | | }, |
| | | |
| | | /** |
| | | * 设置背景样式 |
| | | */ |
| | | setStyleBackgroud(item) { |
| | | let styles = {} |
| | | let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' |
| | | if (this.selectedColor) { |
| | | if (this.mode !== 'list') { |
| | | styles['border-color'] = item.selected?selectedColor:'#DCDFE6' |
| | | } |
| | | if (this.mode === 'tag') { |
| | | styles['background-color'] = item.selected? selectedColor:'#f5f5f5' |
| | | } |
| | | } |
| | | let classles = '' |
| | | for (let i in styles) { |
| | | classles += `${i}:${styles[i]};` |
| | | } |
| | | return classles |
| | | }, |
| | | setStyleIcon(item) { |
| | | let styles = {} |
| | | let classles = '' |
| | | if (this.selectedColor) { |
| | | let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' |
| | | styles['background-color'] = item.selected?selectedColor:'#fff' |
| | | styles['border-color'] = item.selected?selectedColor:'#DCDFE6' |
| | | |
| | | if(!item.selected && item.disabled){ |
| | | styles['background-color'] = '#F2F6FC' |
| | | styles['border-color'] = item.selected?selectedColor:'#DCDFE6' |
| | | } |
| | | } |
| | | for (let i in styles) { |
| | | classles += `${i}:${styles[i]};` |
| | | } |
| | | return classles |
| | | }, |
| | | setStyleIconText(item) { |
| | | let styles = {} |
| | | let classles = '' |
| | | if (this.selectedColor) { |
| | | let selectedColor = this.selectedColor?this.selectedColor:'#2979ff' |
| | | if (this.mode === 'tag') { |
| | | styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666' |
| | | } else { |
| | | styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666' |
| | | } |
| | | if(!item.selected && item.disabled){ |
| | | styles.color = '#999' |
| | | } |
| | | } |
| | | for (let i in styles) { |
| | | classles += `${i}:${styles[i]};` |
| | | } |
| | | return classles |
| | | }, |
| | | setStyleRightIcon(item) { |
| | | let styles = {} |
| | | let classles = '' |
| | | if (this.mode === 'list') { |
| | | styles['border-color'] = item.selected?this.styles.selectedColor:'#DCDFE6' |
| | | } |
| | | for (let i in styles) { |
| | | classles += `${i}:${styles[i]};` |
| | | } |
| | | |
| | | return classles |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-primary: #2979ff !default; |
| | | $border-color: #DCDFE6; |
| | | $disable:0.4; |
| | | |
| | | @mixin flex { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-data-loading { |
| | | @include flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 36px; |
| | | padding-left: 10px; |
| | | color: #999; |
| | | } |
| | | |
| | | .uni-data-checklist { |
| | | position: relative; |
| | | z-index: 0; |
| | | flex: 1; |
| | | // 多选样式 |
| | | .checklist-group { |
| | | @include flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | |
| | | &.is-list { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .checklist-box { |
| | | @include flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | position: relative; |
| | | margin: 5px 0; |
| | | margin-right: 25px; |
| | | |
| | | .hidden { |
| | | position: absolute; |
| | | opacity: 0; |
| | | } |
| | | |
| | | // 文字样式 |
| | | .checklist-content { |
| | | @include flex; |
| | | flex: 1; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | .checklist-text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | margin-left: 5px; |
| | | line-height: 14px; |
| | | } |
| | | |
| | | .checkobx__list { |
| | | border-right-width: 1px; |
| | | border-right-color: #007aff; |
| | | border-right-style: solid; |
| | | border-bottom-width:1px; |
| | | border-bottom-color: #007aff; |
| | | border-bottom-style: solid; |
| | | height: 12px; |
| | | width: 6px; |
| | | left: -5px; |
| | | transform-origin: center; |
| | | transform: rotate(45deg); |
| | | opacity: 0; |
| | | } |
| | | } |
| | | |
| | | // 多选样式 |
| | | .checkbox__inner { |
| | | /* #ifndef APP-NVUE */ |
| | | flex-shrink: 0; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | position: relative; |
| | | width: 16px; |
| | | height: 16px; |
| | | border: 1px solid $border-color; |
| | | border-radius: 4px; |
| | | background-color: #fff; |
| | | z-index: 1; |
| | | .checkbox__inner-icon { |
| | | position: absolute; |
| | | /* #ifdef APP-NVUE */ |
| | | top: 2px; |
| | | /* #endif */ |
| | | /* #ifndef APP-NVUE */ |
| | | top: 1px; |
| | | /* #endif */ |
| | | left: 5px; |
| | | height: 8px; |
| | | width: 4px; |
| | | border-right-width: 1px; |
| | | border-right-color: #fff; |
| | | border-right-style: solid; |
| | | border-bottom-width:1px ; |
| | | border-bottom-color: #fff; |
| | | border-bottom-style: solid; |
| | | opacity: 0; |
| | | transform-origin: center; |
| | | transform: rotate(40deg); |
| | | } |
| | | } |
| | | |
| | | // 单选样式 |
| | | .radio__inner { |
| | | @include flex; |
| | | /* #ifndef APP-NVUE */ |
| | | flex-shrink: 0; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: relative; |
| | | width: 16px; |
| | | height: 16px; |
| | | border: 1px solid $border-color; |
| | | border-radius: 16px; |
| | | background-color: #fff; |
| | | z-index: 1; |
| | | |
| | | .radio__inner-icon { |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 10px; |
| | | opacity: 0; |
| | | } |
| | | } |
| | | |
| | | // 默认样式 |
| | | &.is--default { |
| | | |
| | | // 禁用 |
| | | &.is-disable { |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | .checkbox__inner { |
| | | background-color: #F2F6FC; |
| | | border-color: $border-color; |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .radio__inner { |
| | | background-color: #F2F6FC; |
| | | border-color: $border-color; |
| | | } |
| | | .checklist-text { |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | // 选中 |
| | | &.is-checked { |
| | | .checkbox__inner { |
| | | border-color: $uni-primary; |
| | | background-color: $uni-primary; |
| | | |
| | | .checkbox__inner-icon { |
| | | opacity: 1; |
| | | transform: rotate(45deg); |
| | | } |
| | | } |
| | | .radio__inner { |
| | | border-color: $uni-primary; |
| | | .radio__inner-icon { |
| | | opacity: 1; |
| | | background-color: $uni-primary; |
| | | } |
| | | } |
| | | .checklist-text { |
| | | color: $uni-primary; |
| | | } |
| | | // 选中禁用 |
| | | &.is-disable { |
| | | .checkbox__inner { |
| | | opacity: $disable; |
| | | } |
| | | |
| | | .checklist-text { |
| | | opacity: $disable; |
| | | } |
| | | .radio__inner { |
| | | opacity: $disable; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 按钮样式 |
| | | &.is--button { |
| | | margin-right: 10px; |
| | | padding: 5px 10px; |
| | | border: 1px $border-color solid; |
| | | border-radius: 3px; |
| | | transition: border-color 0.2s; |
| | | |
| | | // 禁用 |
| | | &.is-disable { |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | border: 1px #eee solid; |
| | | opacity: $disable; |
| | | .checkbox__inner { |
| | | background-color: #F2F6FC; |
| | | border-color: $border-color; |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | } |
| | | .radio__inner { |
| | | background-color: #F2F6FC; |
| | | border-color: $border-color; |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | } |
| | | .checklist-text { |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | &.is-checked { |
| | | border-color: $uni-primary; |
| | | .checkbox__inner { |
| | | border-color: $uni-primary; |
| | | background-color: $uni-primary; |
| | | .checkbox__inner-icon { |
| | | opacity: 1; |
| | | transform: rotate(45deg); |
| | | } |
| | | } |
| | | |
| | | .radio__inner { |
| | | border-color: $uni-primary; |
| | | |
| | | .radio__inner-icon { |
| | | opacity: 1; |
| | | background-color: $uni-primary; |
| | | } |
| | | } |
| | | |
| | | .checklist-text { |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | // 选中禁用 |
| | | &.is-disable { |
| | | opacity: $disable; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 标签样式 |
| | | &.is--tag { |
| | | margin-right: 10px; |
| | | padding: 5px 10px; |
| | | border: 1px $border-color solid; |
| | | border-radius: 3px; |
| | | background-color: #f5f5f5; |
| | | |
| | | .checklist-text { |
| | | margin: 0; |
| | | color: #666; |
| | | } |
| | | |
| | | // 禁用 |
| | | &.is-disable { |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | opacity: $disable; |
| | | } |
| | | |
| | | &.is-checked { |
| | | background-color: $uni-primary; |
| | | border-color: $uni-primary; |
| | | |
| | | .checklist-text { |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | // 列表样式 |
| | | &.is--list { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | padding: 10px 15px; |
| | | padding-left: 0; |
| | | margin: 0; |
| | | |
| | | &.is-list-border { |
| | | border-top: 1px #eee solid; |
| | | } |
| | | |
| | | // 禁用 |
| | | &.is-disable { |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | .checkbox__inner { |
| | | background-color: #F2F6FC; |
| | | border-color: $border-color; |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed; |
| | | /* #endif */ |
| | | } |
| | | .checklist-text { |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | &.is-checked { |
| | | .checkbox__inner { |
| | | border-color: $uni-primary; |
| | | background-color: $uni-primary; |
| | | |
| | | .checkbox__inner-icon { |
| | | opacity: 1; |
| | | transform: rotate(45deg); |
| | | } |
| | | } |
| | | .radio__inner { |
| | | .radio__inner-icon { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | .checklist-text { |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .checklist-content { |
| | | .checkobx__list { |
| | | opacity: 1; |
| | | border-color: $uni-primary; |
| | | } |
| | | } |
| | | |
| | | // 选中禁用 |
| | | &.is-disable { |
| | | .checkbox__inner { |
| | | opacity: $disable; |
| | | } |
| | | |
| | | .checklist-text { |
| | | opacity: $disable; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-data-checkbox", |
| | | "displayName": "uni-data-checkbox 数据选择器", |
| | | "version": "1.0.3", |
| | | "description": "通过数据驱动的单选框和复选框", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "checkbox", |
| | | "单选", |
| | | "多选", |
| | | "单选多选" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "^3.1.1" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-load-more","uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## DataCheckbox 数据驱动的单选复选框 |
| | | > **组件名:uni-data-checkbox** |
| | | > 代码块: `uDataCheckbox` |
| | | |
| | | |
| | | 本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括: |
| | | |
| | | 1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能 |
| | | 2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验 |
| | | 3. 本组件合并了单选多选 |
| | | 4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性 |
| | | |
| | | 在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.1.2(2023-04-11) |
| | | - 修复 更改 modelValue 报错的 bug |
| | | - 修复 v-for 未使用 key 值控制台 warning |
| | | ## 1.1.1(2023-02-21) |
| | | - 修复代码合并时引发 value 属性为空时不渲染数据的问题 |
| | | ## 1.1.0(2023-02-15) |
| | | - 修复 localdata 不支持动态更新的bug |
| | | ## 1.0.9(2023-02-15) |
| | | - 修复 localdata 不支持动态更新的bug |
| | | ## 1.0.8(2022-09-16) |
| | | - 可以使用 uni-scss 控制主题色 |
| | | ## 1.0.7(2022-07-06) |
| | | - 优化 pc端图标位置不正确的问题 |
| | | ## 1.0.6(2022-07-05) |
| | | - 优化 显示样式 |
| | | ## 1.0.5(2022-07-04) |
| | | - 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug |
| | | ## 1.0.4(2022-04-19) |
| | | - 修复 字节小程序 本地数据无法选择下一级的Bug |
| | | ## 1.0.3(2022-02-25) |
| | | - 修复 nvue 不支持的 v-show 的 bug |
| | | ## 1.0.2(2022-02-25) |
| | | - 修复 条件编译 nvue 不支持的 css 样式 |
| | | ## 1.0.1(2021-11-23) |
| | | - 修复 由上个版本引发的map、v-model等属性不生效的bug |
| | | ## 1.0.0(2021-11-19) |
| | | - 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker) |
| | | ## 0.4.9(2021-10-28) |
| | | - 修复 VUE2 v-model 概率无效的 bug |
| | | ## 0.4.8(2021-10-27) |
| | | - 修复 v-model 概率无效的 bug |
| | | ## 0.4.7(2021-10-25) |
| | | - 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+ |
| | | - 修复 树型 uniCloud 数据类型为 int 时报错的 bug |
| | | ## 0.4.6(2021-10-19) |
| | | - 修复 非 VUE3 v-model 为 0 时无法选中的 bug |
| | | ## 0.4.5(2021-09-26) |
| | | - 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效 |
| | | - 修复 readonly 为 true 时报错的 bug |
| | | ## 0.4.4(2021-09-26) |
| | | - 修复 上一版本造成的 map 属性失效的 bug |
| | | - 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略 |
| | | ## 0.4.3(2021-09-24) |
| | | - 修复 某些情况下级联未触发的 bug |
| | | ## 0.4.2(2021-09-23) |
| | | - 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用 |
| | | - 新增 选项内容过长自动添加省略号 |
| | | ## 0.4.1(2021-09-15) |
| | | - 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段 |
| | | ## 0.4.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 0.3.5(2021-06-04) |
| | | - 修复 无法加载云端数据的问题 |
| | | ## 0.3.4(2021-05-28) |
| | | - 修复 v-model 无效问题 |
| | | - 修复 loaddata 为空数据组时加载时间过长问题 |
| | | - 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点 |
| | | ## 0.3.3(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 0.3.2(2021-04-22) |
| | | - 修复 非树形数据有 where 属性查询报错的问题 |
| | | ## 0.3.1(2021-04-15) |
| | | - 修复 本地数据概率无法回显时问题 |
| | | ## 0.3.0(2021-04-07) |
| | | - 新增 支持云端非树形表结构数据 |
| | | - 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题 |
| | | ## 0.2.0(2021-03-15) |
| | | - 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题 |
| | | ## 0.1.9(2021-03-09) |
| | | - 修复 微信小程序某些情况下无法选择的问题 |
| | | ## 0.1.8(2021-02-05) |
| | | - 优化 部分样式在 nvue 上的兼容表现 |
| | | ## 0.1.7(2021-02-05) |
| | | - 调整为 uni_modules 目录规范 |
对比新文件 |
| | |
| | | // #ifdef H5 |
| | | export default { |
| | | name: 'Keypress', |
| | | props: { |
| | | disable: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | mounted () { |
| | | const keyNames = { |
| | | esc: ['Esc', 'Escape'], |
| | | tab: 'Tab', |
| | | enter: 'Enter', |
| | | space: [' ', 'Spacebar'], |
| | | up: ['Up', 'ArrowUp'], |
| | | left: ['Left', 'ArrowLeft'], |
| | | right: ['Right', 'ArrowRight'], |
| | | down: ['Down', 'ArrowDown'], |
| | | delete: ['Backspace', 'Delete', 'Del'] |
| | | } |
| | | const listener = ($event) => { |
| | | if (this.disable) { |
| | | return |
| | | } |
| | | const keyName = Object.keys(keyNames).find(key => { |
| | | const keyName = $event.key |
| | | const value = keyNames[key] |
| | | return value === keyName || (Array.isArray(value) && value.includes(keyName)) |
| | | }) |
| | | if (keyName) { |
| | | // 避免和其他按键事件冲突 |
| | | setTimeout(() => { |
| | | this.$emit(keyName, {}) |
| | | }, 0) |
| | | } |
| | | } |
| | | document.addEventListener('keyup', listener) |
| | | this.$once('hook:beforeDestroy', () => { |
| | | document.removeEventListener('keyup', listener) |
| | | }) |
| | | }, |
| | | render: () => {} |
| | | } |
| | | // #endif |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-data-tree"> |
| | | <view class="uni-data-tree-input" @click="handleInput"> |
| | | <slot :options="options" :data="inputSelected" :error="errorMessage"> |
| | | <view class="input-value" :class="{'input-value-border': border}"> |
| | | <text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text> |
| | | <view v-else-if="loading && !isOpened" class="selected-area"> |
| | | <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more> |
| | | </view> |
| | | <scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true"> |
| | | <view class="selected-list"> |
| | | <view class="selected-item" v-for="(item,index) in inputSelected" :key="index"> |
| | | <text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1" |
| | | class="input-split-line">{{split}}</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | <text v-else class="selected-area placeholder">{{placeholder}}</text> |
| | | <view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear"> |
| | | <uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons> |
| | | </view> |
| | | <view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly "> |
| | | <view class="input-arrow"></view> |
| | | </view> |
| | | </view> |
| | | </slot> |
| | | </view> |
| | | <view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view> |
| | | <view class="uni-data-tree-dialog" v-if="isOpened"> |
| | | <view class="uni-popper__arrow"></view> |
| | | <view class="dialog-caption"> |
| | | <view class="title-area"> |
| | | <text class="dialog-title">{{popupTitle}}</text> |
| | | </view> |
| | | <view class="dialog-close" @click="handleClose"> |
| | | <view class="dialog-close-plus" data-id="close"></view> |
| | | <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view> |
| | | </view> |
| | | </view> |
| | | <data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata" |
| | | :preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where" |
| | | :step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true" :map="map" |
| | | :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick"> |
| | | </data-picker-view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import dataPicker from "../uni-data-pickerview/uni-data-picker.js" |
| | | import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue" |
| | | |
| | | /** |
| | | * DataPicker 级联选择 |
| | | * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
| | | * @property {String} popup-title 弹出窗口标题 |
| | | * @property {Array} localdata 本地数据,参考 |
| | | * @property {Boolean} border = [true|false] 是否有边框 |
| | | * @property {Boolean} readonly = [true|false] 是否仅读 |
| | | * @property {Boolean} preload = [true|false] 是否预加载数据 |
| | | * @value true 开启预加载数据,点击弹出窗口后显示已加载数据 |
| | | * @value false 关闭预加载数据,点击弹出窗口后开始加载数据 |
| | | * @property {Boolean} step-searh = [true|false] 是否分布查询 |
| | | * @value true 启用分布查询,仅查询当前选中节点 |
| | | * @value false 关闭分布查询,一次查询出所有数据 |
| | | * @property {String|DBFieldString} self-field 分布查询当前字段名称 |
| | | * @property {String|DBFieldString} parent-field 分布查询父字段名称 |
| | | * @property {String|DBCollectionString} collection 表名 |
| | | * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
| | | * @property {String} orderby 排序字段及正序倒叙设置 |
| | | * @property {String|JQLString} where 查询条件 |
| | | * @event {Function} popupshow 弹出的选择窗口打开时触发此事件 |
| | | * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件 |
| | | */ |
| | | export default { |
| | | name: 'UniDataPicker', |
| | | emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue','inputclick'], |
| | | mixins: [dataPicker], |
| | | components: { |
| | | DataPickerView |
| | | }, |
| | | props: { |
| | | options: { |
| | | type: [Object, Array], |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | popupTitle: { |
| | | type: String, |
| | | default: '请选择' |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: '请选择' |
| | | }, |
| | | heightMobile: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | readonly: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | clearIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | split: { |
| | | type: String, |
| | | default: '/' |
| | | }, |
| | | ellipsis: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isOpened: false, |
| | | inputSelected: [] |
| | | } |
| | | }, |
| | | created() { |
| | | this.$nextTick(() => { |
| | | this.load(); |
| | | }) |
| | | }, |
| | | watch: { |
| | | localdata: { |
| | | handler() { |
| | | this.load() |
| | | }, |
| | | deep: true |
| | | }, |
| | | }, |
| | | methods: { |
| | | clear() { |
| | | this._dispatchEvent([]); |
| | | }, |
| | | onPropsChange() { |
| | | this._treeData = []; |
| | | this.selectedIndex = 0; |
| | | |
| | | this.load(); |
| | | }, |
| | | load() { |
| | | if (this.readonly) { |
| | | this._processReadonly(this.localdata, this.dataValue); |
| | | return; |
| | | } |
| | | |
| | | // 回显本地数据 |
| | | if (this.isLocalData) { |
| | | this.loadData(); |
| | | this.inputSelected = this.selected.slice(0); |
| | | } else if (this.isCloudDataList || this.isCloudDataTree) { // 回显 Cloud 数据 |
| | | this.loading = true; |
| | | this.getCloudDataValue().then((res) => { |
| | | this.loading = false; |
| | | this.inputSelected = res; |
| | | }).catch((err) => { |
| | | this.loading = false; |
| | | this.errorMessage = err; |
| | | }) |
| | | } |
| | | }, |
| | | show() { |
| | | this.isOpened = true |
| | | setTimeout(() => { |
| | | this.$refs.pickerView.updateData({ |
| | | treeData: this._treeData, |
| | | selected: this.selected, |
| | | selectedIndex: this.selectedIndex |
| | | }) |
| | | }, 200) |
| | | this.$emit('popupopened') |
| | | }, |
| | | hide() { |
| | | this.isOpened = false |
| | | this.$emit('popupclosed') |
| | | }, |
| | | handleInput() { |
| | | if (this.readonly) { |
| | | this.$emit('inputclick') |
| | | return |
| | | } |
| | | this.show() |
| | | }, |
| | | handleClose(e) { |
| | | this.hide() |
| | | }, |
| | | onnodeclick(e) { |
| | | this.$emit('nodeclick', e) |
| | | }, |
| | | ondatachange(e) { |
| | | this._treeData = this.$refs.pickerView._treeData |
| | | }, |
| | | onchange(e) { |
| | | this.hide() |
| | | this.$nextTick(() => { |
| | | this.inputSelected = e; |
| | | }) |
| | | this._dispatchEvent(e) |
| | | }, |
| | | _processReadonly(dataList, value) { |
| | | var isTree = dataList.findIndex((item) => { |
| | | return item.children |
| | | }) |
| | | if (isTree > -1) { |
| | | let inputValue |
| | | if (Array.isArray(value)) { |
| | | inputValue = value[value.length - 1] |
| | | if (typeof inputValue === 'object' && inputValue.value) { |
| | | inputValue = inputValue.value |
| | | } |
| | | } else { |
| | | inputValue = value |
| | | } |
| | | this.inputSelected = this._findNodePath(inputValue, this.localdata) |
| | | return |
| | | } |
| | | |
| | | if (!this.hasValue) { |
| | | this.inputSelected = [] |
| | | return |
| | | } |
| | | |
| | | let result = [] |
| | | for (let i = 0; i < value.length; i++) { |
| | | var val = value[i] |
| | | var item = dataList.find((v) => { |
| | | return v.value == val |
| | | }) |
| | | if (item) { |
| | | result.push(item) |
| | | } |
| | | } |
| | | if (result.length) { |
| | | this.inputSelected = result |
| | | } |
| | | }, |
| | | _filterForArray(data, valueArray) { |
| | | var result = [] |
| | | for (let i = 0; i < valueArray.length; i++) { |
| | | var value = valueArray[i] |
| | | var found = data.find((item) => { |
| | | return item.value == value |
| | | }) |
| | | if (found) { |
| | | result.push(found) |
| | | } |
| | | } |
| | | return result |
| | | }, |
| | | _dispatchEvent(selected) { |
| | | let item = {} |
| | | if (selected.length) { |
| | | var value = new Array(selected.length) |
| | | for (var i = 0; i < selected.length; i++) { |
| | | value[i] = selected[i].value |
| | | } |
| | | item = selected[selected.length - 1] |
| | | } else { |
| | | item.value = '' |
| | | } |
| | | if (this.formItem) { |
| | | this.formItem.setValue(item.value) |
| | | } |
| | | |
| | | this.$emit('input', item.value) |
| | | this.$emit('update:modelValue', item.value) |
| | | this.$emit('change', { |
| | | detail: { |
| | | value: selected |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .uni-data-tree { |
| | | flex: 1; |
| | | position: relative; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .error-text { |
| | | color: #DD524D; |
| | | } |
| | | |
| | | .input-value { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | flex-wrap: nowrap; |
| | | font-size: 14px; |
| | | /* line-height: 35px; */ |
| | | padding: 0 10px; |
| | | padding-right: 5px; |
| | | overflow: hidden; |
| | | height: 35px; |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .input-value-border { |
| | | border: 1px solid #e5e5e5; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .selected-area { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .load-more { |
| | | /* #ifndef APP-NVUE */ |
| | | margin-right: auto; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | width: 40px; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .selected-list { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | flex-wrap: nowrap; |
| | | /* padding: 0 5px; */ |
| | | } |
| | | |
| | | .selected-item { |
| | | flex-direction: row; |
| | | /* padding: 0 1px; */ |
| | | /* #ifndef APP-NVUE */ |
| | | white-space: nowrap; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .text-color { |
| | | color: #333; |
| | | } |
| | | |
| | | .placeholder { |
| | | color: grey; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .input-split-line { |
| | | opacity: .5; |
| | | } |
| | | |
| | | .arrow-area { |
| | | position: relative; |
| | | width: 20px; |
| | | /* #ifndef APP-NVUE */ |
| | | margin-bottom: 5px; |
| | | margin-left: auto; |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | transform: rotate(-45deg); |
| | | transform-origin: center; |
| | | } |
| | | |
| | | .input-arrow { |
| | | width: 7px; |
| | | height: 7px; |
| | | border-left: 1px solid #999; |
| | | border-bottom: 1px solid #999; |
| | | } |
| | | |
| | | .uni-data-tree-cover { |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, .4); |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | z-index: 100; |
| | | } |
| | | |
| | | .uni-data-tree-dialog { |
| | | position: fixed; |
| | | left: 0; |
| | | /* #ifndef APP-NVUE */ |
| | | top: 20%; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | top: 200px; |
| | | /* #endif */ |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: #FFFFFF; |
| | | border-top-left-radius: 10px; |
| | | border-top-right-radius: 10px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | z-index: 102; |
| | | overflow: hidden; |
| | | /* #ifdef APP-NVUE */ |
| | | width: 750rpx; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .dialog-caption { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | /* border-bottom: 1px solid #f0f0f0; */ |
| | | } |
| | | |
| | | .title-area { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | /* #ifndef APP-NVUE */ |
| | | margin: auto; |
| | | /* #endif */ |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .dialog-title { |
| | | /* font-weight: bold; */ |
| | | line-height: 44px; |
| | | } |
| | | |
| | | .dialog-close { |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | padding: 0 15px; |
| | | } |
| | | |
| | | .dialog-close-plus { |
| | | width: 16px; |
| | | height: 2px; |
| | | background-color: #666; |
| | | border-radius: 2px; |
| | | transform: rotate(45deg); |
| | | } |
| | | |
| | | .dialog-close-rotate { |
| | | position: absolute; |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .picker-view { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .icon-clear { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | /* #ifdef H5 */ |
| | | @media all and (min-width: 768px) { |
| | | .uni-data-tree-cover { |
| | | background-color: transparent; |
| | | } |
| | | |
| | | .uni-data-tree-dialog { |
| | | position: absolute; |
| | | top: 55px; |
| | | height: auto; |
| | | min-height: 400px; |
| | | max-height: 50vh; |
| | | background-color: #fff; |
| | | border: 1px solid #EBEEF5; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | border-radius: 4px; |
| | | overflow: unset; |
| | | } |
| | | |
| | | .dialog-caption { |
| | | display: none; |
| | | } |
| | | |
| | | .icon-clear { |
| | | /* margin-right: 5px; */ |
| | | } |
| | | } |
| | | |
| | | /* #endif */ |
| | | |
| | | /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */ |
| | | /* #ifndef APP-NVUE */ |
| | | .uni-popper__arrow, |
| | | .uni-popper__arrow::after { |
| | | position: absolute; |
| | | display: block; |
| | | width: 0; |
| | | height: 0; |
| | | border-color: transparent; |
| | | border-style: solid; |
| | | border-width: 6px; |
| | | } |
| | | |
| | | .uni-popper__arrow { |
| | | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
| | | top: -6px; |
| | | left: 10%; |
| | | margin-right: 3px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #EBEEF5; |
| | | } |
| | | |
| | | .uni-popper__arrow::after { |
| | | content: " "; |
| | | top: 1px; |
| | | margin-left: -6px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #fff; |
| | | } |
| | | |
| | | /* #endif */ |
| | | </style> |
对比新文件 |
| | |
| | | export default { |
| | | props: { |
| | | localdata: { |
| | | type: [Array, Object], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | spaceInfo: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | collection: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | action: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | field: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | orderby: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | where: { |
| | | type: [String, Object], |
| | | default: '' |
| | | }, |
| | | pageData: { |
| | | type: String, |
| | | default: 'add' |
| | | }, |
| | | pageCurrent: { |
| | | type: Number, |
| | | default: 1 |
| | | }, |
| | | pageSize: { |
| | | type: Number, |
| | | default: 500 |
| | | }, |
| | | getcount: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | getone: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | gettree: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | manual: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | value: { |
| | | type: [Array, String, Number], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | modelValue: { |
| | | type: [Array, String, Number], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | preload: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | stepSearh: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | selfField: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | parentField: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | multiple: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | map: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | text: "text", |
| | | value: "value" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | loading: false, |
| | | errorMessage: '', |
| | | loadMore: { |
| | | contentdown: '', |
| | | contentrefresh: '', |
| | | contentnomore: '' |
| | | }, |
| | | dataList: [], |
| | | selected: [], |
| | | selectedIndex: 0, |
| | | page: { |
| | | current: this.pageCurrent, |
| | | size: this.pageSize, |
| | | count: 0 |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | isLocalData() { |
| | | return !this.collection.length; |
| | | }, |
| | | isCloudData() { |
| | | return this.collection.length > 0; |
| | | }, |
| | | isCloudDataList() { |
| | | return (this.isCloudData && (!this.parentField && !this.selfField)); |
| | | }, |
| | | isCloudDataTree() { |
| | | return (this.isCloudData && this.parentField && this.selfField); |
| | | }, |
| | | dataValue() { |
| | | let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || |
| | | this.modelValue !== undefined); |
| | | return isModelValue ? this.modelValue : this.value; |
| | | }, |
| | | hasValue() { |
| | | if (typeof this.dataValue === 'number') { |
| | | return true |
| | | } |
| | | return (this.dataValue != null) && (this.dataValue.length > 0) |
| | | } |
| | | }, |
| | | created() { |
| | | this.$watch(() => { |
| | | var al = []; |
| | | ['pageCurrent', |
| | | 'pageSize', |
| | | 'spaceInfo', |
| | | 'value', |
| | | 'modelValue', |
| | | 'localdata', |
| | | 'collection', |
| | | 'action', |
| | | 'field', |
| | | 'orderby', |
| | | 'where', |
| | | 'getont', |
| | | 'getcount', |
| | | 'gettree' |
| | | ].forEach(key => { |
| | | al.push(this[key]) |
| | | }); |
| | | return al |
| | | }, (newValue, oldValue) => { |
| | | let needReset = false |
| | | for (let i = 2; i < newValue.length; i++) { |
| | | if (newValue[i] != oldValue[i]) { |
| | | needReset = true |
| | | break |
| | | } |
| | | } |
| | | if (newValue[0] != oldValue[0]) { |
| | | this.page.current = this.pageCurrent |
| | | } |
| | | this.page.size = this.pageSize |
| | | |
| | | this.onPropsChange() |
| | | }) |
| | | this._treeData = [] |
| | | }, |
| | | methods: { |
| | | onPropsChange() { |
| | | this._treeData = []; |
| | | }, |
| | | |
| | | // 填充 pickview 数据 |
| | | async loadData() { |
| | | if (this.isLocalData) { |
| | | this.loadLocalData(); |
| | | } else if (this.isCloudDataList) { |
| | | this.loadCloudDataList(); |
| | | } else if (this.isCloudDataTree) { |
| | | this.loadCloudDataTree(); |
| | | } |
| | | }, |
| | | |
| | | // 加载本地数据 |
| | | async loadLocalData() { |
| | | this._treeData = []; |
| | | this._extractTree(this.localdata, this._treeData); |
| | | |
| | | let inputValue = this.dataValue; |
| | | if (inputValue === undefined) { |
| | | return; |
| | | } |
| | | |
| | | if (Array.isArray(inputValue)) { |
| | | inputValue = inputValue[inputValue.length - 1]; |
| | | if (typeof inputValue === 'object' && inputValue[this.map.value]) { |
| | | inputValue = inputValue[this.map.value]; |
| | | } |
| | | } |
| | | |
| | | this.selected = this._findNodePath(inputValue, this.localdata); |
| | | }, |
| | | |
| | | // 加载 Cloud 数据 (单列) |
| | | async loadCloudDataList() { |
| | | if (this.loading) { |
| | | return; |
| | | } |
| | | this.loading = true; |
| | | |
| | | try { |
| | | let response = await this.getCommand(); |
| | | let responseData = response.result.data; |
| | | |
| | | this._treeData = responseData; |
| | | |
| | | this._updateBindData(); |
| | | this._updateSelected(); |
| | | |
| | | this.onDataChange(); |
| | | } catch (e) { |
| | | this.errorMessage = e; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 加载 Cloud 数据 (树形) |
| | | async loadCloudDataTree() { |
| | | if (this.loading) { |
| | | return; |
| | | } |
| | | this.loading = true; |
| | | |
| | | try { |
| | | let commandOptions = { |
| | | field: this._cloudDataPostField(), |
| | | where: this._cloudDataTreeWhere() |
| | | }; |
| | | if (this.gettree) { |
| | | commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`; |
| | | } |
| | | |
| | | let response = await this.getCommand(commandOptions); |
| | | let responseData = response.result.data; |
| | | |
| | | this._treeData = responseData; |
| | | this._updateBindData(); |
| | | this._updateSelected(); |
| | | |
| | | this.onDataChange(); |
| | | } catch (e) { |
| | | this.errorMessage = e; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 加载 Cloud 数据 (节点) |
| | | async loadCloudDataNode(callback) { |
| | | if (this.loading) { |
| | | return; |
| | | } |
| | | this.loading = true; |
| | | |
| | | try { |
| | | let commandOptions = { |
| | | field: this._cloudDataPostField(), |
| | | where: this._cloudDataNodeWhere() |
| | | }; |
| | | |
| | | let response = await this.getCommand(commandOptions); |
| | | let responseData = response.result.data; |
| | | |
| | | callback(responseData); |
| | | } catch (e) { |
| | | this.errorMessage = e; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 回显 Cloud 数据 |
| | | getCloudDataValue() { |
| | | if (this.isCloudDataList) { |
| | | return this.getCloudDataListValue(); |
| | | } |
| | | |
| | | if (this.isCloudDataTree) { |
| | | return this.getCloudDataTreeValue(); |
| | | } |
| | | }, |
| | | |
| | | // 回显 Cloud 数据 (单列) |
| | | getCloudDataListValue() { |
| | | // 根据 field's as value标识匹配 where 条件 |
| | | let where = []; |
| | | let whereField = this._getForeignKeyByField(); |
| | | if (whereField) { |
| | | where.push(`${whereField} == '${this.dataValue}'`) |
| | | } |
| | | |
| | | where = where.join(' || '); |
| | | |
| | | if (this.where) { |
| | | where = `(${this.where}) && (${where})` |
| | | } |
| | | |
| | | return this.getCommand({ |
| | | field: this._cloudDataPostField(), |
| | | where |
| | | }).then((res) => { |
| | | this.selected = res.result.data; |
| | | return res.result.data; |
| | | }); |
| | | }, |
| | | |
| | | // 回显 Cloud 数据 (树形) |
| | | getCloudDataTreeValue() { |
| | | return this.getCommand({ |
| | | field: this._cloudDataPostField(), |
| | | getTreePath: { |
| | | startWith: `${this.selfField}=='${this.dataValue}'` |
| | | } |
| | | }).then((res) => { |
| | | let treePath = []; |
| | | this._extractTreePath(res.result.data, treePath); |
| | | this.selected = treePath; |
| | | return treePath; |
| | | }); |
| | | }, |
| | | |
| | | getCommand(options = {}) { |
| | | /* eslint-disable no-undef */ |
| | | let db = uniCloud.database(this.spaceInfo) |
| | | |
| | | const action = options.action || this.action |
| | | if (action) { |
| | | db = db.action(action) |
| | | } |
| | | |
| | | const collection = options.collection || this.collection |
| | | db = db.collection(collection) |
| | | |
| | | const where = options.where || this.where |
| | | if (!(!where || !Object.keys(where).length)) { |
| | | db = db.where(where) |
| | | } |
| | | |
| | | const field = options.field || this.field |
| | | if (field) { |
| | | db = db.field(field) |
| | | } |
| | | |
| | | const orderby = options.orderby || this.orderby |
| | | if (orderby) { |
| | | db = db.orderBy(orderby) |
| | | } |
| | | |
| | | const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current |
| | | const size = options.pageSize !== undefined ? options.pageSize : this.page.size |
| | | const getCount = options.getcount !== undefined ? options.getcount : this.getcount |
| | | const getTree = options.gettree !== undefined ? options.gettree : this.gettree |
| | | |
| | | const getOptions = { |
| | | getCount, |
| | | getTree |
| | | } |
| | | if (options.getTreePath) { |
| | | getOptions.getTreePath = options.getTreePath |
| | | } |
| | | |
| | | db = db.skip(size * (current - 1)).limit(size).get(getOptions) |
| | | |
| | | return db |
| | | }, |
| | | |
| | | _cloudDataPostField() { |
| | | let fields = [this.field]; |
| | | if (this.parentField) { |
| | | fields.push(`${this.parentField} as parent_value`); |
| | | } |
| | | return fields.join(','); |
| | | }, |
| | | |
| | | _cloudDataTreeWhere() { |
| | | let result = [] |
| | | let selected = this.selected |
| | | let parentField = this.parentField |
| | | if (parentField) { |
| | | result.push(`${parentField} == null || ${parentField} == ""`) |
| | | } |
| | | if (selected.length) { |
| | | for (var i = 0; i < selected.length - 1; i++) { |
| | | result.push(`${parentField} == '${selected[i].value}'`) |
| | | } |
| | | } |
| | | |
| | | let where = [] |
| | | if (this.where) { |
| | | where.push(`(${this.where})`) |
| | | } |
| | | |
| | | if (result.length) { |
| | | where.push(`(${result.join(' || ')})`) |
| | | } |
| | | |
| | | return where.join(' && ') |
| | | }, |
| | | |
| | | _cloudDataNodeWhere() { |
| | | let where = [] |
| | | let selected = this.selected; |
| | | if (selected.length) { |
| | | where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`); |
| | | } |
| | | |
| | | where = where.join(' || '); |
| | | |
| | | if (this.where) { |
| | | return `(${this.where}) && (${where})` |
| | | } |
| | | |
| | | return where |
| | | }, |
| | | |
| | | _getWhereByForeignKey() { |
| | | let result = [] |
| | | let whereField = this._getForeignKeyByField(); |
| | | if (whereField) { |
| | | result.push(`${whereField} == '${this.dataValue}'`) |
| | | } |
| | | |
| | | if (this.where) { |
| | | return `(${this.where}) && (${result.join(' || ')})` |
| | | } |
| | | |
| | | return result.join(' || ') |
| | | }, |
| | | |
| | | _getForeignKeyByField() { |
| | | let fields = this.field.split(','); |
| | | let whereField = null; |
| | | for (let i = 0; i < fields.length; i++) { |
| | | const items = fields[i].split('as'); |
| | | if (items.length < 2) { |
| | | continue; |
| | | } |
| | | if (items[1].trim() === 'value') { |
| | | whereField = items[0].trim(); |
| | | break; |
| | | } |
| | | } |
| | | return whereField; |
| | | }, |
| | | |
| | | _updateBindData(node) { |
| | | const { |
| | | dataList, |
| | | hasNodes |
| | | } = this._filterData(this._treeData, this.selected) |
| | | |
| | | let isleaf = this._stepSearh === false && !hasNodes |
| | | |
| | | if (node) { |
| | | node.isleaf = isleaf |
| | | } |
| | | |
| | | this.dataList = dataList |
| | | this.selectedIndex = dataList.length - 1 |
| | | |
| | | if (!isleaf && this.selected.length < dataList.length) { |
| | | this.selected.push({ |
| | | value: null, |
| | | text: "请选择" |
| | | }) |
| | | } |
| | | |
| | | return { |
| | | isleaf, |
| | | hasNodes |
| | | } |
| | | }, |
| | | |
| | | _updateSelected() { |
| | | let dl = this.dataList |
| | | let sl = this.selected |
| | | let textField = this.map.text |
| | | let valueField = this.map.value |
| | | for (let i = 0; i < sl.length; i++) { |
| | | let value = sl[i].value |
| | | let dl2 = dl[i] |
| | | for (let j = 0; j < dl2.length; j++) { |
| | | let item2 = dl2[j] |
| | | if (item2[valueField] === value) { |
| | | sl[i].text = item2[textField] |
| | | break |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _filterData(data, paths) { |
| | | let dataList = [] |
| | | let hasNodes = true |
| | | |
| | | dataList.push(data.filter((item) => { |
| | | return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '') |
| | | })) |
| | | for (let i = 0; i < paths.length; i++) { |
| | | let value = paths[i].value |
| | | let nodes = data.filter((item) => { |
| | | return item.parent_value === value |
| | | }) |
| | | |
| | | if (nodes.length) { |
| | | dataList.push(nodes) |
| | | } else { |
| | | hasNodes = false |
| | | } |
| | | } |
| | | |
| | | return { |
| | | dataList, |
| | | hasNodes |
| | | } |
| | | }, |
| | | |
| | | _extractTree(nodes, result, parent_value) { |
| | | let list = result || [] |
| | | let valueField = this.map.value |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | let node = nodes[i] |
| | | |
| | | let child = {} |
| | | for (let key in node) { |
| | | if (key !== 'children') { |
| | | child[key] = node[key] |
| | | } |
| | | } |
| | | if (parent_value !== null && parent_value !== undefined && parent_value !== '') { |
| | | child.parent_value = parent_value |
| | | } |
| | | result.push(child) |
| | | |
| | | let children = node.children |
| | | if (children) { |
| | | this._extractTree(children, result, node[valueField]) |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _extractTreePath(nodes, result) { |
| | | let list = result || [] |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | let node = nodes[i] |
| | | |
| | | let child = {} |
| | | for (let key in node) { |
| | | if (key !== 'children') { |
| | | child[key] = node[key] |
| | | } |
| | | } |
| | | result.push(child) |
| | | |
| | | let children = node.children |
| | | if (children) { |
| | | this._extractTreePath(children, result) |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _findNodePath(key, nodes, path = []) { |
| | | let textField = this.map.text |
| | | let valueField = this.map.value |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | let node = nodes[i] |
| | | let children = node.children |
| | | let text = node[textField] |
| | | let value = node[valueField] |
| | | |
| | | path.push({ |
| | | value, |
| | | text |
| | | }) |
| | | |
| | | if (value === key) { |
| | | return path |
| | | } |
| | | |
| | | if (children) { |
| | | const p = this._findNodePath(key, children, path) |
| | | if (p.length) { |
| | | return p |
| | | } |
| | | } |
| | | |
| | | path.pop() |
| | | } |
| | | return [] |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-data-pickerview"> |
| | | <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true"> |
| | | <view class="selected-list"> |
| | | <view |
| | | class="selected-item" |
| | | v-for="(item,index) in selected" |
| | | :key="index" |
| | | :class="{ |
| | | 'selected-item-active':index == selectedIndex |
| | | }" |
| | | @click="handleSelect(index)" |
| | | > |
| | | <text>{{item.text || ''}}</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | <view class="tab-c"> |
| | | <scroll-view class="list" :scroll-y="true"> |
| | | <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in dataList[selectedIndex]" :key="j" |
| | | @click="handleNodeClick(item, selectedIndex, j)"> |
| | | <text class="item-text">{{item[map.text]}}</text> |
| | | <view class="check" v-if="selected.length > selectedIndex && item[map.value] == selected[selectedIndex].value"></view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <view class="loading-cover" v-if="loading"> |
| | | <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more> |
| | | </view> |
| | | <view class="error-message" v-if="errorMessage"> |
| | | <text class="error-text">{{errorMessage}}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import dataPicker from "./uni-data-picker.js" |
| | | |
| | | /** |
| | | * DataPickerview |
| | | * @description uni-data-pickerview |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
| | | * @property {Array} localdata 本地数据,参考 |
| | | * @property {Boolean} step-searh = [true|false] 是否分布查询 |
| | | * @value true 启用分布查询,仅查询当前选中节点 |
| | | * @value false 关闭分布查询,一次查询出所有数据 |
| | | * @property {String|DBFieldString} self-field 分布查询当前字段名称 |
| | | * @property {String|DBFieldString} parent-field 分布查询父字段名称 |
| | | * @property {String|DBCollectionString} collection 表名 |
| | | * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
| | | * @property {String} orderby 排序字段及正序倒叙设置 |
| | | * @property {String|JQLString} where 查询条件 |
| | | */ |
| | | export default { |
| | | name: 'UniDataPickerView', |
| | | emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'], |
| | | mixins: [dataPicker], |
| | | props: { |
| | | managedMode: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | ellipsis: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | created() { |
| | | if (!this.managedMode) { |
| | | this.$nextTick(() => { |
| | | this.loadData(); |
| | | }) |
| | | } |
| | | }, |
| | | methods: { |
| | | onPropsChange() { |
| | | this._treeData = []; |
| | | this.selectedIndex = 0; |
| | | this.$nextTick(() => { |
| | | this.loadData(); |
| | | }) |
| | | }, |
| | | handleSelect(index) { |
| | | this.selectedIndex = index; |
| | | }, |
| | | handleNodeClick(item, i, j) { |
| | | if (item.disable) { |
| | | return; |
| | | } |
| | | |
| | | const node = this.dataList[i][j]; |
| | | const text = node[this.map.text]; |
| | | const value = node[this.map.value]; |
| | | |
| | | if (i < this.selected.length - 1) { |
| | | this.selected.splice(i, this.selected.length - i) |
| | | this.selected.push({ |
| | | text, |
| | | value |
| | | }) |
| | | } else if (i === this.selected.length - 1) { |
| | | this.selected.splice(i, 1, { |
| | | text, |
| | | value |
| | | }) |
| | | } |
| | | |
| | | if (node.isleaf) { |
| | | this.onSelectedChange(node, node.isleaf) |
| | | return |
| | | } |
| | | |
| | | const { |
| | | isleaf, |
| | | hasNodes |
| | | } = this._updateBindData() |
| | | |
| | | // 本地数据 |
| | | if (this.isLocalData) { |
| | | this.onSelectedChange(node, (!hasNodes || isleaf)) |
| | | } else if (this.isCloudDataList) { // Cloud 数据 (单列) |
| | | this.onSelectedChange(node, true) |
| | | } else if (this.isCloudDataTree) { // Cloud 数据 (树形) |
| | | if (isleaf) { |
| | | this.onSelectedChange(node, node.isleaf) |
| | | } else if (!hasNodes) { // 请求一次服务器以确定是否为叶子节点 |
| | | this.loadCloudDataNode((data) => { |
| | | if (!data.length) { |
| | | node.isleaf = true |
| | | } else { |
| | | this._treeData.push(...data) |
| | | this._updateBindData(node) |
| | | } |
| | | this.onSelectedChange(node, node.isleaf) |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | updateData(data) { |
| | | this._treeData = data.treeData |
| | | this.selected = data.selected |
| | | if (!this._treeData.length) { |
| | | this.loadData() |
| | | } else { |
| | | //this.selected = data.selected |
| | | this._updateBindData() |
| | | } |
| | | }, |
| | | onDataChange() { |
| | | this.$emit('datachange'); |
| | | }, |
| | | onSelectedChange(node, isleaf) { |
| | | if (isleaf) { |
| | | this._dispatchEvent() |
| | | } |
| | | |
| | | if (node) { |
| | | this.$emit('nodeclick', node) |
| | | } |
| | | }, |
| | | _dispatchEvent() { |
| | | this.$emit('change', this.selected.slice(0)) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-primary: #007aff !default; |
| | | |
| | | .uni-data-pickerview { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | height: 100%; |
| | | } |
| | | |
| | | .error-text { |
| | | color: #DD524D; |
| | | } |
| | | |
| | | .loading-cover { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(255, 255, 255, .5); |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | align-items: center; |
| | | z-index: 1001; |
| | | } |
| | | |
| | | .load-more { |
| | | /* #ifndef APP-NVUE */ |
| | | margin: auto; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .error-message { |
| | | background-color: #fff; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | padding: 15px; |
| | | opacity: .9; |
| | | z-index: 102; |
| | | } |
| | | |
| | | /* #ifdef APP-NVUE */ |
| | | .selected-area { |
| | | width: 750rpx; |
| | | } |
| | | /* #endif */ |
| | | |
| | | .selected-list { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | flex-wrap: nowrap; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | padding: 0 5px; |
| | | border-bottom: 1px solid #f8f8f8; |
| | | } |
| | | |
| | | .selected-item { |
| | | margin-left: 10px; |
| | | margin-right: 10px; |
| | | padding: 12px 0; |
| | | text-align: center; |
| | | /* #ifndef APP-NVUE */ |
| | | white-space: nowrap; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .selected-item-text-overflow { |
| | | width: 168px; |
| | | /* fix nvue */ |
| | | overflow: hidden; |
| | | /* #ifndef APP-NVUE */ |
| | | width: 6em; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | -o-text-overflow: ellipsis; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .selected-item-active { |
| | | border-bottom: 2px solid $uni-primary; |
| | | } |
| | | |
| | | .selected-item-text { |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .tab-c { |
| | | position: relative; |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .list { |
| | | flex: 1; |
| | | } |
| | | |
| | | .item { |
| | | padding: 12px 15px; |
| | | /* border-bottom: 1px solid #f0f0f0; */ |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .is-disabled { |
| | | opacity: .5; |
| | | } |
| | | |
| | | .item-text { |
| | | /* flex: 1; */ |
| | | color: #333333; |
| | | } |
| | | |
| | | .item-text-overflow { |
| | | width: 280px; |
| | | /* fix nvue */ |
| | | overflow: hidden; |
| | | /* #ifndef APP-NVUE */ |
| | | width: 20em; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | -o-text-overflow: ellipsis; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .check { |
| | | margin-right: 5px; |
| | | border: 2px solid $uni-primary; |
| | | border-left: 0; |
| | | border-top: 0; |
| | | height: 12px; |
| | | width: 6px; |
| | | transform-origin: center; |
| | | /* #ifndef APP-NVUE */ |
| | | transition: all 0.3s; |
| | | /* #endif */ |
| | | transform: rotate(45deg); |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-data-picker", |
| | | "displayName": "uni-data-picker 数据驱动的picker选择器", |
| | | "version": "1.1.2", |
| | | "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "picker", |
| | | "级联", |
| | | "省市区", |
| | | "" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-load-more", |
| | | "uni-icons", |
| | | "uni-scss" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "u" |
| | | }, |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | ## DataPicker 级联选择 |
| | | > **组件名:uni-data-picker** |
| | | > 代码块: `uDataPicker` |
| | | > 关联组件:`uni-data-pickerview`、`uni-load-more`。 |
| | | |
| | | |
| | | `<uni-data-picker>` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。 |
| | | |
| | | 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 |
| | | |
| | | 候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。 |
| | | |
| | | `<uni-data-picker>` 组件尤其适用于地址选择、分类选择等选择类。 |
| | | |
| | | `<uni-data-picker>` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。 |
| | | |
| | | `<uni-data-picker>` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。 |
| | | |
| | | 在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.0.6(2023-04-12) |
| | | - 修复 微信小程序点击时会改变背景颜色的 bug |
| | | ## 1.0.5(2023-02-03) |
| | | - 修复 禁用时会显示清空按钮 |
| | | ## 1.0.4(2023-02-02) |
| | | - 优化 查询条件短期内多次变更只查询最后一次变更后的结果 |
| | | - 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue |
| | | ## 1.0.3(2023-01-16) |
| | | - 修复 不关联服务空间报错的问题 |
| | | ## 1.0.2(2023-01-14) |
| | | - 新增 属性 `format` 可用于格式化显示选项内容 |
| | | ## 1.0.1(2022-12-06) |
| | | - 修复 当where变化时,数据不会自动更新的问题 |
| | | ## 0.1.9(2022-09-05) |
| | | - 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框 |
| | | ## 0.1.8(2022-08-29) |
| | | - 修复 点击的位置不准确 |
| | | ## 0.1.7(2022-08-12) |
| | | - 新增 支持 disabled 属性 |
| | | ## 0.1.6(2022-07-06) |
| | | - 修复 pc端宽度异常的bug |
| | | ## 0.1.5 |
| | | - 修复 pc端宽度异常的bug |
| | | ## 0.1.4(2022-07-05) |
| | | - 优化 显示样式 |
| | | ## 0.1.3(2022-06-02) |
| | | - 修复 localdata 赋值不生效的 bug |
| | | - 新增 支持 uni.scss 修改颜色 |
| | | - 新增 支持选项禁用(数据选项设置 disabled: true 即禁用) |
| | | ## 0.1.2(2022-05-08) |
| | | - 修复 当 value 为 0 时选择不生效的 bug |
| | | ## 0.1.1(2022-05-07) |
| | | - 新增 记住上次的选项(仅 collection 存在时有效) |
| | | ## 0.1.0(2022-04-22) |
| | | - 初始化 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-stat__select"> |
| | | <span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span> |
| | | <view class="uni-stat-box" :class="{'uni-stat__actived': current}"> |
| | | <view class="uni-select" :class="{'uni-select--disabled':disabled}"> |
| | | <view class="uni-select__input-box" @click="toggleSelector"> |
| | | <view v-if="current" class="uni-select__input-text">{{current}}</view> |
| | | <view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view> |
| | | <view v-if="current && clear && !disabled" @click.stop="clearVal" > |
| | | <uni-icons type="clear" color="#c0c4cc" size="24"/> |
| | | </view> |
| | | <view v-else> |
| | | <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" /> |
| | | </view> |
| | | </view> |
| | | <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" /> |
| | | <view class="uni-select__selector" v-if="showSelector"> |
| | | <view class="uni-popper__arrow"></view> |
| | | <scroll-view scroll-y="true" class="uni-select__selector-scroll"> |
| | | <view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0"> |
| | | <text>{{emptyTips}}</text> |
| | | </view> |
| | | <view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index" |
| | | @click="change(item)"> |
| | | <text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * DataChecklist 数据选择器 |
| | | * @description 通过数据渲染的下拉框组件 |
| | | * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select |
| | | * @property {String} value 默认值 |
| | | * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}] |
| | | * @property {Boolean} clear 是否可以清空已选项 |
| | | * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效 |
| | | * @property {String} label 左侧标题 |
| | | * @property {String} placeholder 输入框的提示文字 |
| | | * @property {Boolean} disabled 是否禁用 |
| | | * @event {Function} change 选中发生变化触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: "uni-data-select", |
| | | mixins: [uniCloud.mixinDatacom || {}], |
| | | props: { |
| | | localdata: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | modelValue: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | label: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: '请选择' |
| | | }, |
| | | emptyTips: { |
| | | type: String, |
| | | default: '无选项' |
| | | }, |
| | | clear: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | defItem: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}" |
| | | format: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | showSelector: false, |
| | | current: '', |
| | | mixinDatacomResData: [], |
| | | apps: [], |
| | | channels: [], |
| | | cacheKey: "uni-data-select-lastSelectedValue", |
| | | }; |
| | | }, |
| | | created() { |
| | | this.debounceGet = this.debounce(() => { |
| | | this.query(); |
| | | }, 300); |
| | | if (this.collection && !this.localdata.length) { |
| | | this.debounceGet(); |
| | | } |
| | | }, |
| | | computed: { |
| | | typePlaceholder() { |
| | | const text = { |
| | | 'opendb-stat-app-versions': '版本', |
| | | 'opendb-app-channels': '渠道', |
| | | 'opendb-app-list': '应用' |
| | | } |
| | | const common = this.placeholder |
| | | const placeholder = text[this.collection] |
| | | return placeholder ? |
| | | common + placeholder : |
| | | common |
| | | }, |
| | | valueCom(){ |
| | | // #ifdef VUE3 |
| | | return this.modelValue; |
| | | // #endif |
| | | // #ifndef VUE3 |
| | | return this.value; |
| | | // #endif |
| | | } |
| | | }, |
| | | watch: { |
| | | localdata: { |
| | | immediate: true, |
| | | handler(val, old) { |
| | | if (Array.isArray(val) && old !== val) { |
| | | this.mixinDatacomResData = val |
| | | } |
| | | } |
| | | }, |
| | | valueCom(val, old) { |
| | | this.initDefVal() |
| | | }, |
| | | mixinDatacomResData: { |
| | | immediate: true, |
| | | handler(val) { |
| | | if (val.length) { |
| | | this.initDefVal() |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | debounce(fn, time = 100){ |
| | | let timer = null |
| | | return function(...args) { |
| | | if (timer) clearTimeout(timer) |
| | | timer = setTimeout(() => { |
| | | fn.apply(this, args) |
| | | }, time) |
| | | } |
| | | }, |
| | | // 执行数据库查询 |
| | | query(){ |
| | | this.mixinDatacomEasyGet(); |
| | | }, |
| | | // 监听查询条件变更事件 |
| | | onMixinDatacomPropsChange(){ |
| | | if (this.collection) { |
| | | this.debounceGet(); |
| | | } |
| | | }, |
| | | initDefVal() { |
| | | let defValue = '' |
| | | if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) { |
| | | defValue = this.valueCom |
| | | } else { |
| | | let strogeValue |
| | | if (this.collection) { |
| | | strogeValue = this.getCache() |
| | | } |
| | | if (strogeValue || strogeValue === 0) { |
| | | defValue = strogeValue |
| | | } else { |
| | | let defItem = '' |
| | | if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) { |
| | | defItem = this.mixinDatacomResData[this.defItem - 1].value |
| | | } |
| | | defValue = defItem |
| | | } |
| | | if (defValue || defValue === 0) { |
| | | this.emit(defValue) |
| | | } |
| | | } |
| | | const def = this.mixinDatacomResData.find(item => item.value === defValue) |
| | | this.current = def ? this.formatItemName(def) : '' |
| | | }, |
| | | |
| | | /** |
| | | * @param {[String, Number]} value |
| | | * 判断用户给的 value 是否同时为禁用状态 |
| | | */ |
| | | isDisabled(value) { |
| | | let isDisabled = false; |
| | | |
| | | this.mixinDatacomResData.forEach(item => { |
| | | if (item.value === value) { |
| | | isDisabled = item.disable |
| | | } |
| | | }) |
| | | |
| | | return isDisabled; |
| | | }, |
| | | |
| | | clearVal() { |
| | | this.emit('') |
| | | if (this.collection) { |
| | | this.removeCache() |
| | | } |
| | | }, |
| | | change(item) { |
| | | if (!item.disable) { |
| | | this.showSelector = false |
| | | this.current = this.formatItemName(item) |
| | | this.emit(item.value) |
| | | } |
| | | }, |
| | | emit(val) { |
| | | this.$emit('input', val) |
| | | this.$emit('update:modelValue', val) |
| | | this.$emit('change', val) |
| | | if (this.collection) { |
| | | this.setCache(val); |
| | | } |
| | | }, |
| | | toggleSelector() { |
| | | if (this.disabled) { |
| | | return |
| | | } |
| | | |
| | | this.showSelector = !this.showSelector |
| | | }, |
| | | formatItemName(item) { |
| | | let { |
| | | text, |
| | | value, |
| | | channel_code |
| | | } = item |
| | | channel_code = channel_code ? `(${channel_code})` : '' |
| | | |
| | | if (this.format) { |
| | | // 格式化输出 |
| | | let str = ""; |
| | | str = this.format; |
| | | for (let key in item) { |
| | | str = str.replace(new RegExp(`{${key}}`,"g"),item[key]); |
| | | } |
| | | return str; |
| | | } else { |
| | | return this.collection.indexOf('app-list') > 0 ? |
| | | `${text}(${value})` : |
| | | ( |
| | | text ? |
| | | text : |
| | | `未命名${channel_code}` |
| | | ) |
| | | } |
| | | }, |
| | | // 获取当前加载的数据 |
| | | getLoadData(){ |
| | | return this.mixinDatacomResData; |
| | | }, |
| | | // 获取当前缓存key |
| | | getCurrentCacheKey(){ |
| | | return this.collection; |
| | | }, |
| | | // 获取缓存 |
| | | getCache(name=this.getCurrentCacheKey()){ |
| | | let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
| | | return cacheData[name]; |
| | | }, |
| | | // 设置缓存 |
| | | setCache(value, name=this.getCurrentCacheKey()){ |
| | | let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
| | | cacheData[name] = value; |
| | | uni.setStorageSync(this.cacheKey, cacheData); |
| | | }, |
| | | // 删除缓存 |
| | | removeCache(name=this.getCurrentCacheKey()){ |
| | | let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
| | | delete cacheData[name]; |
| | | uni.setStorageSync(this.cacheKey, cacheData); |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-base-color: #6a6a6a !default; |
| | | $uni-main-color: #333 !default; |
| | | $uni-secondary-color: #909399 !default; |
| | | $uni-border-3: #e5e5e5; |
| | | |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | @media screen and (max-width: 500px) { |
| | | .hide-on-phone { |
| | | display: none; |
| | | } |
| | | } |
| | | |
| | | /* #endif */ |
| | | .uni-stat__select { |
| | | display: flex; |
| | | align-items: center; |
| | | // padding: 15px; |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | width: 100%; |
| | | flex: 1; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .uni-stat-box { |
| | | width: 100%; |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-stat__actived { |
| | | width: 100%; |
| | | flex: 1; |
| | | // outline: 1px solid #2979ff; |
| | | } |
| | | |
| | | .uni-label-text { |
| | | font-size: 14px; |
| | | font-weight: bold; |
| | | color: $uni-base-color; |
| | | margin: auto 0; |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | .uni-select { |
| | | font-size: 14px; |
| | | border: 1px solid $uni-border-3; |
| | | box-sizing: border-box; |
| | | border-radius: 4px; |
| | | padding: 0 5px; |
| | | padding-left: 10px; |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | user-select: none; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | border-bottom: solid 1px $uni-border-3; |
| | | width: 100%; |
| | | flex: 1; |
| | | height: 35px; |
| | | |
| | | &--disabled { |
| | | background-color: #f5f7fa; |
| | | cursor: not-allowed; |
| | | } |
| | | } |
| | | |
| | | .uni-select__label { |
| | | font-size: 16px; |
| | | // line-height: 22px; |
| | | height: 35px; |
| | | padding-right: 10px; |
| | | color: $uni-secondary-color; |
| | | } |
| | | |
| | | .uni-select__input-box { |
| | | height: 35px; |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex: 1; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-select__input { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | height: 22px; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .uni-select__input-plac { |
| | | font-size: 14px; |
| | | color: $uni-secondary-color; |
| | | } |
| | | |
| | | .uni-select__selector { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | position: absolute; |
| | | top: calc(100% + 12px); |
| | | left: 0; |
| | | width: 100%; |
| | | background-color: #FFFFFF; |
| | | border: 1px solid #EBEEF5; |
| | | border-radius: 6px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | z-index: 3; |
| | | padding: 4px 0; |
| | | } |
| | | |
| | | .uni-select__selector-scroll { |
| | | /* #ifndef APP-NVUE */ |
| | | max-height: 200px; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | |
| | | /* #ifdef H5 */ |
| | | @media (min-width: 768px) { |
| | | .uni-select__selector-scroll { |
| | | max-height: 600px; |
| | | } |
| | | } |
| | | /* #endif */ |
| | | |
| | | .uni-select__selector-empty, |
| | | .uni-select__selector-item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | line-height: 35px; |
| | | font-size: 14px; |
| | | text-align: center; |
| | | /* border-bottom: solid 1px $uni-border-3; */ |
| | | padding: 0px 10px; |
| | | } |
| | | |
| | | .uni-select__selector-item:hover { |
| | | background-color: #f9f9f9; |
| | | } |
| | | |
| | | .uni-select__selector-empty:last-child, |
| | | .uni-select__selector-item:last-child { |
| | | /* #ifndef APP-NVUE */ |
| | | border-bottom: none; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-select__selector__disabled { |
| | | opacity: 0.4; |
| | | cursor: default; |
| | | } |
| | | |
| | | /* picker 弹出层通用的指示小三角 */ |
| | | .uni-popper__arrow, |
| | | .uni-popper__arrow::after { |
| | | position: absolute; |
| | | display: block; |
| | | width: 0; |
| | | height: 0; |
| | | border-color: transparent; |
| | | border-style: solid; |
| | | border-width: 6px; |
| | | } |
| | | |
| | | .uni-popper__arrow { |
| | | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
| | | top: -6px; |
| | | left: 10%; |
| | | margin-right: 3px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #EBEEF5; |
| | | } |
| | | |
| | | .uni-popper__arrow::after { |
| | | content: " "; |
| | | top: 1px; |
| | | margin-left: -6px; |
| | | border-top-width: 0; |
| | | border-bottom-color: #fff; |
| | | } |
| | | |
| | | .uni-select__input-text { |
| | | // width: 280px; |
| | | width: 100%; |
| | | color: $uni-main-color; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | -o-text-overflow: ellipsis; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .uni-select__input-placeholder { |
| | | color: $uni-base-color; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .uni-select--mask { |
| | | position: fixed; |
| | | top: 0; |
| | | bottom: 0; |
| | | right: 0; |
| | | left: 0; |
| | | z-index: 2; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-data-select", |
| | | "displayName": "uni-data-select 下拉框选择器", |
| | | "version": "1.0.6", |
| | | "description": "通过数据驱动的下拉框选择器", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "select", |
| | | "uni-data-select", |
| | | "下拉框", |
| | | "下拉选" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "^3.1.1" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-load-more"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "u", |
| | | "app-nvue": "n" |
| | | }, |
| | | "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", |
| | | "阿里": "u", |
| | | "百度": "u", |
| | | "字节跳动": "u", |
| | | "QQ": "u", |
| | | "京东": "u" |
| | | }, |
| | | "快应用": { |
| | | "华为": "u", |
| | | "联盟": "u" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | ## DataSelect 下拉框选择器 |
| | | > **组件名:uni-data-select** |
| | | > 代码块: `uDataSelect` |
| | | |
| | | 当选项过多时,使用下拉菜单展示并选择内容 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.0.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat) |
| | | ## 0.0.5(2021-07-08) |
| | | - 调整 默认时间不再是当前时间,而是显示'-'字符 |
| | | ## 0.0.4(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 0.0.3(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
| | | - 修复 iOS 平台日期格式化出错的问题 |
对比新文件 |
| | |
| | | // yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型 |
| | | function pad(str, length = 2) { |
| | | str += '' |
| | | while (str.length < length) { |
| | | str = '0' + str |
| | | } |
| | | return str.slice(-length) |
| | | } |
| | | |
| | | const parser = { |
| | | yyyy: (dateObj) => { |
| | | return pad(dateObj.year, 4) |
| | | }, |
| | | yy: (dateObj) => { |
| | | return pad(dateObj.year) |
| | | }, |
| | | MM: (dateObj) => { |
| | | return pad(dateObj.month) |
| | | }, |
| | | M: (dateObj) => { |
| | | return dateObj.month |
| | | }, |
| | | dd: (dateObj) => { |
| | | return pad(dateObj.day) |
| | | }, |
| | | d: (dateObj) => { |
| | | return dateObj.day |
| | | }, |
| | | hh: (dateObj) => { |
| | | return pad(dateObj.hour) |
| | | }, |
| | | h: (dateObj) => { |
| | | return dateObj.hour |
| | | }, |
| | | mm: (dateObj) => { |
| | | return pad(dateObj.minute) |
| | | }, |
| | | m: (dateObj) => { |
| | | return dateObj.minute |
| | | }, |
| | | ss: (dateObj) => { |
| | | return pad(dateObj.second) |
| | | }, |
| | | s: (dateObj) => { |
| | | return dateObj.second |
| | | }, |
| | | SSS: (dateObj) => { |
| | | return pad(dateObj.millisecond, 3) |
| | | }, |
| | | S: (dateObj) => { |
| | | return dateObj.millisecond |
| | | }, |
| | | } |
| | | |
| | | // 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12 |
| | | function getDate(time) { |
| | | if (time instanceof Date) { |
| | | return time |
| | | } |
| | | switch (typeof time) { |
| | | case 'string': |
| | | { |
| | | // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000 |
| | | if (time.indexOf('T') > -1) { |
| | | return new Date(time) |
| | | } |
| | | return new Date(time.replace(/-/g, '/')) |
| | | } |
| | | default: |
| | | return new Date(time) |
| | | } |
| | | } |
| | | |
| | | export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') { |
| | | if (!date && date !== 0) { |
| | | return '' |
| | | } |
| | | date = getDate(date) |
| | | const dateObj = { |
| | | year: date.getFullYear(), |
| | | month: date.getMonth() + 1, |
| | | day: date.getDate(), |
| | | hour: date.getHours(), |
| | | minute: date.getMinutes(), |
| | | second: date.getSeconds(), |
| | | millisecond: date.getMilliseconds() |
| | | } |
| | | const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/ |
| | | let flag = true |
| | | let result = format |
| | | while (flag) { |
| | | flag = false |
| | | result = result.replace(tokenRegExp, function(matched) { |
| | | flag = true |
| | | return parser[matched](dateObj) |
| | | }) |
| | | } |
| | | return result |
| | | } |
| | | |
| | | export function friendlyDate(time, { |
| | | locale = 'zh', |
| | | threshold = [60000, 3600000], |
| | | format = 'yyyy/MM/dd hh:mm:ss' |
| | | }) { |
| | | if (time === '-') { |
| | | return time |
| | | } |
| | | if (!time && time !== 0) { |
| | | return '' |
| | | } |
| | | const localeText = { |
| | | zh: { |
| | | year: '年', |
| | | month: '月', |
| | | day: '天', |
| | | hour: '小时', |
| | | minute: '分钟', |
| | | second: '秒', |
| | | ago: '前', |
| | | later: '后', |
| | | justNow: '刚刚', |
| | | soon: '马上', |
| | | template: '{num}{unit}{suffix}' |
| | | }, |
| | | en: { |
| | | year: 'year', |
| | | month: 'month', |
| | | day: 'day', |
| | | hour: 'hour', |
| | | minute: 'minute', |
| | | second: 'second', |
| | | ago: 'ago', |
| | | later: 'later', |
| | | justNow: 'just now', |
| | | soon: 'soon', |
| | | template: '{num} {unit} {suffix}' |
| | | } |
| | | } |
| | | const text = localeText[locale] || localeText.zh |
| | | let date = getDate(time) |
| | | let ms = date.getTime() - Date.now() |
| | | let absMs = Math.abs(ms) |
| | | if (absMs < threshold[0]) { |
| | | return ms < 0 ? text.justNow : text.soon |
| | | } |
| | | if (absMs >= threshold[1]) { |
| | | return formatDate(date, format) |
| | | } |
| | | let num |
| | | let unit |
| | | let suffix = text.later |
| | | if (ms < 0) { |
| | | suffix = text.ago |
| | | ms = -ms |
| | | } |
| | | const seconds = Math.floor((ms) / 1000) |
| | | const minutes = Math.floor(seconds / 60) |
| | | const hours = Math.floor(minutes / 60) |
| | | const days = Math.floor(hours / 24) |
| | | const months = Math.floor(days / 30) |
| | | const years = Math.floor(months / 12) |
| | | switch (true) { |
| | | case years > 0: |
| | | num = years |
| | | unit = text.year |
| | | break |
| | | case months > 0: |
| | | num = months |
| | | unit = text.month |
| | | break |
| | | case days > 0: |
| | | num = days |
| | | unit = text.day |
| | | break |
| | | case hours > 0: |
| | | num = hours |
| | | unit = text.hour |
| | | break |
| | | case minutes > 0: |
| | | num = minutes |
| | | unit = text.minute |
| | | break |
| | | default: |
| | | num = seconds |
| | | unit = text.second |
| | | break |
| | | } |
| | | |
| | | if (locale === 'en') { |
| | | if (num === 1) { |
| | | num = 'a' |
| | | } else { |
| | | unit += 's' |
| | | } |
| | | } |
| | | |
| | | return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g, |
| | | suffix) |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <text>{{dateShow}}</text> |
| | | </template> |
| | | |
| | | <script> |
| | | import {friendlyDate} from './date-format.js' |
| | | /** |
| | | * Dateformat 日期格式化 |
| | | * @description 日期格式化组件 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=3279 |
| | | * @property {Object|String|Number} date 日期对象/日期字符串/时间戳 |
| | | * @property {String} locale 格式化使用的语言 |
| | | * @value zh 中文 |
| | | * @value en 英文 |
| | | * @property {Array} threshold 应用不同类型格式化的阈值 |
| | | * @property {String} format 输出日期字符串时的格式 |
| | | */ |
| | | export default { |
| | | name: 'uniDateformat', |
| | | props: { |
| | | date: { |
| | | type: [Object, String, Number], |
| | | default () { |
| | | return '-' |
| | | } |
| | | }, |
| | | locale: { |
| | | type: String, |
| | | default: 'zh', |
| | | }, |
| | | threshold: { |
| | | type: Array, |
| | | default () { |
| | | return [0, 0] |
| | | } |
| | | }, |
| | | format: { |
| | | type: String, |
| | | default: 'yyyy/MM/dd hh:mm:ss' |
| | | }, |
| | | // refreshRate使用不当可能导致性能问题,谨慎使用 |
| | | refreshRate: { |
| | | type: [Number, String], |
| | | default: 0 |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | refreshMark: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | dateShow() { |
| | | this.refreshMark |
| | | return friendlyDate(this.date, { |
| | | locale: this.locale, |
| | | threshold: this.threshold, |
| | | format: this.format |
| | | }) |
| | | } |
| | | }, |
| | | watch: { |
| | | refreshRate: { |
| | | handler() { |
| | | this.setAutoRefresh() |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | refresh() { |
| | | this.refreshMark++ |
| | | }, |
| | | setAutoRefresh() { |
| | | clearInterval(this.refreshInterval) |
| | | if (this.refreshRate) { |
| | | this.refreshInterval = setInterval(() => { |
| | | this.refresh() |
| | | }, parseInt(this.refreshRate)) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-dateformat", |
| | | "displayName": "uni-dateformat 日期格式化", |
| | | "version": "1.0.0", |
| | | "description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "日期格式化", |
| | | "时间格式化", |
| | | "格式化时间", |
| | | "" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "快应用": { |
| | | "华为": "y", |
| | | "联盟": "y" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ### DateFormat 日期格式化 |
| | | > **组件名:uni-dateformat** |
| | | > 代码块: `uDateformat` |
| | | |
| | | |
| | | 日期格式化组件。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-dateformat) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 2.2.22(2023-03-30) |
| | | - 修复 日历 picker 修改年月后,自动选中当月1日 [详情](https://ask.dcloud.net.cn/question/165937) |
| | | - 修复 小程序端 低版本 ios NaN [详情](https://ask.dcloud.net.cn/question/162979) |
| | | ## 2.2.21(2023-02-20) |
| | | - 修复 firefox 浏览器显示区域点击无法拉起日历弹框的Bug [详情](https://ask.dcloud.net.cn/question/163362) |
| | | ## 2.2.20(2023-02-17) |
| | | - 优化 值为空依然选中当天问题 |
| | | - 优化 提供 default-value 属性支持配置选择器打开时默认显示的时间 |
| | | - 优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间 |
| | | - 优化 字节小程序日期时间范围选择,底部日期换行问题 |
| | | ## 2.2.19(2023-02-09) |
| | | - 修复 2.2.18 引起范围选择配置 end 选择无效的Bug [详情](https://github.com/dcloudio/uni-ui/issues/686) |
| | | ## 2.2.18(2023-02-08) |
| | | - 修复 移动端范围选择change事件触发异常的Bug [详情](https://github.com/dcloudio/uni-ui/issues/684) |
| | | - 优化 PC端输入日期格式错误时返回当前日期时间 |
| | | - 优化 PC端输入日期时间超出 start、end 限制的Bug |
| | | - 优化 移动端日期时间范围用法时间展示不完整问题 |
| | | ## 2.2.17(2023-02-04) |
| | | - 修复 小程序端绑定 Date 类型报错的Bug [详情](https://github.com/dcloudio/uni-ui/issues/679) |
| | | - 修复 vue3 time-picker 无法显示绑定时分秒的Bug |
| | | ## 2.2.16(2023-02-02) |
| | | - 修复 字节小程序报错的Bug |
| | | ## 2.2.15(2023-02-02) |
| | | - 修复 某些情况切换月份错误的Bug |
| | | ## 2.2.14(2023-01-30) |
| | | - 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/162033) |
| | | ## 2.2.13(2023-01-10) |
| | | - 修复 多次加载组件造成内存占用的Bug |
| | | ## 2.2.12(2022-12-01) |
| | | - 修复 vue3 下 i18n 国际化初始值不正确的Bug |
| | | ## 2.2.11(2022-09-19) |
| | | - 修复 支付宝小程序样式错乱的Bug [详情](https://github.com/dcloudio/uni-app/issues/3861) |
| | | ## 2.2.10(2022-09-19) |
| | | - 修复 反向选择日期范围,日期显示异常的Bug [详情](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false) |
| | | ## 2.2.9(2022-09-16) |
| | | - 可以使用 uni-scss 控制主题色 |
| | | ## 2.2.8(2022-09-08) |
| | | - 修复 close事件无效的Bug |
| | | ## 2.2.7(2022-09-05) |
| | | - 修复 移动端 maskClick 无效的Bug [详情](https://ask.dcloud.net.cn/question/140824) |
| | | ## 2.2.6(2022-06-30) |
| | | - 优化 组件样式,调整了组件图标大小、高度、颜色等,与uni-ui风格保持一致 |
| | | ## 2.2.5(2022-06-24) |
| | | - 修复 日历顶部年月及底部确认未国际化的Bug |
| | | ## 2.2.4(2022-03-31) |
| | | - 修复 Vue3 下动态赋值,单选类型未响应的Bug |
| | | ## 2.2.3(2022-03-28) |
| | | - 修复 Vue3 下动态赋值未响应的Bug |
| | | ## 2.2.2(2021-12-10) |
| | | - 修复 clear-icon 属性在小程序平台不生效的Bug |
| | | ## 2.2.1(2021-12-10) |
| | | - 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的Bug |
| | | ## 2.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源 [详情](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移 [https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) |
| | | ## 2.1.5(2021-11-09) |
| | | - 新增 提供组件设计资源,组件样式调整 |
| | | ## 2.1.4(2021-09-10) |
| | | - 修复 hide-second 在移动端的Bug |
| | | - 修复 单选赋默认值时,赋值日期未高亮的Bug |
| | | - 修复 赋默认值时,移动端未正确显示时间的Bug |
| | | ## 2.1.3(2021-09-09) |
| | | - 新增 hide-second 属性,支持只使用时分,隐藏秒 |
| | | ## 2.1.2(2021-09-03) |
| | | - 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次 |
| | | - 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法 |
| | | - 优化 调整字号大小,美化日历界面 |
| | | - 修复 因国际化导致的 placeholder 失效的Bug |
| | | ## 2.1.1(2021-08-24) |
| | | - 新增 支持国际化 |
| | | - 优化 范围选择器在 pc 端过宽的问题 |
| | | ## 2.1.0(2021-08-09) |
| | | - 新增 适配 vue3 |
| | | ## 2.0.19(2021-08-09) |
| | | - 新增 支持作为 uni-forms 子组件相关功能 |
| | | - 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的Bug |
| | | ## 2.0.18(2021-08-05) |
| | | - 修复 type 属性动态赋值无效的Bug |
| | | - 修复 ‘确认’按钮被 tabbar 遮盖 bug |
| | | - 修复 组件未赋值时范围选左、右日历相同的Bug |
| | | ## 2.0.17(2021-08-04) |
| | | - 修复 范围选未正确显示当前值的Bug |
| | | - 修复 h5 平台(移动端)报错 'cale' of undefined 的Bug |
| | | ## 2.0.16(2021-07-21) |
| | | - 新增 return-type 属性支持返回 date 日期对象 |
| | | ## 2.0.15(2021-07-14) |
| | | - 修复 单选日期类型,初始赋值后不在当前日历的Bug |
| | | - 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效) |
| | | - 优化 移动端移除显示框的清空按钮,无实际用途 |
| | | ## 2.0.14(2021-07-14) |
| | | - 修复 组件赋值为空,界面未更新的Bug |
| | | - 修复 start 和 end 不能动态赋值的Bug |
| | | - 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的Bug |
| | | ## 2.0.13(2021-07-08) |
| | | - 修复 范围选择不能动态赋值的Bug |
| | | ## 2.0.12(2021-07-08) |
| | | - 修复 范围选择的初始时间在一个月内时,造成无法选择的bug |
| | | ## 2.0.11(2021-07-08) |
| | | - 优化 弹出层在超出视窗边缘定位不准确的问题 |
| | | ## 2.0.10(2021-07-08) |
| | | - 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的Bug |
| | | - 优化 弹出层在超出视窗边缘被遮盖的问题 |
| | | ## 2.0.9(2021-07-07) |
| | | - 新增 maskClick 事件 |
| | | - 修复 特殊情况日历 rpx 布局错误的Bug,rpx -> px |
| | | - 修复 范围选择时清空返回值不合理的bug,['', ''] -> [] |
| | | ## 2.0.8(2021-07-07) |
| | | - 新增 日期时间显示框支持插槽 |
| | | ## 2.0.7(2021-07-01) |
| | | - 优化 添加 uni-icons 依赖 |
| | | ## 2.0.6(2021-05-22) |
| | | - 修复 图标在小程序上不显示的Bug |
| | | - 优化 重命名引用组件,避免潜在组件命名冲突 |
| | | ## 2.0.5(2021-05-20) |
| | | - 优化 代码目录扁平化 |
| | | ## 2.0.4(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 2.0.3(2021-05-10) |
| | | - 修复 ios 下不识别 '-' 日期格式的Bug |
| | | - 优化 pc 下弹出层添加边框和阴影 |
| | | ## 2.0.2(2021-05-08) |
| | | - 修复 在 admin 中获取弹出层定位错误的bug |
| | | ## 2.0.1(2021-05-08) |
| | | - 修复 type 属性向下兼容,默认值从 date 变更为 datetime |
| | | ## 2.0.0(2021-04-30) |
| | | - 支持日历形式的日期+时间的范围选择 |
| | | > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker) |
| | | ## 1.0.6(2021-03-18) |
| | | - 新增 hide-second 属性,时间支持仅选择时、分 |
| | | - 修复 选择跟显示的日期不一样的Bug |
| | | - 修复 chang事件触发2次的Bug |
| | | - 修复 分、秒 end 范围错误的Bug |
| | | - 优化 更好的 nvue 适配 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-calendar-item__weeks-box" :class="{ |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | 'uni-calendar-item--before-checked-x':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked-x':weeks.afterMultiple, |
| | | }" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)"> |
| | | <view class="uni-calendar-item__weeks-box-item" :class="{ |
| | | 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover), |
| | | 'uni-calendar-item--checked-range-text': checkHover, |
| | | 'uni-calendar-item--before-checked':weeks.beforeMultiple, |
| | | 'uni-calendar-item--multiple': weeks.multiple, |
| | | 'uni-calendar-item--after-checked':weeks.afterMultiple, |
| | | 'uni-calendar-item--disable':weeks.disable, |
| | | }"> |
| | | <text v-if="selected && weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text> |
| | | <text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text> |
| | | </view> |
| | | <view :class="{'uni-calendar-item--today': weeks.isToday}"></view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | weeks: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | calendar: { |
| | | type: Object, |
| | | default: () => { |
| | | return {} |
| | | } |
| | | }, |
| | | selected: { |
| | | type: Array, |
| | | default: () => { |
| | | return [] |
| | | } |
| | | }, |
| | | checkHover: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | methods: { |
| | | choiceDate(weeks) { |
| | | this.$emit('change', weeks) |
| | | }, |
| | | handleMousemove(weeks) { |
| | | this.$emit('handleMouse', weeks) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $uni-primary: #007aff !default; |
| | | |
| | | .uni-calendar-item__weeks-box { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin: 1px 0; |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box-text { |
| | | font-size: 14px; |
| | | // font-family: Lato-Bold, Lato; |
| | | font-weight: bold; |
| | | color: darken($color: $uni-primary, $amount: 40%); |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box-item { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 40px; |
| | | height: 40px; |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | |
| | | .uni-calendar-item__weeks-box-circle { |
| | | position: absolute; |
| | | top: 5px; |
| | | right: 5px; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 8px; |
| | | background-color: #dd524d; |
| | | |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box .uni-calendar-item--disable { |
| | | cursor: default; |
| | | } |
| | | |
| | | .uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable { |
| | | color: #D1D1D1; |
| | | } |
| | | |
| | | .uni-calendar-item--today { |
| | | position: absolute; |
| | | top: 10px; |
| | | right: 17%; |
| | | background-color: #dd524d; |
| | | width:6px; |
| | | height: 6px; |
| | | border-radius: 50%; |
| | | } |
| | | |
| | | .uni-calendar-item--extra { |
| | | color: #dd524d; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .uni-calendar-item__weeks-box .uni-calendar-item--checked { |
| | | background-color: $uni-primary; |
| | | border-radius: 50%; |
| | | box-sizing: border-box; |
| | | border: 3px solid #fff; |
| | | } |
| | | |
| | | .uni-calendar-item--checked .uni-calendar-item--checked-text { |
| | | color: #fff; |
| | | } |
| | | |
| | | .uni-calendar-item--multiple .uni-calendar-item--checked-range-text { |
| | | color: #333; |
| | | } |
| | | |
| | | .uni-calendar-item--multiple { |
| | | background-color: #F6F7FC; |
| | | // color: #fff; |
| | | } |
| | | |
| | | .uni-calendar-item--multiple .uni-calendar-item--before-checked, |
| | | .uni-calendar-item--multiple .uni-calendar-item--after-checked { |
| | | background-color: $uni-primary; |
| | | border-radius: 50%; |
| | | box-sizing: border-box; |
| | | border: 3px solid #F6F7FC; |
| | | } |
| | | |
| | | .uni-calendar-item--before-checked .uni-calendar-item--checked-text, |
| | | .uni-calendar-item--after-checked .uni-calendar-item--checked-text { |
| | | color: #fff; |
| | | } |
| | | |
| | | .uni-calendar-item--before-checked-x { |
| | | border-top-left-radius: 50px; |
| | | border-bottom-left-radius: 50px; |
| | | box-sizing: border-box; |
| | | background-color: #F6F7FC; |
| | | } |
| | | |
| | | .uni-calendar-item--after-checked-x { |
| | | border-top-right-radius: 50px; |
| | | border-bottom-right-radius: 50px; |
| | | background-color: #F6F7FC; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-calendar" @mouseleave="leaveCale"> |
| | | |
| | | <view v-if="!insert && show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" |
| | | @click="maskClick"></view> |
| | | |
| | | <view v-if="insert || show" class="uni-calendar__content" |
| | | :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}"> |
| | | <view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}"> |
| | | |
| | | <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('pre')"> |
| | | <view class="uni-calendar__header-btn uni-calendar--left"></view> |
| | | </view> |
| | | |
| | | <picker mode="date" :value="date" fields="month" @change="bindDateChange"> |
| | | <text |
| | | class="uni-calendar__header-text">{{ (nowDate.year||'') + yearText + ( nowDate.month||'') + monthText}}</text> |
| | | </picker> |
| | | |
| | | <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('next')"> |
| | | <view class="uni-calendar__header-btn uni-calendar--right"></view> |
| | | </view> |
| | | |
| | | <view v-if="!insert" class="dialog-close" @click="close"> |
| | | <view class="dialog-close-plus" data-id="close"></view> |
| | | <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view> |
| | | </view> |
| | | </view> |
| | | <view class="uni-calendar__box"> |
| | | |
| | | <view v-if="showMonth" class="uni-calendar__box-bg"> |
| | | <text class="uni-calendar__box-bg-text">{{nowDate.month}}</text> |
| | | </view> |
| | | |
| | | <view class="uni-calendar__weeks" style="padding-bottom: 7px;"> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{SUNText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{MONText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{TUEText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{WEDText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{THUText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{FRIText}}</text> |
| | | </view> |
| | | <view class="uni-calendar__weeks-day"> |
| | | <text class="uni-calendar__weeks-day-text">{{SATText}}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex"> |
| | | <view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex"> |
| | | <calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" |
| | | :selected="selected" :checkHover="range" @change="choiceDate" |
| | | @handleMouse="handleMouse"> |
| | | </calendar-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="!insert && !range && hasTime" class="uni-date-changed uni-calendar--fixed-top" |
| | | style="padding: 0 80px;"> |
| | | <view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view> |
| | | <time-picker type="time" :start="timepickerStartTime" :end="timepickerEndTime" v-model="time" |
| | | :disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style"> |
| | | </time-picker> |
| | | </view> |
| | | |
| | | <view v-if="!insert && range && hasTime" class="uni-date-changed uni-calendar--fixed-top"> |
| | | <view class="uni-date-changed--time-start"> |
| | | <view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}} |
| | | </view> |
| | | <time-picker type="time" :start="timepickerStartTime" v-model="timeRange.startTime" :border="false" |
| | | :hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style"> |
| | | </time-picker> |
| | | </view> |
| | | <view style="line-height: 50px;"> |
| | | <uni-icons type="arrowthinright" color="#999"></uni-icons> |
| | | </view> |
| | | <view class="uni-date-changed--time-end"> |
| | | <view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view> |
| | | <time-picker type="time" :end="timepickerEndTime" v-model="timeRange.endTime" :border="false" |
| | | :hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style"> |
| | | </time-picker> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="!insert" class="uni-date-changed uni-date-btn--ok"> |
| | | <view class="uni-datetime-picker--btn" @click="confirm">{{confirmText}}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { Calendar, getDate, getTime } from './util.js'; |
| | | import calendarItem from './calendar-item.vue' |
| | | import timePicker from './time-picker.vue' |
| | | |
| | | import { initVueI18n } from '@dcloudio/uni-i18n' |
| | | import i18nMessages from './i18n/index.js' |
| | | const { t } = initVueI18n(i18nMessages) |
| | | |
| | | /** |
| | | * Calendar 日历 |
| | | * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=56 |
| | | * @property {String} date 自定义当前时间,默认为今天 |
| | | * @property {String} startDate 日期选择范围-开始日期 |
| | | * @property {String} endDate 日期选择范围-结束日期 |
| | | * @property {Boolean} range 范围选择 |
| | | * @property {Boolean} insert = [true|false] 插入模式,默认为false |
| | | * @value true 弹窗模式 |
| | | * @value false 插入模式 |
| | | * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容 |
| | | * @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
| | | * @property {Boolean} showMonth 是否选择月份为背景 |
| | | * @property {[String} defaultValue 选择器打开时默认显示的时间 |
| | | * @event {Function} change 日期改变,`insert :ture` 时生效 |
| | | * @event {Function} confirm 确认选择`insert :false` 时生效 |
| | | * @event {Function} monthSwitch 切换月份时触发 |
| | | * @example <uni-calendar :insert="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" /> |
| | | */ |
| | | export default { |
| | | components: { |
| | | calendarItem, |
| | | timePicker |
| | | }, |
| | | props: { |
| | | date: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | defTime: { |
| | | type: [String, Object], |
| | | default: '' |
| | | }, |
| | | selectableTimes: { |
| | | type: [Object], |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | selected: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | startDate: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | endDate: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | startPlaceholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | endPlaceholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | range: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | hasTime: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | insert: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | showMonth: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | clearDate: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | checkHover: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | hideSecond: { |
| | | type: [Boolean], |
| | | default: false |
| | | }, |
| | | pleStatus: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | before: '', |
| | | after: '', |
| | | data: [], |
| | | fulldate: '' |
| | | } |
| | | } |
| | | }, |
| | | defaultValue: { |
| | | type: [String, Object, Array], |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | show: false, |
| | | weeks: [], |
| | | calendar: {}, |
| | | nowDate: {}, |
| | | aniMaskShow: false, |
| | | firstEnter: true, |
| | | time: '', |
| | | timeRange: { |
| | | startTime: '', |
| | | endTime: '' |
| | | }, |
| | | tempSingleDate: '', |
| | | tempRange: { |
| | | before: '', |
| | | after: '' |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | date: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (!this.range) { |
| | | this.tempSingleDate = newVal |
| | | setTimeout(() => { |
| | | this.init(newVal) |
| | | }, 100) |
| | | } |
| | | } |
| | | }, |
| | | defTime: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (!this.range) { |
| | | this.time = newVal |
| | | } else { |
| | | this.timeRange.startTime = newVal.start |
| | | this.timeRange.endTime = newVal.end |
| | | } |
| | | } |
| | | }, |
| | | startDate(val) { |
| | | // 字节小程序 watch 早于 created |
| | | if(!this.cale){ |
| | | return |
| | | } |
| | | this.cale.setStartDate(val) |
| | | this.cale.setDate(this.nowDate.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | }, |
| | | endDate(val) { |
| | | // 字节小程序 watch 早于 created |
| | | if(!this.cale){ |
| | | return |
| | | } |
| | | this.cale.setEndDate(val) |
| | | this.cale.setDate(this.nowDate.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | }, |
| | | selected(newVal) { |
| | | // 字节小程序 watch 早于 created |
| | | if(!this.cale){ |
| | | return |
| | | } |
| | | this.cale.setSelectInfo(this.nowDate.fullDate, newVal) |
| | | this.weeks = this.cale.weeks |
| | | }, |
| | | pleStatus: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | const { |
| | | before, |
| | | after, |
| | | fulldate, |
| | | which |
| | | } = newVal |
| | | this.tempRange.before = before |
| | | this.tempRange.after = after |
| | | setTimeout(() => { |
| | | if (fulldate) { |
| | | this.cale.setHoverMultiple(fulldate) |
| | | if (before && after) { |
| | | this.cale.lastHover = true |
| | | if (this.rangeWithinMonth(after, before)) return |
| | | this.setDate(before) |
| | | } else { |
| | | this.cale.setMultiple(fulldate) |
| | | this.setDate(this.nowDate.fullDate) |
| | | this.calendar.fullDate = '' |
| | | this.cale.lastHover = false |
| | | } |
| | | } else { |
| | | // 字节小程序 watch 早于 created |
| | | if(!this.cale){ |
| | | return |
| | | } |
| | | |
| | | this.cale.setDefaultMultiple(before, after) |
| | | if (which === 'left' && before) { |
| | | this.setDate(before) |
| | | this.weeks = this.cale.weeks |
| | | } else if(after) { |
| | | this.setDate(after) |
| | | this.weeks = this.cale.weeks |
| | | } |
| | | this.cale.lastHover = true |
| | | } |
| | | }, 16) |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | timepickerStartTime() { |
| | | const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate |
| | | return activeDate === this.startDate ? this.selectableTimes.start : '' |
| | | }, |
| | | timepickerEndTime() { |
| | | const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate |
| | | return activeDate === this.endDate ? this.selectableTimes.end : '' |
| | | }, |
| | | /** |
| | | * for i18n |
| | | */ |
| | | selectDateText() { |
| | | return t("uni-datetime-picker.selectDate") |
| | | }, |
| | | startDateText() { |
| | | return this.startPlaceholder || t("uni-datetime-picker.startDate") |
| | | }, |
| | | endDateText() { |
| | | return this.endPlaceholder || t("uni-datetime-picker.endDate") |
| | | }, |
| | | okText() { |
| | | return t("uni-datetime-picker.ok") |
| | | }, |
| | | yearText() { |
| | | return t("uni-datetime-picker.year") |
| | | }, |
| | | monthText() { |
| | | return t("uni-datetime-picker.month") |
| | | }, |
| | | MONText() { |
| | | return t("uni-calender.MON") |
| | | }, |
| | | TUEText() { |
| | | return t("uni-calender.TUE") |
| | | }, |
| | | WEDText() { |
| | | return t("uni-calender.WED") |
| | | }, |
| | | THUText() { |
| | | return t("uni-calender.THU") |
| | | }, |
| | | FRIText() { |
| | | return t("uni-calender.FRI") |
| | | }, |
| | | SATText() { |
| | | return t("uni-calender.SAT") |
| | | }, |
| | | SUNText() { |
| | | return t("uni-calender.SUN") |
| | | }, |
| | | confirmText() { |
| | | return t("uni-calender.confirm") |
| | | }, |
| | | }, |
| | | created() { |
| | | // 获取日历方法实例 |
| | | this.cale = new Calendar({ |
| | | selected: this.selected, |
| | | startDate: this.startDate, |
| | | endDate: this.endDate, |
| | | range: this.range, |
| | | }) |
| | | // 选中某一天 |
| | | this.init(this.date) |
| | | }, |
| | | methods: { |
| | | leaveCale() { |
| | | this.firstEnter = true |
| | | }, |
| | | handleMouse(weeks) { |
| | | if (weeks.disable) return |
| | | if (this.cale.lastHover) return |
| | | let { |
| | | before, |
| | | after |
| | | } = this.cale.multipleStatus |
| | | if (!before) return |
| | | this.calendar = weeks |
| | | // 设置范围选 |
| | | this.cale.setHoverMultiple(this.calendar.fullDate) |
| | | this.weeks = this.cale.weeks |
| | | // hover时,进入一个日历,更新另一个 |
| | | if (this.firstEnter) { |
| | | this.$emit('firstEnterCale', this.cale.multipleStatus) |
| | | this.firstEnter = false |
| | | } |
| | | }, |
| | | rangeWithinMonth(A, B) { |
| | | const [yearA, monthA] = A.split('-') |
| | | const [yearB, monthB] = B.split('-') |
| | | return yearA === yearB && monthA === monthB |
| | | }, |
| | | // 蒙版点击事件 |
| | | maskClick() { |
| | | this.close() |
| | | this.$emit('maskClose') |
| | | }, |
| | | |
| | | clearCalender() { |
| | | if (this.range) { |
| | | this.timeRange.startTime = '' |
| | | this.timeRange.endTime = '' |
| | | this.tempRange.before = '' |
| | | this.tempRange.after = '' |
| | | this.cale.multipleStatus.before = '' |
| | | this.cale.multipleStatus.after = '' |
| | | this.cale.multipleStatus.data = [] |
| | | this.cale.lastHover = false |
| | | } else { |
| | | this.time = '' |
| | | this.tempSingleDate = '' |
| | | } |
| | | this.calendar.fullDate = '' |
| | | this.setDate(new Date()) |
| | | }, |
| | | |
| | | bindDateChange(e) { |
| | | const value = e.detail.value + '-1' |
| | | this.setDate(value) |
| | | }, |
| | | /** |
| | | * 初始化日期显示 |
| | | * @param {Object} date |
| | | */ |
| | | init(date) { |
| | | // 字节小程序 watch 早于 created |
| | | if(!this.cale){ |
| | | return |
| | | } |
| | | this.cale.setDate(date || new Date()) |
| | | this.weeks = this.cale.weeks |
| | | this.nowDate = this.cale.getInfo(date) |
| | | this.calendar = {...this.nowDate} |
| | | if(!date){ |
| | | // 优化date为空默认不选中今天 |
| | | this.calendar.fullDate = '' |
| | | if(this.defaultValue && !this.range){ |
| | | // 暂时只支持移动端非范围选择 |
| | | const defaultDate = new Date(this.defaultValue) |
| | | const fullDate = getDate(defaultDate) |
| | | const year = defaultDate.getFullYear() |
| | | const month = defaultDate.getMonth()+1 |
| | | const date = defaultDate.getDate() |
| | | const day = defaultDate.getDay() |
| | | this.calendar = { |
| | | fullDate, |
| | | year, |
| | | month, |
| | | date, |
| | | day |
| | | }, |
| | | this.tempSingleDate = fullDate |
| | | this.time = getTime(defaultDate, this.hideSecond) |
| | | } |
| | | } |
| | | }, |
| | | /** |
| | | * 打开日历弹窗 |
| | | */ |
| | | open() { |
| | | // 弹窗模式并且清理数据 |
| | | if (this.clearDate && !this.insert) { |
| | | this.cale.cleanMultipleStatus() |
| | | this.init(this.date) |
| | | } |
| | | this.show = true |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.aniMaskShow = true |
| | | }, 50) |
| | | }) |
| | | }, |
| | | /** |
| | | * 关闭日历弹窗 |
| | | */ |
| | | close() { |
| | | this.aniMaskShow = false |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.show = false |
| | | this.$emit('close') |
| | | }, 300) |
| | | }) |
| | | }, |
| | | /** |
| | | * 确认按钮 |
| | | */ |
| | | confirm() { |
| | | this.setEmit('confirm') |
| | | this.close() |
| | | }, |
| | | /** |
| | | * 变化触发 |
| | | */ |
| | | change() { |
| | | if (!this.insert) return |
| | | this.setEmit('change') |
| | | }, |
| | | /** |
| | | * 选择月份触发 |
| | | */ |
| | | monthSwitch() { |
| | | let { |
| | | year, |
| | | month |
| | | } = this.nowDate |
| | | this.$emit('monthSwitch', { |
| | | year, |
| | | month: Number(month) |
| | | }) |
| | | }, |
| | | /** |
| | | * 派发事件 |
| | | * @param {Object} name |
| | | */ |
| | | setEmit(name) { |
| | | if(!this.range){ |
| | | if(!this.calendar.fullDate){ |
| | | this.calendar = this.cale.getInfo(new Date()) |
| | | this.tempSingleDate = this.calendar.fullDate |
| | | } |
| | | if(this.hasTime && !this.time) { |
| | | this.time = getTime(new Date(), this.hideSecond) |
| | | } |
| | | } |
| | | let { |
| | | year, |
| | | month, |
| | | date, |
| | | fullDate, |
| | | extraInfo |
| | | } = this.calendar |
| | | this.$emit(name, { |
| | | range: this.cale.multipleStatus, |
| | | year, |
| | | month, |
| | | date, |
| | | time: this.time, |
| | | timeRange: this.timeRange, |
| | | fulldate: fullDate, |
| | | extraInfo: extraInfo || {} |
| | | }) |
| | | }, |
| | | /** |
| | | * 选择天触发 |
| | | * @param {Object} weeks |
| | | */ |
| | | choiceDate(weeks) { |
| | | if (weeks.disable) return |
| | | this.calendar = weeks |
| | | this.calendar.userChecked = true |
| | | // 设置多选 |
| | | this.cale.setMultiple(this.calendar.fullDate, true) |
| | | this.weeks = this.cale.weeks |
| | | this.tempSingleDate = this.calendar.fullDate |
| | | const beforeDate = new Date(this.cale.multipleStatus.before).getTime() |
| | | const afterDate = new Date(this.cale.multipleStatus.after).getTime() |
| | | if (beforeDate > afterDate && afterDate) { |
| | | this.tempRange.before = this.cale.multipleStatus.after |
| | | this.tempRange.after = this.cale.multipleStatus.before |
| | | } else { |
| | | this.tempRange.before = this.cale.multipleStatus.before |
| | | this.tempRange.after = this.cale.multipleStatus.after |
| | | } |
| | | this.change() |
| | | }, |
| | | changeMonth(type) { |
| | | let newDate |
| | | if(type === 'pre') { |
| | | newDate = this.cale.getPreMonthObj(this.nowDate.fullDate).fullDate |
| | | } else if(type === 'next') { |
| | | newDate = this.cale.getNextMonthObj(this.nowDate.fullDate).fullDate |
| | | } |
| | | |
| | | this.setDate(newDate) |
| | | this.monthSwitch() |
| | | }, |
| | | /** |
| | | * 设置日期 |
| | | * @param {Object} date |
| | | */ |
| | | setDate(date) { |
| | | this.cale.setDate(date) |
| | | this.weeks = this.cale.weeks |
| | | this.nowDate = this.cale.getInfo(date) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $uni-primary: #007aff !default; |
| | | |
| | | .uni-calendar { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .uni-calendar__mask { |
| | | position: fixed; |
| | | bottom: 0; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: rgba(0, 0, 0, 0.4); |
| | | transition-property: opacity; |
| | | transition-duration: 0.3s; |
| | | opacity: 0; |
| | | /* #ifndef APP-NVUE */ |
| | | z-index: 99; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-calendar--mask-show { |
| | | opacity: 1 |
| | | } |
| | | |
| | | .uni-calendar--fixed { |
| | | position: fixed; |
| | | bottom: calc(var(--window-bottom)); |
| | | left: 0; |
| | | right: 0; |
| | | transition-property: transform; |
| | | transition-duration: 0.3s; |
| | | transform: translateY(460px); |
| | | /* #ifndef APP-NVUE */ |
| | | z-index: 99; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-calendar--ani-show { |
| | | transform: translateY(0); |
| | | } |
| | | |
| | | .uni-calendar__content { |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .uni-calendar__content-mobile { |
| | | border-top-left-radius: 10px; |
| | | border-top-right-radius: 10px; |
| | | box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .uni-calendar__header { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 50px; |
| | | } |
| | | |
| | | .uni-calendar__header-mobile { |
| | | padding: 10px; |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | .uni-calendar--fixed-top { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | border-top-color: rgba(0, 0, 0, 0.4); |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar--fixed-width { |
| | | width: 50px; |
| | | } |
| | | |
| | | .uni-calendar__backtoday { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 25rpx; |
| | | padding: 0 5px; |
| | | padding-left: 10px; |
| | | height: 25px; |
| | | line-height: 25px; |
| | | font-size: 12px; |
| | | border-top-left-radius: 25px; |
| | | border-bottom-left-radius: 25px; |
| | | color: #fff; |
| | | background-color: #f1f1f1; |
| | | } |
| | | |
| | | .uni-calendar__header-text { |
| | | text-align: center; |
| | | width: 100px; |
| | | font-size: 15px; |
| | | color: #666; |
| | | } |
| | | |
| | | .uni-calendar__button-text { |
| | | text-align: center; |
| | | width: 100px; |
| | | font-size: 14px; |
| | | color: $uni-primary; |
| | | /* #ifndef APP-NVUE */ |
| | | letter-spacing: 3px; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-calendar__header-btn-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 50px; |
| | | height: 50px; |
| | | } |
| | | |
| | | .uni-calendar__header-btn { |
| | | width: 9px; |
| | | height: 9px; |
| | | border-left-color: #808080; |
| | | border-left-style: solid; |
| | | border-left-width: 1px; |
| | | border-top-color: #555555; |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar--left { |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .uni-calendar--right { |
| | | transform: rotate(135deg); |
| | | } |
| | | |
| | | |
| | | .uni-calendar__weeks { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .uni-calendar__weeks-item { |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-calendar__weeks-day { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 40px; |
| | | border-bottom-color: #F5F5F5; |
| | | border-bottom-style: solid; |
| | | border-bottom-width: 1px; |
| | | } |
| | | |
| | | .uni-calendar__weeks-day-text { |
| | | font-size: 12px; |
| | | color: #B2B2B2; |
| | | } |
| | | |
| | | .uni-calendar__box { |
| | | position: relative; |
| | | // padding: 0 10px; |
| | | padding-bottom: 7px; |
| | | } |
| | | |
| | | .uni-calendar__box-bg { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | } |
| | | |
| | | .uni-calendar__box-bg-text { |
| | | font-size: 200px; |
| | | font-weight: bold; |
| | | color: #999; |
| | | opacity: 0.1; |
| | | text-align: center; |
| | | /* #ifndef APP-NVUE */ |
| | | line-height: 1; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-date-changed { |
| | | padding: 0 10px; |
| | | // line-height: 50px; |
| | | text-align: center; |
| | | color: #333; |
| | | border-top-color: #DCDCDC; |
| | | ; |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-date-btn--ok { |
| | | padding: 20px 15px; |
| | | } |
| | | |
| | | .uni-date-changed--time-start { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-date-changed--time-end { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-date-changed--time-date { |
| | | color: #999; |
| | | line-height: 50px; |
| | | /* #ifdef MP-TOUTIAO */ |
| | | font-size: 16px; |
| | | /* #endif */ |
| | | margin-right: 5px; |
| | | // opacity: 0.6; |
| | | } |
| | | |
| | | .time-picker-style { |
| | | // width: 62px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center |
| | | } |
| | | |
| | | .mr-10 { |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .dialog-close { |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | padding: 0 25px; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .dialog-close-plus { |
| | | width: 16px; |
| | | height: 2px; |
| | | background-color: #737987; |
| | | border-radius: 2px; |
| | | transform: rotate(45deg); |
| | | } |
| | | |
| | | .dialog-close-rotate { |
| | | position: absolute; |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .uni-datetime-picker--btn { |
| | | border-radius: 100px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | background-color: $uni-primary; |
| | | color: #fff; |
| | | font-size: 16px; |
| | | letter-spacing: 2px; |
| | | } |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | .uni-datetime-picker--btn:active { |
| | | opacity: 0.7; |
| | | } |
| | | /* #endif */ |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "uni-datetime-picker.selectDate": "select date", |
| | | "uni-datetime-picker.selectTime": "select time", |
| | | "uni-datetime-picker.selectDateTime": "select date and time", |
| | | "uni-datetime-picker.startDate": "start date", |
| | | "uni-datetime-picker.endDate": "end date", |
| | | "uni-datetime-picker.startTime": "start time", |
| | | "uni-datetime-picker.endTime": "end time", |
| | | "uni-datetime-picker.ok": "ok", |
| | | "uni-datetime-picker.clear": "clear", |
| | | "uni-datetime-picker.cancel": "cancel", |
| | | "uni-datetime-picker.year": "-", |
| | | "uni-datetime-picker.month": "", |
| | | "uni-calender.MON": "MON", |
| | | "uni-calender.TUE": "TUE", |
| | | "uni-calender.WED": "WED", |
| | | "uni-calender.THU": "THU", |
| | | "uni-calender.FRI": "FRI", |
| | | "uni-calender.SAT": "SAT", |
| | | "uni-calender.SUN": "SUN", |
| | | "uni-calender.confirm": "confirm" |
| | | } |
对比新文件 |
| | |
| | | import en from './en.json' |
| | | import zhHans from './zh-Hans.json' |
| | | import zhHant from './zh-Hant.json' |
| | | export default { |
| | | en, |
| | | 'zh-Hans': zhHans, |
| | | 'zh-Hant': zhHant |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-datetime-picker.selectDate": "选择日期", |
| | | "uni-datetime-picker.selectTime": "选择时间", |
| | | "uni-datetime-picker.selectDateTime": "选择日期时间", |
| | | "uni-datetime-picker.startDate": "开始日期", |
| | | "uni-datetime-picker.endDate": "结束日期", |
| | | "uni-datetime-picker.startTime": "开始时间", |
| | | "uni-datetime-picker.endTime": "结束时间", |
| | | "uni-datetime-picker.ok": "确定", |
| | | "uni-datetime-picker.clear": "清除", |
| | | "uni-datetime-picker.cancel": "取消", |
| | | "uni-datetime-picker.year": "年", |
| | | "uni-datetime-picker.month": "月", |
| | | "uni-calender.SUN": "日", |
| | | "uni-calender.MON": "一", |
| | | "uni-calender.TUE": "二", |
| | | "uni-calender.WED": "三", |
| | | "uni-calender.THU": "四", |
| | | "uni-calender.FRI": "五", |
| | | "uni-calender.SAT": "六", |
| | | "uni-calender.confirm": "确认" |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-datetime-picker.selectDate": "選擇日期", |
| | | "uni-datetime-picker.selectTime": "選擇時間", |
| | | "uni-datetime-picker.selectDateTime": "選擇日期時間", |
| | | "uni-datetime-picker.startDate": "開始日期", |
| | | "uni-datetime-picker.endDate": "結束日期", |
| | | "uni-datetime-picker.startTime": "開始时间", |
| | | "uni-datetime-picker.endTime": "結束时间", |
| | | "uni-datetime-picker.ok": "確定", |
| | | "uni-datetime-picker.clear": "清除", |
| | | "uni-datetime-picker.cancel": "取消", |
| | | "uni-datetime-picker.year": "年", |
| | | "uni-datetime-picker.month": "月", |
| | | "uni-calender.SUN": "日", |
| | | "uni-calender.MON": "一", |
| | | "uni-calender.TUE": "二", |
| | | "uni-calender.WED": "三", |
| | | "uni-calender.THU": "四", |
| | | "uni-calender.FRI": "五", |
| | | "uni-calender.SAT": "六", |
| | | "uni-calender.confirm": "確認" |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-datetime-picker"> |
| | | <view @click="initTimePicker"> |
| | | <slot> |
| | | <view class="uni-datetime-picker-timebox-pointer" |
| | | :class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}"> |
| | | <text class="uni-datetime-picker-text">{{time}}</text> |
| | | <view v-if="!time" class="uni-datetime-picker-time"> |
| | | <text class="uni-datetime-picker-text">{{selectTimeText}}</text> |
| | | </view> |
| | | </view> |
| | | </slot> |
| | | </view> |
| | | <view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view> |
| | | <view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']" |
| | | :style="fixNvueBug"> |
| | | <view class="uni-title"> |
| | | <text class="uni-datetime-picker-text">{{selectTimeText}}</text> |
| | | </view> |
| | | <view v-if="dateShow" class="uni-datetime-picker__container-box"> |
| | | <picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd" |
| | | @change="bindDateChange"> |
| | | <picker-view-column> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | <!-- 兼容 nvue 不支持伪类 --> |
| | | <text class="uni-datetime-picker-sign sign-left">-</text> |
| | | <text class="uni-datetime-picker-sign sign-right">-</text> |
| | | </view> |
| | | <view v-if="timeShow" class="uni-datetime-picker__container-box"> |
| | | <picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']" |
| | | :indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange"> |
| | | <picker-view-column> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!hideSecond"> |
| | | <view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index"> |
| | | <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | <!-- 兼容 nvue 不支持伪类 --> |
| | | <text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text> |
| | | <text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text> |
| | | </view> |
| | | <view class="uni-datetime-picker-btn"> |
| | | <view @click="clearTime"> |
| | | <text class="uni-datetime-picker-btn-text">{{clearText}}</text> |
| | | </view> |
| | | <view class="uni-datetime-picker-btn-group"> |
| | | <view class="uni-datetime-picker-cancel" @click="tiggerTimePicker"> |
| | | <text class="uni-datetime-picker-btn-text">{{cancelText}}</text> |
| | | </view> |
| | | <view @click="setTime"> |
| | | <text class="uni-datetime-picker-btn-text">{{okText}}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { initVueI18n } from '@dcloudio/uni-i18n' |
| | | import i18nMessages from './i18n/index.js' |
| | | const { t } = initVueI18n(i18nMessages) |
| | | import { fixIosDateFormat } from './util' |
| | | |
| | | /** |
| | | * DatetimePicker 时间选择器 |
| | | * @description 可以同时选择日期和时间的选择器 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx |
| | | * @property {String} type = [datetime | date | time] 显示模式 |
| | | * @property {Boolean} multiple = [true|false] 是否多选 |
| | | * @property {String|Number} value 默认值 |
| | | * @property {String|Number} start 起始日期或时间 |
| | | * @property {String|Number} end 起始日期或时间 |
| | | * @property {String} return-type = [timestamp | string] |
| | | * @event {Function} change 选中发生变化触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: 'UniDatetimePicker', |
| | | data() { |
| | | return { |
| | | indicatorStyle: `height: 50px;`, |
| | | visible: false, |
| | | fixNvueBug: {}, |
| | | dateShow: true, |
| | | timeShow: true, |
| | | title: '日期和时间', |
| | | // 输入框当前时间 |
| | | time: '', |
| | | // 当前的年月日时分秒 |
| | | year: 1920, |
| | | month: 0, |
| | | day: 0, |
| | | hour: 0, |
| | | minute: 0, |
| | | second: 0, |
| | | // 起始时间 |
| | | startYear: 1920, |
| | | startMonth: 1, |
| | | startDay: 1, |
| | | startHour: 0, |
| | | startMinute: 0, |
| | | startSecond: 0, |
| | | // 结束时间 |
| | | endYear: 2120, |
| | | endMonth: 12, |
| | | endDay: 31, |
| | | endHour: 23, |
| | | endMinute: 59, |
| | | endSecond: 59, |
| | | } |
| | | }, |
| | | props: { |
| | | type: { |
| | | type: String, |
| | | default: 'datetime' |
| | | }, |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | modelValue: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | start: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | end: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | returnType: { |
| | | type: String, |
| | | default: 'string' |
| | | }, |
| | | disabled: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | border: { |
| | | type: [Boolean, String], |
| | | default: true |
| | | }, |
| | | hideSecond: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | } |
| | | }, |
| | | watch: { |
| | | // #ifndef VUE3 |
| | | value: { |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.parseValue(fixIosDateFormat(newVal)) |
| | | this.initTime(false) |
| | | } else { |
| | | this.time = '' |
| | | this.parseValue(Date.now()) |
| | | } |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.parseValue(fixIosDateFormat(newVal)) |
| | | this.initTime(false) |
| | | } else { |
| | | this.time = '' |
| | | this.parseValue(Date.now()) |
| | | } |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | type: { |
| | | handler(newValue) { |
| | | if (newValue === 'date') { |
| | | this.dateShow = true |
| | | this.timeShow = false |
| | | this.title = '日期' |
| | | } else if (newValue === 'time') { |
| | | this.dateShow = false |
| | | this.timeShow = true |
| | | this.title = '时间' |
| | | } else { |
| | | this.dateShow = true |
| | | this.timeShow = true |
| | | this.title = '日期和时间' |
| | | } |
| | | }, |
| | | immediate: true |
| | | }, |
| | | start: { |
| | | handler(newVal) { |
| | | this.parseDatetimeRange(fixIosDateFormat(newVal), 'start') |
| | | }, |
| | | immediate: true |
| | | }, |
| | | end: { |
| | | handler(newVal) { |
| | | this.parseDatetimeRange(fixIosDateFormat(newVal), 'end') |
| | | }, |
| | | immediate: true |
| | | }, |
| | | |
| | | // 月、日、时、分、秒可选范围变化后,检查当前值是否在范围内,不在则当前值重置为可选范围第一项 |
| | | months(newVal) { |
| | | this.checkValue('month', this.month, newVal) |
| | | }, |
| | | days(newVal) { |
| | | this.checkValue('day', this.day, newVal) |
| | | }, |
| | | hours(newVal) { |
| | | this.checkValue('hour', this.hour, newVal) |
| | | }, |
| | | minutes(newVal) { |
| | | this.checkValue('minute', this.minute, newVal) |
| | | }, |
| | | seconds(newVal) { |
| | | this.checkValue('second', this.second, newVal) |
| | | } |
| | | }, |
| | | computed: { |
| | | // 当前年、月、日、时、分、秒选择范围 |
| | | years() { |
| | | return this.getCurrentRange('year') |
| | | }, |
| | | |
| | | months() { |
| | | return this.getCurrentRange('month') |
| | | }, |
| | | |
| | | days() { |
| | | return this.getCurrentRange('day') |
| | | }, |
| | | |
| | | hours() { |
| | | return this.getCurrentRange('hour') |
| | | }, |
| | | |
| | | minutes() { |
| | | return this.getCurrentRange('minute') |
| | | }, |
| | | |
| | | seconds() { |
| | | return this.getCurrentRange('second') |
| | | }, |
| | | |
| | | // picker 当前值数组 |
| | | ymd() { |
| | | return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay] |
| | | }, |
| | | hms() { |
| | | return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond] |
| | | }, |
| | | |
| | | // 当前 date 是 start |
| | | currentDateIsStart() { |
| | | return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay |
| | | }, |
| | | |
| | | // 当前 date 是 end |
| | | currentDateIsEnd() { |
| | | return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay |
| | | }, |
| | | |
| | | // 当前年、月、日、时、分、秒的最小值和最大值 |
| | | minYear() { |
| | | return this.startYear |
| | | }, |
| | | maxYear() { |
| | | return this.endYear |
| | | }, |
| | | minMonth() { |
| | | if (this.year === this.startYear) { |
| | | return this.startMonth |
| | | } else { |
| | | return 1 |
| | | } |
| | | }, |
| | | maxMonth() { |
| | | if (this.year === this.endYear) { |
| | | return this.endMonth |
| | | } else { |
| | | return 12 |
| | | } |
| | | }, |
| | | minDay() { |
| | | if (this.year === this.startYear && this.month === this.startMonth) { |
| | | return this.startDay |
| | | } else { |
| | | return 1 |
| | | } |
| | | }, |
| | | maxDay() { |
| | | if (this.year === this.endYear && this.month === this.endMonth) { |
| | | return this.endDay |
| | | } else { |
| | | return this.daysInMonth(this.year, this.month) |
| | | } |
| | | }, |
| | | minHour() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsStart) { |
| | | return this.startHour |
| | | } else { |
| | | return 0 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | return this.startHour |
| | | } |
| | | }, |
| | | maxHour() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsEnd) { |
| | | return this.endHour |
| | | } else { |
| | | return 23 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | return this.endHour |
| | | } |
| | | }, |
| | | minMinute() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsStart && this.hour === this.startHour) { |
| | | return this.startMinute |
| | | } else { |
| | | return 0 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | if (this.hour === this.startHour) { |
| | | return this.startMinute |
| | | } else { |
| | | return 0 |
| | | } |
| | | } |
| | | }, |
| | | maxMinute() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsEnd && this.hour === this.endHour) { |
| | | return this.endMinute |
| | | } else { |
| | | return 59 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | if (this.hour === this.endHour) { |
| | | return this.endMinute |
| | | } else { |
| | | return 59 |
| | | } |
| | | } |
| | | }, |
| | | minSecond() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) { |
| | | return this.startSecond |
| | | } else { |
| | | return 0 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | if (this.hour === this.startHour && this.minute === this.startMinute) { |
| | | return this.startSecond |
| | | } else { |
| | | return 0 |
| | | } |
| | | } |
| | | }, |
| | | maxSecond() { |
| | | if (this.type === 'datetime') { |
| | | if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) { |
| | | return this.endSecond |
| | | } else { |
| | | return 59 |
| | | } |
| | | } |
| | | if (this.type === 'time') { |
| | | if (this.hour === this.endHour && this.minute === this.endMinute) { |
| | | return this.endSecond |
| | | } else { |
| | | return 59 |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * for i18n |
| | | */ |
| | | selectTimeText() { |
| | | return t("uni-datetime-picker.selectTime") |
| | | }, |
| | | okText() { |
| | | return t("uni-datetime-picker.ok") |
| | | }, |
| | | clearText() { |
| | | return t("uni-datetime-picker.clear") |
| | | }, |
| | | cancelText() { |
| | | return t("uni-datetime-picker.cancel") |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | // #ifdef APP-NVUE |
| | | const res = uni.getSystemInfoSync(); |
| | | this.fixNvueBug = { |
| | | top: res.windowHeight / 2, |
| | | left: res.windowWidth / 2 |
| | | } |
| | | // #endif |
| | | }, |
| | | |
| | | methods: { |
| | | /** |
| | | * @param {Object} item |
| | | * 小于 10 在前面加个 0 |
| | | */ |
| | | |
| | | lessThanTen(item) { |
| | | return item < 10 ? '0' + item : item |
| | | }, |
| | | |
| | | /** |
| | | * 解析时分秒字符串,例如:00:00:00 |
| | | * @param {String} timeString |
| | | */ |
| | | parseTimeType(timeString) { |
| | | if (timeString) { |
| | | let timeArr = timeString.split(':') |
| | | this.hour = Number(timeArr[0]) |
| | | this.minute = Number(timeArr[1]) |
| | | this.second = Number(timeArr[2]) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 解析选择器初始值,类型可以是字符串、时间戳,例如:2000-10-02、'08:30:00'、 1610695109000 |
| | | * @param {String | Number} datetime |
| | | */ |
| | | initPickerValue(datetime) { |
| | | let defaultValue = null |
| | | if (datetime) { |
| | | defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end) |
| | | } else { |
| | | defaultValue = Date.now() |
| | | defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end) |
| | | } |
| | | this.parseValue(defaultValue) |
| | | }, |
| | | |
| | | /** |
| | | * 初始值规则: |
| | | * - 用户设置初始值 value |
| | | * - 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start |
| | | * - 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start |
| | | * - 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end |
| | | * - 无起始终止时间,则初始值为 value |
| | | * - 无初始值 value,则初始值为当前本地时间 Date.now() |
| | | * @param {Object} value |
| | | * @param {Object} dateBase |
| | | */ |
| | | compareValueWithStartAndEnd(value, start, end) { |
| | | let winner = null |
| | | value = this.superTimeStamp(value) |
| | | start = this.superTimeStamp(start) |
| | | end = this.superTimeStamp(end) |
| | | |
| | | if (start && end) { |
| | | if (value < start) { |
| | | winner = new Date(start) |
| | | } else if (value > end) { |
| | | winner = new Date(end) |
| | | } else { |
| | | winner = new Date(value) |
| | | } |
| | | } else if (start && !end) { |
| | | winner = start <= value ? new Date(value) : new Date(start) |
| | | } else if (!start && end) { |
| | | winner = value <= end ? new Date(value) : new Date(end) |
| | | } else { |
| | | winner = new Date(value) |
| | | } |
| | | |
| | | return winner |
| | | }, |
| | | |
| | | /** |
| | | * 转换为可比较的时间戳,接受日期、时分秒、时间戳 |
| | | * @param {Object} value |
| | | */ |
| | | superTimeStamp(value) { |
| | | let dateBase = '' |
| | | if (this.type === 'time' && value && typeof value === 'string') { |
| | | const now = new Date() |
| | | const year = now.getFullYear() |
| | | const month = now.getMonth() + 1 |
| | | const day = now.getDate() |
| | | dateBase = year + '/' + month + '/' + day + ' ' |
| | | } |
| | | if (Number(value)) { |
| | | value = parseInt(value) |
| | | dateBase = 0 |
| | | } |
| | | return this.createTimeStamp(dateBase + value) |
| | | }, |
| | | |
| | | /** |
| | | * 解析默认值 value,字符串、时间戳 |
| | | * @param {Object} defaultTime |
| | | */ |
| | | parseValue(value) { |
| | | if (!value) { |
| | | return |
| | | } |
| | | if (this.type === 'time' && typeof value === "string") { |
| | | this.parseTimeType(value) |
| | | } else { |
| | | let defaultDate = null |
| | | defaultDate = new Date(value) |
| | | if (this.type !== 'time') { |
| | | this.year = defaultDate.getFullYear() |
| | | this.month = defaultDate.getMonth() + 1 |
| | | this.day = defaultDate.getDate() |
| | | } |
| | | if (this.type !== 'date') { |
| | | this.hour = defaultDate.getHours() |
| | | this.minute = defaultDate.getMinutes() |
| | | this.second = defaultDate.getSeconds() |
| | | } |
| | | } |
| | | if (this.hideSecond) { |
| | | this.second = 0 |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 解析可选择时间范围 start、end,年月日字符串、时间戳 |
| | | * @param {Object} defaultTime |
| | | */ |
| | | parseDatetimeRange(point, pointType) { |
| | | // 时间为空,则重置为初始值 |
| | | if (!point) { |
| | | if (pointType === 'start') { |
| | | this.startYear = 1920 |
| | | this.startMonth = 1 |
| | | this.startDay = 1 |
| | | this.startHour = 0 |
| | | this.startMinute = 0 |
| | | this.startSecond = 0 |
| | | } |
| | | if (pointType === 'end') { |
| | | this.endYear = 2120 |
| | | this.endMonth = 12 |
| | | this.endDay = 31 |
| | | this.endHour = 23 |
| | | this.endMinute = 59 |
| | | this.endSecond = 59 |
| | | } |
| | | return |
| | | } |
| | | if (this.type === 'time') { |
| | | const pointArr = point.split(':') |
| | | this[pointType + 'Hour'] = Number(pointArr[0]) |
| | | this[pointType + 'Minute'] = Number(pointArr[1]) |
| | | this[pointType + 'Second'] = Number(pointArr[2]) |
| | | } else { |
| | | if (!point) { |
| | | pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60 |
| | | return |
| | | } |
| | | if (Number(point)) { |
| | | point = parseInt(point) |
| | | } |
| | | // datetime 的 end 没有时分秒, 则不限制 |
| | | const hasTime = /[0-9]:[0-9]/ |
| | | if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test( |
| | | point)) { |
| | | point = point + ' 23:59:59' |
| | | } |
| | | const pointDate = new Date(point) |
| | | this[pointType + 'Year'] = pointDate.getFullYear() |
| | | this[pointType + 'Month'] = pointDate.getMonth() + 1 |
| | | this[pointType + 'Day'] = pointDate.getDate() |
| | | if (this.type === 'datetime') { |
| | | this[pointType + 'Hour'] = pointDate.getHours() |
| | | this[pointType + 'Minute'] = pointDate.getMinutes() |
| | | this[pointType + 'Second'] = pointDate.getSeconds() |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 获取 年、月、日、时、分、秒 当前可选范围 |
| | | getCurrentRange(value) { |
| | | const range = [] |
| | | for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) { |
| | | range.push(i) |
| | | } |
| | | return range |
| | | }, |
| | | |
| | | // 字符串首字母大写 |
| | | capitalize(str) { |
| | | return str.charAt(0).toUpperCase() + str.slice(1) |
| | | }, |
| | | |
| | | // 检查当前值是否在范围内,不在则当前值重置为可选范围第一项 |
| | | checkValue(name, value, values) { |
| | | if (values.indexOf(value) === -1) { |
| | | this[name] = values[0] |
| | | } |
| | | }, |
| | | |
| | | // 每个月的实际天数 |
| | | daysInMonth(year, month) { // Use 1 for January, 2 for February, etc. |
| | | return new Date(year, month, 0).getDate(); |
| | | }, |
| | | |
| | | //兼容 iOS、safari 日期格式 |
| | | fixIosDateFormat(value) { |
| | | if (typeof value === 'string') { |
| | | value = value.replace(/-/g, '/') |
| | | } |
| | | return value |
| | | }, |
| | | |
| | | /** |
| | | * 生成时间戳 |
| | | * @param {Object} time |
| | | */ |
| | | createTimeStamp(time) { |
| | | if (!time) return |
| | | if (typeof time === "number") { |
| | | return time |
| | | } else { |
| | | time = time.replace(/-/g, '/') |
| | | if (this.type === 'date') { |
| | | time = time + ' ' + '00:00:00' |
| | | } |
| | | return Date.parse(time) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 生成日期或时间的字符串 |
| | | */ |
| | | createDomSting() { |
| | | const yymmdd = this.year + |
| | | '-' + |
| | | this.lessThanTen(this.month) + |
| | | '-' + |
| | | this.lessThanTen(this.day) |
| | | |
| | | let hhmmss = this.lessThanTen(this.hour) + |
| | | ':' + |
| | | this.lessThanTen(this.minute) |
| | | |
| | | if (!this.hideSecond) { |
| | | hhmmss = hhmmss + ':' + this.lessThanTen(this.second) |
| | | } |
| | | |
| | | if (this.type === 'date') { |
| | | return yymmdd |
| | | } else if (this.type === 'time') { |
| | | return hhmmss |
| | | } else { |
| | | return yymmdd + ' ' + hhmmss |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 初始化返回值,并抛出 change 事件 |
| | | */ |
| | | initTime(emit = true) { |
| | | this.time = this.createDomSting() |
| | | if (!emit) return |
| | | if (this.returnType === 'timestamp' && this.type !== 'time') { |
| | | this.$emit('change', this.createTimeStamp(this.time)) |
| | | this.$emit('input', this.createTimeStamp(this.time)) |
| | | this.$emit('update:modelValue', this.createTimeStamp(this.time)) |
| | | } else { |
| | | this.$emit('change', this.time) |
| | | this.$emit('input', this.time) |
| | | this.$emit('update:modelValue', this.time) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 用户选择日期或时间更新 data |
| | | * @param {Object} e |
| | | */ |
| | | bindDateChange(e) { |
| | | const val = e.detail.value |
| | | this.year = this.years[val[0]] |
| | | this.month = this.months[val[1]] |
| | | this.day = this.days[val[2]] |
| | | }, |
| | | bindTimeChange(e) { |
| | | const val = e.detail.value |
| | | this.hour = this.hours[val[0]] |
| | | this.minute = this.minutes[val[1]] |
| | | this.second = this.seconds[val[2]] |
| | | }, |
| | | |
| | | /** |
| | | * 初始化弹出层 |
| | | */ |
| | | initTimePicker() { |
| | | if (this.disabled) return |
| | | const value = fixIosDateFormat(this.time) |
| | | this.initPickerValue(value) |
| | | this.visible = !this.visible |
| | | }, |
| | | |
| | | /** |
| | | * 触发或关闭弹框 |
| | | */ |
| | | tiggerTimePicker(e) { |
| | | this.visible = !this.visible |
| | | }, |
| | | |
| | | /** |
| | | * 用户点击“清空”按钮,清空当前值 |
| | | */ |
| | | clearTime() { |
| | | this.time = '' |
| | | this.$emit('change', this.time) |
| | | this.$emit('input', this.time) |
| | | this.$emit('update:modelValue', this.time) |
| | | this.tiggerTimePicker() |
| | | }, |
| | | |
| | | /** |
| | | * 用户点击“确定”按钮 |
| | | */ |
| | | setTime() { |
| | | this.initTime() |
| | | this.tiggerTimePicker() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-primary: #007aff !default; |
| | | |
| | | .uni-datetime-picker { |
| | | /* #ifndef APP-NVUE */ |
| | | /* width: 100%; */ |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-datetime-picker-view { |
| | | height: 130px; |
| | | width: 270px; |
| | | /* #ifndef APP-NVUE */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-datetime-picker-item { |
| | | height: 50px; |
| | | line-height: 50px; |
| | | text-align: center; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .uni-datetime-picker-btn { |
| | | margin-top: 60px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .uni-datetime-picker-btn-text { |
| | | font-size: 14px; |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .uni-datetime-picker-btn-group { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .uni-datetime-picker-cancel { |
| | | margin-right: 30px; |
| | | } |
| | | |
| | | .uni-datetime-picker-mask { |
| | | position: fixed; |
| | | bottom: 0px; |
| | | top: 0px; |
| | | left: 0px; |
| | | right: 0px; |
| | | background-color: rgba(0, 0, 0, 0.4); |
| | | transition-duration: 0.3s; |
| | | z-index: 998; |
| | | } |
| | | |
| | | .uni-datetime-picker-popup { |
| | | border-radius: 8px; |
| | | padding: 30px; |
| | | width: 270px; |
| | | /* #ifdef APP-NVUE */ |
| | | height: 500px; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | width: 330px; |
| | | /* #endif */ |
| | | background-color: #fff; |
| | | position: fixed; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | transition-duration: 0.3s; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .fix-nvue-height { |
| | | /* #ifdef APP-NVUE */ |
| | | height: 330px; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-datetime-picker-time { |
| | | color: grey; |
| | | } |
| | | |
| | | .uni-datetime-picker-column { |
| | | height: 50px; |
| | | } |
| | | |
| | | .uni-datetime-picker-timebox { |
| | | |
| | | border: 1px solid #E5E5E5; |
| | | border-radius: 5px; |
| | | padding: 7px 10px; |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-datetime-picker-timebox-pointer { |
| | | /* #ifndef APP-NVUE */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | |
| | | .uni-datetime-picker-disabled { |
| | | opacity: 0.4; |
| | | /* #ifdef H5 */ |
| | | cursor: not-allowed !important; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-datetime-picker-text { |
| | | font-size: 14px; |
| | | line-height: 50px |
| | | } |
| | | |
| | | .uni-datetime-picker-sign { |
| | | position: absolute; |
| | | top: 53px; |
| | | /* 减掉 10px 的元素高度,兼容nvue */ |
| | | color: #999; |
| | | /* #ifdef APP-NVUE */ |
| | | font-size: 16px; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .sign-left { |
| | | left: 86px; |
| | | } |
| | | |
| | | .sign-right { |
| | | right: 86px; |
| | | } |
| | | |
| | | .sign-center { |
| | | left: 135px; |
| | | } |
| | | |
| | | .uni-datetime-picker__container-box { |
| | | position: relative; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: 40px; |
| | | } |
| | | |
| | | .time-hide-second { |
| | | width: 180px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-date"> |
| | | <view class="uni-date-editor" @click="show"> |
| | | <slot> |
| | | <view |
| | | class="uni-date-editor--x" |
| | | :class="{'uni-date-editor--x__disabled': disabled,'uni-date-x--border': border}" |
| | | > |
| | | <view v-if="!isRange" class="uni-date-x uni-date-single"> |
| | | <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons> |
| | | <view class="uni-date__x-input">{{ displayValue || singlePlaceholderText }}</view> |
| | | </view> |
| | | |
| | | <view v-else class="uni-date-x uni-date-range"> |
| | | <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons> |
| | | <view class="uni-date__x-input text-center">{{ displayRangeValue.startDate || startPlaceholderText }}</view> |
| | | |
| | | <view class="range-separator">{{rangeSeparator}}</view> |
| | | |
| | | <view class="uni-date__x-input text-center">{{ displayRangeValue.endDate || endPlaceholderText }}</view> |
| | | </view> |
| | | |
| | | <view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear"> |
| | | <uni-icons type="clear" color="#c0c4cc" size="22"></uni-icons> |
| | | </view> |
| | | </view> |
| | | </slot> |
| | | </view> |
| | | |
| | | <view v-show="pickerVisible" class="uni-date-mask--pc" @click="close"></view> |
| | | |
| | | <view v-if="!isPhone" v-show="pickerVisible" ref="datePicker" class="uni-date-picker__container"> |
| | | <view v-if="!isRange" class="uni-date-single--x" :style="pickerPositionStyle"> |
| | | <view class="uni-popper__arrow"></view> |
| | | |
| | | <view v-if="hasTime" class="uni-date-changed popup-x-header"> |
| | | <input class="uni-date__input text-center" type="text" v-model="inputDate" |
| | | :placeholder="selectDateText" /> |
| | | |
| | | <time-picker type="time" v-model="pickerTime" :border="false" :disabled="!inputDate" |
| | | :start="timepickerStartTime" :end="timepickerEndTime" :hideSecond="hideSecond" style="width: 100%;"> |
| | | <input class="uni-date__input text-center" type="text" v-model="pickerTime" :placeholder="selectTimeText" |
| | | :disabled="!inputDate" /> |
| | | </time-picker> |
| | | </view> |
| | | |
| | | <Calendar ref="pcSingle" :showMonth="false" :start-date="calendarRange.startDate" |
| | | :end-date="calendarRange.endDate" :date="calendarDate" @change="singleChange" |
| | | :default-value="defaultValue" |
| | | style="padding: 0 8px;" /> |
| | | |
| | | <view v-if="hasTime" class="popup-x-footer"> |
| | | <text class="confirm-text" @click="confirmSingleChange">{{okText}}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="uni-date-range--x" :style="pickerPositionStyle"> |
| | | <view class="uni-popper__arrow"></view> |
| | | <view v-if="hasTime" class="popup-x-header uni-date-changed"> |
| | | <view class="popup-x-header--datetime"> |
| | | <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.startDate" |
| | | :placeholder="startDateText" /> |
| | | |
| | | <time-picker type="time" v-model="tempRange.startTime" :start="timepickerStartTime" :border="false" |
| | | :disabled="!tempRange.startDate" :hideSecond="hideSecond"> |
| | | <input class="uni-date__input uni-date-range__input" type="text" |
| | | v-model="tempRange.startTime" :placeholder="startTimeText" |
| | | :disabled="!tempRange.startDate" /> |
| | | </time-picker> |
| | | </view> |
| | | |
| | | <uni-icons type="arrowthinright" color="#999" style="line-height: 40px;"></uni-icons> |
| | | |
| | | <view class="popup-x-header--datetime"> |
| | | <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endDate" |
| | | :placeholder="endDateText" /> |
| | | |
| | | <time-picker type="time" v-model="tempRange.endTime" :end="timepickerEndTime" :border="false" |
| | | :disabled="!tempRange.endDate" :hideSecond="hideSecond"> |
| | | <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endTime" |
| | | :placeholder="endTimeText" :disabled="!tempRange.endDate" /> |
| | | </time-picker> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="popup-x-body"> |
| | | <Calendar ref="left" :showMonth="false" :start-date="calendarRange.startDate" |
| | | :end-date="calendarRange.endDate" :range="true" :pleStatus="endMultipleStatus" |
| | | @change="leftChange" @firstEnterCale="updateRightCale" style="padding: 0 8px;" /> |
| | | <Calendar ref="right" :showMonth="false" :start-date="calendarRange.startDate" |
| | | :end-date="calendarRange.endDate" :range="true" @change="rightChange" |
| | | :pleStatus="startMultipleStatus" @firstEnterCale="updateLeftCale" |
| | | style="padding: 0 8px;border-left: 1px solid #F1F1F1;" /> |
| | | </view> |
| | | |
| | | <view v-if="hasTime" class="popup-x-footer"> |
| | | <text @click="clear">{{clearText}}</text> |
| | | <text class="confirm-text" @click="confirmRangeChange">{{okText}}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <Calendar v-if="isPhone" ref="mobile" :clearDate="false" :date="calendarDate" :defTime="mobileCalendarTime" |
| | | :start-date="calendarRange.startDate" :end-date="calendarRange.endDate" :selectableTimes="mobSelectableTime" |
| | | :startPlaceholder="startPlaceholder" :endPlaceholder="endPlaceholder" |
| | | :default-value="defaultValue" |
| | | :pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :hasTime="hasTime" :insert="false" |
| | | :hideSecond="hideSecond" @confirm="mobileChange" @maskClose="close" /> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | /** |
| | | * DatetimePicker 时间选择器 |
| | | * @description 同时支持 PC 和移动端使用日历选择日期和日期范围 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=3962 |
| | | * @property {String} type 选择器类型 |
| | | * @property {String|Number|Array|Date} value 绑定值 |
| | | * @property {String} placeholder 单选择时的占位内容 |
| | | * @property {String} start 起始时间 |
| | | * @property {String} end 终止时间 |
| | | * @property {String} start-placeholder 范围选择时开始日期的占位内容 |
| | | * @property {String} end-placeholder 范围选择时结束日期的占位内容 |
| | | * @property {String} range-separator 选择范围时的分隔符 |
| | | * @property {Boolean} border = [true|false] 是否有边框 |
| | | * @property {Boolean} disabled = [true|false] 是否禁用 |
| | | * @property {Boolean} clearIcon = [true|false] 是否显示清除按钮(仅PC端适用) |
| | | * @property {[String} defaultValue 选择器打开时默认显示的时间 |
| | | * @event {Function} change 确定日期时触发的事件 |
| | | * @event {Function} maskClick 点击遮罩层触发的事件 |
| | | * @event {Function} show 打开弹出层 |
| | | * @event {Function} close 关闭弹出层 |
| | | * @event {Function} clear 清除上次选中的状态和值 |
| | | **/ |
| | | import Calendar from './calendar.vue' |
| | | import TimePicker from './time-picker.vue' |
| | | import { initVueI18n } from '@dcloudio/uni-i18n' |
| | | import i18nMessages from './i18n/index.js' |
| | | import { getDateTime, getDate, getTime, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat } from './util' |
| | | |
| | | export default { |
| | | name: 'UniDatetimePicker', |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | components: { |
| | | Calendar, |
| | | TimePicker |
| | | }, |
| | | data() { |
| | | return { |
| | | isRange: false, |
| | | hasTime: false, |
| | | displayValue: '', |
| | | inputDate: '', |
| | | calendarDate: '', |
| | | pickerTime: '', |
| | | calendarRange: { |
| | | startDate: '', |
| | | startTime: '', |
| | | endDate: '', |
| | | endTime: '' |
| | | }, |
| | | displayRangeValue: { |
| | | startDate: '', |
| | | endDate: '', |
| | | }, |
| | | tempRange: { |
| | | startDate: '', |
| | | startTime: '', |
| | | endDate: '', |
| | | endTime: '' |
| | | }, |
| | | // 左右日历同步数据 |
| | | startMultipleStatus: { |
| | | before: '', |
| | | after: '', |
| | | data: [], |
| | | fulldate: '' |
| | | }, |
| | | endMultipleStatus: { |
| | | before: '', |
| | | after: '', |
| | | data: [], |
| | | fulldate: '' |
| | | }, |
| | | pickerVisible: false, |
| | | pickerPositionStyle: null, |
| | | isEmitValue: false, |
| | | isPhone: false, |
| | | isFirstShow: true, |
| | | i18nT: () => {} |
| | | } |
| | | }, |
| | | props: { |
| | | type: { |
| | | type: String, |
| | | default: 'datetime' |
| | | }, |
| | | value: { |
| | | type: [String, Number, Array, Date], |
| | | default: '' |
| | | }, |
| | | modelValue: { |
| | | type: [String, Number, Array, Date], |
| | | default: '' |
| | | }, |
| | | start: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | end: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | returnType: { |
| | | type: String, |
| | | default: 'string' |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | startPlaceholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | endPlaceholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | rangeSeparator: { |
| | | type: String, |
| | | default: '-' |
| | | }, |
| | | border: { |
| | | type: [Boolean], |
| | | default: true |
| | | }, |
| | | disabled: { |
| | | type: [Boolean], |
| | | default: false |
| | | }, |
| | | clearIcon: { |
| | | type: [Boolean], |
| | | default: true |
| | | }, |
| | | hideSecond: { |
| | | type: [Boolean], |
| | | default: false |
| | | }, |
| | | defaultValue: { |
| | | type: [String, Object, Array], |
| | | default: '' |
| | | } |
| | | }, |
| | | watch: { |
| | | type: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | this.hasTime = newVal.indexOf('time') !== -1 |
| | | this.isRange = newVal.indexOf('range') !== -1 |
| | | } |
| | | }, |
| | | // #ifndef VUE3 |
| | | value: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (this.isEmitValue) { |
| | | this.isEmitValue = false |
| | | return |
| | | } |
| | | this.initPicker(newVal) |
| | | } |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (this.isEmitValue) { |
| | | this.isEmitValue = false |
| | | return |
| | | } |
| | | this.initPicker(newVal) |
| | | } |
| | | }, |
| | | // #endif |
| | | start: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (!newVal) return |
| | | this.calendarRange.startDate = getDate(newVal) |
| | | if (this.hasTime) { |
| | | this.calendarRange.startTime = getTime(newVal) |
| | | } |
| | | } |
| | | }, |
| | | end: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (!newVal) return |
| | | this.calendarRange.endDate = getDate(newVal) |
| | | if (this.hasTime) { |
| | | this.calendarRange.endTime = getTime(newVal, this.hideSecond) |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | computed: { |
| | | timepickerStartTime() { |
| | | const activeDate = this.isRange ? this.tempRange.startDate : this.inputDate |
| | | return activeDate === this.calendarRange.startDate ? this.calendarRange.startTime : '' |
| | | }, |
| | | timepickerEndTime() { |
| | | const activeDate = this.isRange ? this.tempRange.endDate : this.inputDate |
| | | return activeDate === this.calendarRange.endDate ? this.calendarRange.endTime : '' |
| | | }, |
| | | mobileCalendarTime() { |
| | | const timeRange = { |
| | | start: this.tempRange.startTime, |
| | | end: this.tempRange.endTime |
| | | } |
| | | return this.isRange ? timeRange : this.pickerTime |
| | | }, |
| | | mobSelectableTime() { |
| | | return { |
| | | start: this.calendarRange.startTime, |
| | | end: this.calendarRange.endTime |
| | | } |
| | | }, |
| | | datePopupWidth() { |
| | | // todo |
| | | return this.isRange ? 653 : 301 |
| | | }, |
| | | |
| | | /** |
| | | * for i18n |
| | | */ |
| | | singlePlaceholderText() { |
| | | return this.placeholder || (this.type === 'date' ? this.selectDateText : this.selectDateTimeText) |
| | | }, |
| | | startPlaceholderText() { |
| | | return this.startPlaceholder || this.startDateText |
| | | }, |
| | | endPlaceholderText() { |
| | | return this.endPlaceholder || this.endDateText |
| | | }, |
| | | selectDateText() { |
| | | return this.i18nT("uni-datetime-picker.selectDate") |
| | | }, |
| | | selectDateTimeText() { |
| | | return this.i18nT("uni-datetime-picker.selectDateTime") |
| | | }, |
| | | selectTimeText() { |
| | | return this.i18nT("uni-datetime-picker.selectTime") |
| | | }, |
| | | startDateText() { |
| | | return this.startPlaceholder || this.i18nT("uni-datetime-picker.startDate") |
| | | }, |
| | | startTimeText() { |
| | | return this.i18nT("uni-datetime-picker.startTime") |
| | | }, |
| | | endDateText() { |
| | | return this.endPlaceholder || this.i18nT("uni-datetime-picker.endDate") |
| | | }, |
| | | endTimeText() { |
| | | return this.i18nT("uni-datetime-picker.endTime") |
| | | }, |
| | | okText() { |
| | | return this.i18nT("uni-datetime-picker.ok") |
| | | }, |
| | | clearText() { |
| | | return this.i18nT("uni-datetime-picker.clear") |
| | | }, |
| | | showClearIcon() { |
| | | return this.clearIcon && !this.disabled && (this.displayValue || (this.displayRangeValue.startDate && this.displayRangeValue.endDate)) |
| | | } |
| | | }, |
| | | created() { |
| | | this.initI18nT() |
| | | this.platform() |
| | | }, |
| | | methods: { |
| | | initI18nT() { |
| | | const vueI18n = initVueI18n(i18nMessages) |
| | | this.i18nT = vueI18n.t |
| | | }, |
| | | initPicker(newVal) { |
| | | if ((!newVal && !this.defaultValue) || Array.isArray(newVal) && !newVal.length) { |
| | | this.$nextTick(() => { |
| | | this.clear(false) |
| | | }) |
| | | return |
| | | } |
| | | |
| | | if (!Array.isArray(newVal) && !this.isRange) { |
| | | if(newVal){ |
| | | this.displayValue = this.inputDate = this.calendarDate = getDate(newVal) |
| | | if (this.hasTime) { |
| | | this.pickerTime = getTime(newVal, this.hideSecond) |
| | | this.displayValue = `${this.displayValue} ${this.pickerTime}` |
| | | } |
| | | }else if(this.defaultValue){ |
| | | this.inputDate = this.calendarDate = getDate(this.defaultValue) |
| | | if(this.hasTime){ |
| | | this.pickerTime = getTime(this.defaultValue, this.hideSecond) |
| | | } |
| | | } |
| | | } else { |
| | | const [before, after] = newVal |
| | | if (!before && !after) return |
| | | const beforeDate = getDate(before) |
| | | const beforeTime = getTime(before, this.hideSecond) |
| | | |
| | | const afterDate = getDate(after) |
| | | const afterTime = getTime(after, this.hideSecond) |
| | | const startDate = beforeDate |
| | | const endDate = afterDate |
| | | this.displayRangeValue.startDate = this.tempRange.startDate = startDate |
| | | this.displayRangeValue.endDate = this.tempRange.endDate = endDate |
| | | |
| | | if (this.hasTime) { |
| | | this.displayRangeValue.startDate = `${beforeDate} ${beforeTime}` |
| | | this.displayRangeValue.endDate = `${afterDate} ${afterTime}` |
| | | this.tempRange.startTime = beforeTime |
| | | this.tempRange.endTime = afterTime |
| | | } |
| | | const defaultRange = { |
| | | before: beforeDate, |
| | | after: afterDate |
| | | } |
| | | this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, defaultRange, { |
| | | which: 'right' |
| | | }) |
| | | this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, defaultRange, { |
| | | which: 'left' |
| | | }) |
| | | } |
| | | }, |
| | | updateLeftCale(e) { |
| | | const left = this.$refs.left |
| | | // 设置范围选 |
| | | left.cale.setHoverMultiple(e.after) |
| | | left.setDate(this.$refs.left.nowDate.fullDate) |
| | | }, |
| | | updateRightCale(e) { |
| | | const right = this.$refs.right |
| | | // 设置范围选 |
| | | right.cale.setHoverMultiple(e.after) |
| | | right.setDate(this.$refs.right.nowDate.fullDate) |
| | | }, |
| | | platform() { |
| | | const { windowWidth } = uni.getSystemInfoSync() |
| | | this.isPhone = windowWidth <= 500 |
| | | this.windowWidth = windowWidth |
| | | }, |
| | | show() { |
| | | if (this.disabled) { |
| | | return |
| | | } |
| | | this.platform() |
| | | if (this.isPhone) { |
| | | this.$refs.mobile.open() |
| | | return |
| | | } |
| | | this.pickerPositionStyle = { |
| | | top: '10px' |
| | | } |
| | | const dateEditor = uni.createSelectorQuery().in(this).select(".uni-date-editor") |
| | | dateEditor.boundingClientRect(rect => { |
| | | if (this.windowWidth - rect.left < this.datePopupWidth) { |
| | | this.pickerPositionStyle.right = 0 |
| | | } |
| | | }).exec() |
| | | setTimeout(() => { |
| | | this.pickerVisible = !this.pickerVisible |
| | | if (!this.isPhone && this.isRange && this.isFirstShow) { |
| | | this.isFirstShow = false |
| | | const { |
| | | startDate, |
| | | endDate |
| | | } = this.calendarRange |
| | | if (startDate && endDate) { |
| | | if (this.diffDate(startDate, endDate) < 30) { |
| | | this.$refs.right.changeMonth('pre') |
| | | } |
| | | } else { |
| | | this.$refs.right.changeMonth('next') |
| | | this.$refs.right.cale.lastHover = false |
| | | } |
| | | } |
| | | |
| | | }, 50) |
| | | }, |
| | | close() { |
| | | setTimeout(() => { |
| | | this.pickerVisible = false |
| | | this.$emit('maskClick', this.value) |
| | | this.$refs.mobile && this.$refs.mobile.close() |
| | | }, 20) |
| | | }, |
| | | setEmit(value) { |
| | | if (this.returnType === "timestamp" || this.returnType === "date") { |
| | | if (!Array.isArray(value)) { |
| | | if (!this.hasTime) { |
| | | value = value + ' ' + '00:00:00' |
| | | } |
| | | value = this.createTimestamp(value) |
| | | if (this.returnType === "date") { |
| | | value = new Date(value) |
| | | } |
| | | } else { |
| | | if (!this.hasTime) { |
| | | value[0] = value[0] + ' ' + '00:00:00' |
| | | value[1] = value[1] + ' ' + '00:00:00' |
| | | } |
| | | value[0] = this.createTimestamp(value[0]) |
| | | value[1] = this.createTimestamp(value[1]) |
| | | if (this.returnType === "date") { |
| | | value[0] = new Date(value[0]) |
| | | value[1] = new Date(value[1]) |
| | | } |
| | | } |
| | | } |
| | | |
| | | this.$emit('update:modelValue', value) |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | this.isEmitValue = true |
| | | }, |
| | | createTimestamp(date) { |
| | | date = fixIosDateFormat(date) |
| | | return Date.parse(new Date(date)) |
| | | }, |
| | | singleChange(e) { |
| | | this.calendarDate = this.inputDate = e.fulldate |
| | | if (this.hasTime) return |
| | | this.confirmSingleChange() |
| | | }, |
| | | confirmSingleChange() { |
| | | if(!checkDate(this.inputDate)){ |
| | | const now = new Date() |
| | | this.calendarDate = this.inputDate = getDate(now) |
| | | this.pickerTime = getTime(now, this.hideSecond) |
| | | } |
| | | |
| | | let startLaterInputDate = false |
| | | let startDate, startTime |
| | | if(this.start) { |
| | | let startString = this.start |
| | | if(typeof this.start === 'number'){ |
| | | startString = getDateTime(this.start, this.hideSecond) |
| | | } |
| | | [startDate, startTime] = startString.split(' ') |
| | | if(this.start && !dateCompare(startDate, this.inputDate)) { |
| | | startLaterInputDate = true |
| | | this.inputDate = startDate |
| | | } |
| | | } |
| | | |
| | | let endEarlierInputDate = false |
| | | let endDate, endTime |
| | | if(this.end) { |
| | | let endString = this.end |
| | | if(typeof this.end === 'number'){ |
| | | endString = getDateTime(this.end, this.hideSecond) |
| | | } |
| | | [endDate, endTime] = endString.split(' ') |
| | | if(this.end && !dateCompare(this.inputDate, endDate)) { |
| | | endEarlierInputDate = true |
| | | this.inputDate = endDate |
| | | } |
| | | } |
| | | if (this.hasTime) { |
| | | if(startLaterInputDate){ |
| | | this.pickerTime = startTime || getDefaultSecond(this.hideSecond) |
| | | } |
| | | if(endEarlierInputDate){ |
| | | this.pickerTime = endTime || getDefaultSecond(this.hideSecond) |
| | | } |
| | | if(!this.pickerTime){ |
| | | this.pickerTime = getTime(Date.now(), this.hideSecond) |
| | | } |
| | | this.displayValue = `${this.inputDate} ${this.pickerTime}` |
| | | } else { |
| | | this.displayValue = this.inputDate |
| | | } |
| | | this.setEmit(this.displayValue) |
| | | this.pickerVisible = false |
| | | }, |
| | | leftChange(e) { |
| | | const { |
| | | before, |
| | | after |
| | | } = e.range |
| | | this.rangeChange(before, after) |
| | | const obj = { |
| | | before: e.range.before, |
| | | after: e.range.after, |
| | | data: e.range.data, |
| | | fulldate: e.fulldate |
| | | } |
| | | this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, obj) |
| | | }, |
| | | rightChange(e) { |
| | | const { |
| | | before, |
| | | after |
| | | } = e.range |
| | | this.rangeChange(before, after) |
| | | const obj = { |
| | | before: e.range.before, |
| | | after: e.range.after, |
| | | data: e.range.data, |
| | | fulldate: e.fulldate |
| | | } |
| | | this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, obj) |
| | | }, |
| | | mobileChange(e) { |
| | | if (this.isRange) { |
| | | const {before, after} = e.range |
| | | |
| | | if(!before || !after){ |
| | | return |
| | | } |
| | | |
| | | this.handleStartAndEnd(before, after, true) |
| | | if (this.hasTime) { |
| | | const { |
| | | startTime, |
| | | endTime |
| | | } = e.timeRange |
| | | this.tempRange.startTime = startTime |
| | | this.tempRange.endTime = endTime |
| | | } |
| | | this.confirmRangeChange() |
| | | } else { |
| | | if (this.hasTime) { |
| | | this.displayValue = e.fulldate + ' ' + e.time |
| | | } else { |
| | | this.displayValue = e.fulldate |
| | | } |
| | | this.setEmit(this.displayValue) |
| | | } |
| | | this.$refs.mobile.close() |
| | | }, |
| | | rangeChange(before, after) { |
| | | if (!(before && after)) return |
| | | this.handleStartAndEnd(before, after, true) |
| | | if (this.hasTime) return |
| | | this.confirmRangeChange() |
| | | }, |
| | | confirmRangeChange() { |
| | | if (!this.tempRange.startDate || !this.tempRange.endDate) { |
| | | this.pickerVisible = false |
| | | return |
| | | } |
| | | if(!checkDate(this.tempRange.startDate)){ |
| | | this.tempRange.startDate = getDate(Date.now()) |
| | | } |
| | | if(!checkDate(this.tempRange.endDate)){ |
| | | this.tempRange.endDate = getDate(Date.now()) |
| | | } |
| | | |
| | | let start, end |
| | | |
| | | let startDateLaterRangeStartDate = false |
| | | let startDateLaterRangeEndDate = false |
| | | let startDate, startTime |
| | | if(this.start) { |
| | | let startString = this.start |
| | | if(typeof this.start === 'number'){ |
| | | startString = getDateTime(this.start, this.hideSecond) |
| | | } |
| | | [startDate,startTime] = startString.split(' ') |
| | | if(this.start && !dateCompare(this.start, this.tempRange.startDate)) { |
| | | startDateLaterRangeStartDate = true |
| | | this.tempRange.startDate = startDate |
| | | } |
| | | if(this.start && !dateCompare(this.start, this.tempRange.endDate)) { |
| | | startDateLaterRangeEndDate = true |
| | | this.tempRange.endDate = startDate |
| | | } |
| | | } |
| | | let endDateEarlierRangeStartDate = false |
| | | let endDateEarlierRangeEndDate = false |
| | | let endDate, endTime |
| | | if(this.end) { |
| | | let endString = this.end |
| | | if(typeof this.end === 'number'){ |
| | | endString = getDateTime(this.end, this.hideSecond) |
| | | } |
| | | [endDate,endTime] = endString.split(' ') |
| | | |
| | | if(this.end && !dateCompare(this.tempRange.startDate, this.end)) { |
| | | endDateEarlierRangeStartDate = true |
| | | this.tempRange.startDate = endDate |
| | | } |
| | | if(this.end && !dateCompare(this.tempRange.endDate, this.end)) { |
| | | endDateEarlierRangeEndDate = true |
| | | this.tempRange.endDate = endDate |
| | | } |
| | | } |
| | | if (!this.hasTime) { |
| | | start = this.displayRangeValue.startDate = this.tempRange.startDate |
| | | end = this.displayRangeValue.endDate = this.tempRange.endDate |
| | | } else { |
| | | if(startDateLaterRangeStartDate){ |
| | | this.tempRange.startTime = startTime || getDefaultSecond(this.hideSecond) |
| | | }else if(endDateEarlierRangeStartDate){ |
| | | this.tempRange.startTime = endTime || getDefaultSecond(this.hideSecond) |
| | | } |
| | | if(!this.tempRange.startTime){ |
| | | this.tempRange.startTime = getTime(Date.now(), this.hideSecond) |
| | | } |
| | | |
| | | if(startDateLaterRangeEndDate){ |
| | | this.tempRange.endTime = startTime || getDefaultSecond(this.hideSecond) |
| | | }else if(endDateEarlierRangeEndDate){ |
| | | this.tempRange.endTime = endTime || getDefaultSecond(this.hideSecond) |
| | | } |
| | | if(!this.tempRange.endTime){ |
| | | this.tempRange.endTime = getTime(Date.now(), this.hideSecond) |
| | | } |
| | | start = this.displayRangeValue.startDate = `${this.tempRange.startDate} ${this.tempRange.startTime}` |
| | | end = this.displayRangeValue.endDate = `${this.tempRange.endDate} ${this.tempRange.endTime}` |
| | | } |
| | | if(!dateCompare(start,end)){ |
| | | [start, end] = [end, start] |
| | | } |
| | | this.displayRangeValue.startDate = start |
| | | this.displayRangeValue.endDate = end |
| | | const displayRange = [start, end] |
| | | this.setEmit(displayRange) |
| | | this.pickerVisible = false |
| | | }, |
| | | handleStartAndEnd(before, after, temp = false) { |
| | | if (!(before && after)) return |
| | | |
| | | const type = temp ? 'tempRange' : 'range' |
| | | const isStartEarlierEnd = dateCompare(before, after) |
| | | this[type].startDate = isStartEarlierEnd ? before : after |
| | | this[type].endDate = isStartEarlierEnd ? after : before |
| | | }, |
| | | /** |
| | | * 比较时间大小 |
| | | */ |
| | | dateCompare(startDate, endDate) { |
| | | // 计算截止时间 |
| | | startDate = new Date(startDate.replace('-', '/').replace('-', '/')) |
| | | // 计算详细项的截止时间 |
| | | endDate = new Date(endDate.replace('-', '/').replace('-', '/')) |
| | | return startDate <= endDate |
| | | }, |
| | | |
| | | /** |
| | | * 比较时间差 |
| | | */ |
| | | diffDate(startDate, endDate) { |
| | | // 计算截止时间 |
| | | startDate = new Date(startDate.replace('-', '/').replace('-', '/')) |
| | | // 计算详细项的截止时间 |
| | | endDate = new Date(endDate.replace('-', '/').replace('-', '/')) |
| | | const diff = (endDate - startDate) / (24 * 60 * 60 * 1000) |
| | | return Math.abs(diff) |
| | | }, |
| | | |
| | | clear(needEmit = true) { |
| | | if (!this.isRange) { |
| | | this.displayValue = '' |
| | | this.inputDate = '' |
| | | this.pickerTime = '' |
| | | if (this.isPhone) { |
| | | this.$refs.mobile && this.$refs.mobile.clearCalender() |
| | | } else { |
| | | this.$refs.pcSingle && this.$refs.pcSingle.clearCalender() |
| | | } |
| | | if (needEmit) { |
| | | this.$emit('change', '') |
| | | this.$emit('input', '') |
| | | this.$emit('update:modelValue', '') |
| | | } |
| | | } else { |
| | | this.displayRangeValue.startDate = '' |
| | | this.displayRangeValue.endDate = '' |
| | | this.tempRange.startDate = '' |
| | | this.tempRange.startTime = '' |
| | | this.tempRange.endDate = '' |
| | | this.tempRange.endTime = '' |
| | | if (this.isPhone) { |
| | | this.$refs.mobile && this.$refs.mobile.clearCalender() |
| | | } else { |
| | | this.$refs.left && this.$refs.left.clearCalender() |
| | | this.$refs.right && this.$refs.right.clearCalender() |
| | | this.$refs.right && this.$refs.right.changeMonth('next') |
| | | } |
| | | if (needEmit) { |
| | | this.$emit('change', []) |
| | | this.$emit('input', []) |
| | | this.$emit('update:modelValue', []) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-primary: #007aff !default; |
| | | |
| | | .uni-date { |
| | | width: 100%; |
| | | flex: 1; |
| | | } |
| | | .uni-date-x { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | border-radius: 4px; |
| | | background-color: #fff; |
| | | color: #666; |
| | | font-size: 14px; |
| | | flex: 1; |
| | | |
| | | .icon-calendar{ |
| | | padding-left: 3px; |
| | | } |
| | | .range-separator{ |
| | | height: 35px; |
| | | /* #ifndef MP */ |
| | | padding: 0 2px; |
| | | /* #endif */ |
| | | line-height: 35px; |
| | | } |
| | | } |
| | | |
| | | .uni-date-x--border { |
| | | box-sizing: border-box; |
| | | border-radius: 4px; |
| | | border: 1px solid #e5e5e5; |
| | | } |
| | | |
| | | .uni-date-editor--x { |
| | | display: flex; |
| | | align-items: center; |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-date-editor--x .uni-date__icon-clear { |
| | | padding-right: 3px; |
| | | display: flex; |
| | | align-items: center; |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-date__x-input { |
| | | width: auto; |
| | | height: 35px; |
| | | /* #ifndef MP */ |
| | | padding-left: 5px; |
| | | /* #endif */ |
| | | position: relative; |
| | | flex: 1; |
| | | line-height: 35px; |
| | | font-size: 14px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .text-center { |
| | | text-align: center; |
| | | } |
| | | |
| | | .uni-date__input { |
| | | height: 40px; |
| | | width: 100%; |
| | | line-height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .uni-date-range__input { |
| | | text-align: center; |
| | | max-width: 142px; |
| | | } |
| | | |
| | | .uni-date-picker__container { |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-date-mask--pc { |
| | | position: fixed; |
| | | bottom: 0px; |
| | | top: 0px; |
| | | left: 0px; |
| | | right: 0px; |
| | | background-color: rgba(0, 0, 0, 0); |
| | | transition-duration: 0.3s; |
| | | z-index: 996; |
| | | } |
| | | |
| | | .uni-date-single--x { |
| | | background-color: #fff; |
| | | position: absolute; |
| | | top: 0; |
| | | z-index: 999; |
| | | border: 1px solid #EBEEF5; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .uni-date-range--x { |
| | | background-color: #fff; |
| | | position: absolute; |
| | | top: 0; |
| | | z-index: 999; |
| | | border: 1px solid #EBEEF5; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .uni-date-editor--x__disabled { |
| | | opacity: 0.4; |
| | | cursor: default; |
| | | } |
| | | |
| | | .uni-date-editor--logo { |
| | | width: 16px; |
| | | height: 16px; |
| | | vertical-align: middle; |
| | | } |
| | | |
| | | /* 添加时间 */ |
| | | .popup-x-header { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .popup-x-header--datetime { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | flex: 1; |
| | | } |
| | | |
| | | .popup-x-body { |
| | | display: flex; |
| | | } |
| | | |
| | | .popup-x-footer { |
| | | padding: 0 15px; |
| | | border-top-color: #F1F1F1; |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | line-height: 40px; |
| | | text-align: right; |
| | | color: #666; |
| | | } |
| | | |
| | | .popup-x-footer text:hover { |
| | | color: $uni-primary; |
| | | cursor: pointer; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .popup-x-footer .confirm-text { |
| | | margin-left: 20px; |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .uni-date-changed { |
| | | text-align: center; |
| | | color: #333; |
| | | border-bottom-color: #F1F1F1; |
| | | border-bottom-style: solid; |
| | | border-bottom-width: 1px; |
| | | } |
| | | |
| | | .uni-date-changed--time text { |
| | | height: 50px; |
| | | line-height: 50px; |
| | | } |
| | | |
| | | .uni-date-changed .uni-date-changed--time { |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-date-changed--time-date { |
| | | color: #333; |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | .mr-50 { |
| | | margin-right: 50px; |
| | | } |
| | | |
| | | /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */ |
| | | .uni-popper__arrow, |
| | | .uni-popper__arrow::after { |
| | | position: absolute; |
| | | display: block; |
| | | width: 0; |
| | | height: 0; |
| | | border: 6px solid transparent; |
| | | border-top-width: 0; |
| | | } |
| | | |
| | | .uni-popper__arrow { |
| | | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
| | | top: -6px; |
| | | left: 10%; |
| | | margin-right: 3px; |
| | | border-bottom-color: #EBEEF5; |
| | | } |
| | | |
| | | .uni-popper__arrow::after { |
| | | content: " "; |
| | | top: 1px; |
| | | margin-left: -6px; |
| | | border-bottom-color: #fff; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | class Calendar { |
| | | constructor({ |
| | | selected, |
| | | startDate, |
| | | endDate, |
| | | range, |
| | | } = {}) { |
| | | // 当前日期 |
| | | this.date = this.getDateObj(new Date()) // 当前初入日期 |
| | | // 打点信息 |
| | | this.selected = selected || []; |
| | | // 起始时间 |
| | | this.startDate = startDate |
| | | // 终止时间 |
| | | this.endDate = endDate |
| | | // 是否范围选择 |
| | | this.range = range |
| | | // 多选状态 |
| | | this.cleanMultipleStatus() |
| | | // 每周日期 |
| | | this.weeks = {} |
| | | this.lastHover = false |
| | | } |
| | | /** |
| | | * 设置日期 |
| | | * @param {Object} date |
| | | */ |
| | | setDate(date) { |
| | | const selectDate = this.getDateObj(date) |
| | | this.getWeeks(selectDate.fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 清理多选状态 |
| | | */ |
| | | cleanMultipleStatus() { |
| | | this.multipleStatus = { |
| | | before: '', |
| | | after: '', |
| | | data: [] |
| | | } |
| | | } |
| | | |
| | | setStartDate(startDate) { |
| | | this.startDate = startDate |
| | | } |
| | | |
| | | setEndDate(endDate) { |
| | | this.endDate = endDate |
| | | } |
| | | |
| | | getPreMonthObj(date){ |
| | | date = fixIosDateFormat(date) |
| | | date = new Date(date) |
| | | |
| | | const oldMonth = date.getMonth() |
| | | date.setMonth(oldMonth - 1) |
| | | const newMonth = date.getMonth() |
| | | if(oldMonth !== 0 && newMonth - oldMonth === 0){ |
| | | date.setMonth(newMonth - 1) |
| | | } |
| | | return this.getDateObj(date) |
| | | } |
| | | getNextMonthObj(date){ |
| | | date = fixIosDateFormat(date) |
| | | date = new Date(date) |
| | | |
| | | const oldMonth = date.getMonth() |
| | | date.setMonth(oldMonth + 1) |
| | | const newMonth = date.getMonth() |
| | | if(newMonth - oldMonth > 1){ |
| | | date.setMonth(newMonth - 1) |
| | | } |
| | | return this.getDateObj(date) |
| | | } |
| | | |
| | | /** |
| | | * 获取指定格式Date对象 |
| | | */ |
| | | getDateObj(date) { |
| | | date = fixIosDateFormat(date) |
| | | date = new Date(date) |
| | | |
| | | return { |
| | | fullDate: getDate(date), |
| | | year: date.getFullYear(), |
| | | month: addZero(date.getMonth() + 1), |
| | | date: addZero(date.getDate()), |
| | | day: date.getDay() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取上一个月日期集合 |
| | | */ |
| | | getPreMonthDays(amount, dateObj) { |
| | | const result = [] |
| | | for (let i = amount - 1; i >= 0; i--) { |
| | | const month = dateObj.month - 1 |
| | | result.push({ |
| | | date: new Date(dateObj.year, month, -i).getDate(), |
| | | month, |
| | | disable: true |
| | | }) |
| | | } |
| | | return result |
| | | } |
| | | /** |
| | | * 获取本月日期集合 |
| | | */ |
| | | getCurrentMonthDays(amount, dateObj) { |
| | | const result = [] |
| | | const fullDate = this.date.fullDate |
| | | for (let i = 1; i <= amount; i++) { |
| | | const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}` |
| | | const isToday = fullDate === currentDate |
| | | // 获取打点信息 |
| | | const info = this.selected && this.selected.find((item) => { |
| | | if (this.dateEqual(currentDate, item.date)) { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | // 日期禁用 |
| | | let disableBefore = true |
| | | let disableAfter = true |
| | | if (this.startDate) { |
| | | disableBefore = dateCompare(this.startDate, currentDate) |
| | | } |
| | | |
| | | if (this.endDate) { |
| | | disableAfter = dateCompare(currentDate, this.endDate) |
| | | } |
| | | |
| | | let multiples = this.multipleStatus.data |
| | | let multiplesStatus = -1 |
| | | if (this.range && multiples) { |
| | | multiplesStatus = multiples.findIndex((item) => { |
| | | return this.dateEqual(item, currentDate) |
| | | }) |
| | | } |
| | | const checked = multiplesStatus !== -1 |
| | | |
| | | result.push({ |
| | | fullDate: currentDate, |
| | | year: dateObj.year, |
| | | date: i, |
| | | multiple: this.range ? checked : false, |
| | | beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after), |
| | | afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after), |
| | | month: dateObj.month, |
| | | disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)), |
| | | isToday, |
| | | userChecked: false, |
| | | extraInfo: info |
| | | }) |
| | | } |
| | | return result |
| | | } |
| | | /** |
| | | * 获取下一个月日期集合 |
| | | */ |
| | | _getNextMonthDays(amount, dateObj) { |
| | | const result = [] |
| | | const month = dateObj.month + 1 |
| | | for (let i = 1; i <= amount; i++) { |
| | | result.push({ |
| | | date: i, |
| | | month, |
| | | disable: true |
| | | }) |
| | | } |
| | | return result |
| | | } |
| | | |
| | | /** |
| | | * 获取当前日期详情 |
| | | * @param {Object} date |
| | | */ |
| | | getInfo(date) { |
| | | if (!date) { |
| | | date = new Date() |
| | | } |
| | | |
| | | return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 比较时间是否相等 |
| | | */ |
| | | dateEqual(before, after) { |
| | | before = new Date(fixIosDateFormat(before)) |
| | | after = new Date(fixIosDateFormat(after)) |
| | | return before.valueOf() === after.valueOf() |
| | | } |
| | | |
| | | /** |
| | | * 比较真实起始日期 |
| | | */ |
| | | |
| | | isLogicBefore(currentDate, before, after) { |
| | | let logicBefore = before |
| | | if (before && after) { |
| | | logicBefore = dateCompare(before, after) ? before : after |
| | | } |
| | | return this.dateEqual(logicBefore, currentDate) |
| | | } |
| | | |
| | | isLogicAfter(currentDate, before, after) { |
| | | let logicAfter = after |
| | | if (before && after) { |
| | | logicAfter = dateCompare(before, after) ? after : before |
| | | } |
| | | return this.dateEqual(logicAfter, currentDate) |
| | | } |
| | | |
| | | /** |
| | | * 获取日期范围内所有日期 |
| | | * @param {Object} begin |
| | | * @param {Object} end |
| | | */ |
| | | geDateAll(begin, end) { |
| | | var arr = [] |
| | | var ab = begin.split('-') |
| | | var ae = end.split('-') |
| | | var db = new Date() |
| | | db.setFullYear(ab[0], ab[1] - 1, ab[2]) |
| | | var de = new Date() |
| | | de.setFullYear(ae[0], ae[1] - 1, ae[2]) |
| | | var unixDb = db.getTime() - 24 * 60 * 60 * 1000 |
| | | var unixDe = de.getTime() - 24 * 60 * 60 * 1000 |
| | | for (var k = unixDb; k <= unixDe;) { |
| | | k = k + 24 * 60 * 60 * 1000 |
| | | arr.push(this.getDateObj(new Date(parseInt(k))).fullDate) |
| | | } |
| | | return arr |
| | | } |
| | | |
| | | /** |
| | | * 获取多选状态 |
| | | */ |
| | | setMultiple(fullDate) { |
| | | if (!this.range) return |
| | | |
| | | let { |
| | | before, |
| | | after |
| | | } = this.multipleStatus |
| | | if (before && after) { |
| | | if (!this.lastHover) { |
| | | this.lastHover = true |
| | | return |
| | | } |
| | | this.multipleStatus.before = fullDate |
| | | this.multipleStatus.after = '' |
| | | this.multipleStatus.data = [] |
| | | this.multipleStatus.fulldate = '' |
| | | this.lastHover = false |
| | | } else { |
| | | if (!before) { |
| | | this.multipleStatus.before = fullDate |
| | | this.lastHover = false |
| | | } else { |
| | | this.multipleStatus.after = fullDate |
| | | if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus |
| | | .after); |
| | | } else { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus |
| | | .before); |
| | | } |
| | | this.lastHover = true |
| | | } |
| | | } |
| | | this.getWeeks(fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 鼠标 hover 更新多选状态 |
| | | */ |
| | | setHoverMultiple(fullDate) { |
| | | if (!this.range || this.lastHover) return |
| | | |
| | | const { before } = this.multipleStatus |
| | | |
| | | if (!before) { |
| | | this.multipleStatus.before = fullDate |
| | | } else { |
| | | this.multipleStatus.after = fullDate |
| | | if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); |
| | | } else { |
| | | this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); |
| | | } |
| | | } |
| | | this.getWeeks(fullDate) |
| | | } |
| | | |
| | | /** |
| | | * 更新默认值多选状态 |
| | | */ |
| | | setDefaultMultiple(before, after) { |
| | | this.multipleStatus.before = before |
| | | this.multipleStatus.after = after |
| | | if (before && after) { |
| | | if (dateCompare(before, after)) { |
| | | this.multipleStatus.data = this.geDateAll(before, after); |
| | | this.getWeeks(after) |
| | | } else { |
| | | this.multipleStatus.data = this.geDateAll(after, before); |
| | | this.getWeeks(before) |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取每周数据 |
| | | * @param {Object} dateData |
| | | */ |
| | | getWeeks(dateData) { |
| | | const { |
| | | year, |
| | | month, |
| | | } = this.getDateObj(dateData) |
| | | |
| | | const preMonthDayAmount = new Date(year, month - 1, 1).getDay() |
| | | const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData)) |
| | | |
| | | const currentMonthDayAmount = new Date(year, month, 0).getDate() |
| | | const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData)) |
| | | |
| | | const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount |
| | | const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData)) |
| | | |
| | | const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays] |
| | | |
| | | const weeks = new Array(6) |
| | | for (let i = 0; i < calendarDays.length; i++) { |
| | | const index = Math.floor(i / 7) |
| | | if(!weeks[index]){ |
| | | weeks[index] = new Array(7) |
| | | } |
| | | weeks[index][i % 7] = calendarDays[i] |
| | | } |
| | | |
| | | this.calendar = calendarDays |
| | | this.weeks = weeks |
| | | } |
| | | } |
| | | |
| | | function getDateTime(date, hideSecond){ |
| | | return `${getDate(date)} ${getTime(date, hideSecond)}` |
| | | } |
| | | |
| | | function getDate(date) { |
| | | date = fixIosDateFormat(date) |
| | | date = new Date(date) |
| | | const year = date.getFullYear() |
| | | const month = date.getMonth()+1 |
| | | const day = date.getDate() |
| | | return `${year}-${addZero(month)}-${addZero(day)}` |
| | | } |
| | | |
| | | function getTime(date, hideSecond){ |
| | | date = fixIosDateFormat(date) |
| | | date = new Date(date) |
| | | const hour = date.getHours() |
| | | const minute = date.getMinutes() |
| | | const second = date.getSeconds() |
| | | return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}` |
| | | } |
| | | |
| | | function addZero(num) { |
| | | if(num < 10){ |
| | | num = `0${num}` |
| | | } |
| | | return num |
| | | } |
| | | |
| | | function getDefaultSecond(hideSecond) { |
| | | return hideSecond ? '00:00' : '00:00:00' |
| | | } |
| | | |
| | | function dateCompare(startDate, endDate) { |
| | | startDate = new Date(fixIosDateFormat(startDate)) |
| | | endDate = new Date(fixIosDateFormat(endDate)) |
| | | return startDate <= endDate |
| | | } |
| | | |
| | | function checkDate(date){ |
| | | const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g |
| | | return date.match(dateReg) |
| | | } |
| | | |
| | | const dateTimeReg = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])( [0-5][0-9]:[0-5][0-9]:[0-5][0-9])?$/ |
| | | function fixIosDateFormat(value) { |
| | | if (typeof value === 'string' && dateTimeReg.test(value)) { |
| | | value = value.replace(/-/g, '/') |
| | | } |
| | | return value |
| | | } |
| | | |
| | | export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat} |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-datetime-picker", |
| | | "displayName": "uni-datetime-picker 日期选择器", |
| | | "version": "2.2.22", |
| | | "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择", |
| | | "keywords": [ |
| | | "uni-datetime-picker", |
| | | "uni-ui", |
| | | "uniui", |
| | | "日期时间选择器", |
| | | "日期时间" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-icons" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "n" |
| | | }, |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | > `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护` |
| | | |
| | | ## DatetimePicker 时间选择器 |
| | | |
| | | > **组件名:uni-datetime-picker** |
| | | > 代码块: `uDatetimePicker` |
| | | |
| | | |
| | | 该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。 |
| | | |
| | | 若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。 |
| | | |
| | | **_点击 picker 默认值规则:_** |
| | | |
| | | - 若设置初始值 value, 会显示在 picker 显示框中 |
| | | - 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.2.1(2021-11-22) |
| | | - 修复 vue3中个别scss变量无法找到的问题 |
| | | ## 1.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer) |
| | | ## 1.1.1(2021-07-30) |
| | | - 优化 vue3下事件警告的问题 |
| | | ## 1.1.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.0.7(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.0.6(2021-02-04) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | // #ifdef H5 |
| | | export default { |
| | | name: 'Keypress', |
| | | props: { |
| | | disable: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | mounted () { |
| | | const keyNames = { |
| | | esc: ['Esc', 'Escape'], |
| | | tab: 'Tab', |
| | | enter: 'Enter', |
| | | space: [' ', 'Spacebar'], |
| | | up: ['Up', 'ArrowUp'], |
| | | left: ['Left', 'ArrowLeft'], |
| | | right: ['Right', 'ArrowRight'], |
| | | down: ['Down', 'ArrowDown'], |
| | | delete: ['Backspace', 'Delete', 'Del'] |
| | | } |
| | | const listener = ($event) => { |
| | | if (this.disable) { |
| | | return |
| | | } |
| | | const keyName = Object.keys(keyNames).find(key => { |
| | | const keyName = $event.key |
| | | const value = keyNames[key] |
| | | return value === keyName || (Array.isArray(value) && value.includes(keyName)) |
| | | }) |
| | | if (keyName) { |
| | | // 避免和其他按键事件冲突 |
| | | setTimeout(() => { |
| | | this.$emit(keyName, {}) |
| | | }, 0) |
| | | } |
| | | } |
| | | document.addEventListener('keyup', listener) |
| | | // this.$once('hook:beforeDestroy', () => { |
| | | // document.removeEventListener('keyup', listener) |
| | | // }) |
| | | }, |
| | | render: () => {} |
| | | } |
| | | // #endif |
对比新文件 |
| | |
| | | <template> |
| | | <view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear"> |
| | | <view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" /> |
| | | <view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}"> |
| | | <slot /> |
| | | </view> |
| | | <!-- #ifdef H5 --> |
| | | <keypress @esc="close('mask')" /> |
| | | <!-- #endif --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // #ifdef H5 |
| | | import keypress from './keypress.js' |
| | | // #endif |
| | | /** |
| | | * Drawer 抽屉 |
| | | * @description 抽屉侧滑菜单 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=26 |
| | | * @property {Boolean} mask = [true | false] 是否显示遮罩 |
| | | * @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭 |
| | | * @property {Boolean} mode = [left | right] Drawer 滑出位置 |
| | | * @value left 从左侧滑出 |
| | | * @value right 从右侧侧滑出 |
| | | * @property {Number} width 抽屉的宽度 ,仅 vue 页面生效 |
| | | * @event {Function} close 组件关闭时触发事件 |
| | | */ |
| | | export default { |
| | | name: 'UniDrawer', |
| | | components: { |
| | | // #ifdef H5 |
| | | keypress |
| | | // #endif |
| | | }, |
| | | emits:['change'], |
| | | props: { |
| | | /** |
| | | * 显示模式(左、右),只在初始化生效 |
| | | */ |
| | | mode: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | /** |
| | | * 蒙层显示状态 |
| | | */ |
| | | mask: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | /** |
| | | * 遮罩是否可点击关闭 |
| | | */ |
| | | maskClick:{ |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | /** |
| | | * 抽屉宽度 |
| | | */ |
| | | width: { |
| | | type: Number, |
| | | default: 220 |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | visibleSync: false, |
| | | showDrawer: false, |
| | | rightMode: false, |
| | | watchTimer: null, |
| | | drawerWidth: 220 |
| | | } |
| | | }, |
| | | created() { |
| | | // #ifndef APP-NVUE |
| | | this.drawerWidth = this.width |
| | | // #endif |
| | | this.rightMode = this.mode === 'right' |
| | | }, |
| | | methods: { |
| | | clear(){}, |
| | | close(type) { |
| | | // fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑 |
| | | if((type === 'mask' && !this.maskClick) || !this.visibleSync) return |
| | | this._change('showDrawer', 'visibleSync', false) |
| | | }, |
| | | open() { |
| | | // fixed by mehaotian 处理重复点击打开的事件 |
| | | if(this.visibleSync) return |
| | | this._change('visibleSync', 'showDrawer', true) |
| | | }, |
| | | _change(param1, param2, status) { |
| | | this[param1] = status |
| | | if (this.watchTimer) { |
| | | clearTimeout(this.watchTimer) |
| | | } |
| | | this.watchTimer = setTimeout(() => { |
| | | this[param2] = status |
| | | this.$emit('change',status) |
| | | }, status ? 50 : 300) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $uni-mask: rgba($color: #000000, $alpha: 0.4) ; |
| | | // 抽屉宽度 |
| | | $drawer-width: 220px; |
| | | |
| | | .uni-drawer { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | overflow: hidden; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .uni-drawer__content { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: absolute; |
| | | top: 0; |
| | | width: $drawer-width; |
| | | bottom: 0; |
| | | background-color: $uni-bg-color; |
| | | transition: transform 0.3s ease; |
| | | } |
| | | |
| | | .uni-drawer--left { |
| | | left: 0; |
| | | /* #ifdef APP-NVUE */ |
| | | transform: translateX(-$drawer-width); |
| | | /* #endif */ |
| | | /* #ifndef APP-NVUE */ |
| | | transform: translateX(-100%); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-drawer--right { |
| | | right: 0; |
| | | /* #ifdef APP-NVUE */ |
| | | transform: translateX($drawer-width); |
| | | /* #endif */ |
| | | /* #ifndef APP-NVUE */ |
| | | transform: translateX(100%); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-drawer__content--visible { |
| | | transform: translateX(0px); |
| | | } |
| | | |
| | | |
| | | .uni-drawer__mask { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | opacity: 0; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | bottom: 0; |
| | | right: 0; |
| | | background-color: $uni-mask; |
| | | transition: opacity 0.3s; |
| | | } |
| | | |
| | | .uni-drawer__mask--visible { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | opacity: 1; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-drawer", |
| | | "displayName": "uni-drawer 抽屉", |
| | | "version": "1.2.1", |
| | | "description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "drawer", |
| | | "抽屉", |
| | | "侧滑导航" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Drawer 抽屉 |
| | | > **组件名:uni-drawer** |
| | | > 代码块: `uDrawer` |
| | | |
| | | 抽屉侧滑菜单。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-drawer) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.1.9(2023-04-11) |
| | | - 修复 vue3 下 keyboardheightchange 事件报错的bug |
| | | ## 1.1.8(2023-03-29) |
| | | - 优化 trim 属性默认值 |
| | | ## 1.1.7(2023-03-29) |
| | | - 新增 cursor-spacing 属性 |
| | | ## 1.1.6(2023-01-28) |
| | | - 新增 keyboardheightchange 事件,可监听键盘高度变化 |
| | | ## 1.1.5(2022-11-29) |
| | | - 优化 主题样式 |
| | | ## 1.1.4(2022-10-27) |
| | | - 修复 props 中背景颜色无默认值的bug |
| | | ## 1.1.0(2022-06-30) |
| | | |
| | | - 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容 |
| | | - 新增 clear 事件,点击右侧叉号图标触发 |
| | | - 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发 |
| | | - 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等 |
| | | |
| | | ## 1.0.5(2022-06-07) |
| | | |
| | | - 优化 clearable 显示策略 |
| | | |
| | | ## 1.0.4(2022-06-07) |
| | | |
| | | - 优化 clearable 显示策略 |
| | | |
| | | ## 1.0.3(2022-05-20) |
| | | |
| | | - 修复 关闭图标某些情况下无法取消的 bug |
| | | |
| | | ## 1.0.2(2022-04-12) |
| | | |
| | | - 修复 默认值不生效的 bug |
| | | |
| | | ## 1.0.1(2022-04-02) |
| | | |
| | | - 修复 value 不能为 0 的 bug |
| | | |
| | | ## 1.0.0(2021-11-19) |
| | | |
| | | - 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput) |
| | | |
| | | ## 0.1.4(2021-08-20) |
| | | |
| | | - 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug |
| | | |
| | | ## 0.1.3(2021-08-11) |
| | | |
| | | - 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 |
| | | |
| | | ## 0.1.2(2021-07-30) |
| | | |
| | | - 优化 vue3 下事件警告的问题 |
| | | |
| | | ## 0.1.1 |
| | | |
| | | - 优化 errorMessage 属性支持 Boolean 类型 |
| | | |
| | | ## 0.1.0(2021-07-13) |
| | | |
| | | - 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | |
| | | ## 0.0.16(2021-06-29) |
| | | |
| | | - 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug |
| | | |
| | | ## 0.0.15(2021-06-21) |
| | | |
| | | - 修复 passwordIcon 属性拼写错误的 bug |
| | | |
| | | ## 0.0.14(2021-06-18) |
| | | |
| | | - 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标 |
| | | - 修复 confirmType 属性不生效的问题 |
| | | |
| | | ## 0.0.13(2021-06-04) |
| | | |
| | | - 修复 disabled 状态可清出内容的 bug |
| | | |
| | | ## 0.0.12(2021-05-12) |
| | | |
| | | - 新增 组件示例地址 |
| | | |
| | | ## 0.0.11(2021-05-07) |
| | | |
| | | - 修复 input-border 属性不生效的问题 |
| | | |
| | | ## 0.0.10(2021-04-30) |
| | | |
| | | - 修复 ios 遮挡文字、显示一半的问题 |
| | | |
| | | ## 0.0.9(2021-02-05) |
| | | |
| | | - 调整为 uni_modules 目录规范 |
| | | - 优化 兼容 nvue 页面 |
对比新文件 |
| | |
| | | /** |
| | | * @desc 函数防抖 |
| | | * @param func 目标函数 |
| | | * @param wait 延迟执行毫秒数 |
| | | * @param immediate true - 立即执行, false - 延迟执行 |
| | | */ |
| | | export const debounce = function(func, wait = 1000, immediate = true) { |
| | | let timer; |
| | | console.log(1); |
| | | return function() { |
| | | console.log(123); |
| | | let context = this, |
| | | args = arguments; |
| | | if (timer) clearTimeout(timer); |
| | | if (immediate) { |
| | | let callNow = !timer; |
| | | timer = setTimeout(() => { |
| | | timer = null; |
| | | }, wait); |
| | | if (callNow) func.apply(context, args); |
| | | } else { |
| | | timer = setTimeout(() => { |
| | | func.apply(context, args); |
| | | }, wait) |
| | | } |
| | | } |
| | | } |
| | | /** |
| | | * @desc 函数节流 |
| | | * @param func 函数 |
| | | * @param wait 延迟执行毫秒数 |
| | | * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发 |
| | | */ |
| | | export const throttle = (func, wait = 1000, type = 1) => { |
| | | let previous = 0; |
| | | let timeout; |
| | | return function() { |
| | | let context = this; |
| | | let args = arguments; |
| | | if (type === 1) { |
| | | let now = Date.now(); |
| | | |
| | | if (now - previous > wait) { |
| | | func.apply(context, args); |
| | | previous = now; |
| | | } |
| | | } else if (type === 2) { |
| | | if (!timeout) { |
| | | timeout = setTimeout(() => { |
| | | timeout = null; |
| | | func.apply(context, args) |
| | | }, wait) |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-easyinput" :class="{ 'uni-easyinput-error': msg }" :style="boxStyle"> |
| | | <view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle"> |
| | | <uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')" size="22"></uni-icons> |
| | | <textarea |
| | | v-if="type === 'textarea'" |
| | | class="uni-easyinput__content-textarea" |
| | | :class="{ 'input-padding': inputBorder }" |
| | | :name="name" |
| | | :value="val" |
| | | :placeholder="placeholder" |
| | | :placeholderStyle="placeholderStyle" |
| | | :disabled="disabled" |
| | | placeholder-class="uni-easyinput__placeholder-class" |
| | | :maxlength="inputMaxlength" |
| | | :focus="focused" |
| | | :autoHeight="autoHeight" |
| | | :cursor-spacing="cursorSpacing" |
| | | @input="onInput" |
| | | @blur="_Blur" |
| | | @focus="_Focus" |
| | | @confirm="onConfirm" |
| | | @keyboardheightchange="onkeyboardheightchange" |
| | | ></textarea> |
| | | <input |
| | | v-else |
| | | :type="type === 'password' ? 'text' : type" |
| | | class="uni-easyinput__content-input" |
| | | :style="inputStyle" |
| | | :name="name" |
| | | :value="val" |
| | | :password="!showPassword && type === 'password'" |
| | | :placeholder="placeholder" |
| | | :placeholderStyle="placeholderStyle" |
| | | placeholder-class="uni-easyinput__placeholder-class" |
| | | :disabled="disabled" |
| | | :maxlength="inputMaxlength" |
| | | :focus="focused" |
| | | :confirmType="confirmType" |
| | | :cursor-spacing="cursorSpacing" |
| | | @focus="_Focus" |
| | | @blur="_Blur" |
| | | @input="onInput" |
| | | @confirm="onConfirm" |
| | | @keyboardheightchange="onkeyboardheightchange" |
| | | /> |
| | | <template v-if="type === 'password' && passwordIcon"> |
| | | <!-- 开启密码时显示小眼睛 --> |
| | | <uni-icons |
| | | v-if="isVal" |
| | | class="content-clear-icon" |
| | | :class="{ 'is-textarea-icon': type === 'textarea' }" |
| | | :type="showPassword ? 'eye-slash-filled' : 'eye-filled'" |
| | | :size="22" |
| | | :color="focusShow ? primaryColor : '#c0c4cc'" |
| | | @click="onEyes" |
| | | ></uni-icons> |
| | | </template> |
| | | <template v-else-if="suffixIcon"> |
| | | <uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')" size="22"></uni-icons> |
| | | </template> |
| | | <template v-else> |
| | | <uni-icons |
| | | v-if="clearable && isVal && !disabled && type !== 'textarea'" |
| | | class="content-clear-icon" |
| | | :class="{ 'is-textarea-icon': type === 'textarea' }" |
| | | type="clear" |
| | | :size="clearSize" |
| | | :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'" |
| | | @click="onClear" |
| | | ></uni-icons> |
| | | </template> |
| | | <slot name="right"></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * Easyinput 输入框 |
| | | * @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=3455 |
| | | * @property {String} value 输入内容 |
| | | * @property {String } type 输入框的类型(默认text) password/text/textarea/.. |
| | | * @value text 文本输入键盘 |
| | | * @value textarea 多行文本输入键盘 |
| | | * @value password 密码输入键盘 |
| | | * @value number 数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式 |
| | | * @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序 |
| | | * @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持 |
| | | * @property {Boolean} clearable 是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true) |
| | | * @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认true) |
| | | * @property {String } placeholder 输入框的提示文字 |
| | | * @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd" |
| | | * @property {Boolean} focus 是否自动获得焦点(默认false) |
| | | * @property {Boolean} disabled 是否禁用(默认false) |
| | | * @property {Number } maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认140) |
| | | * @property {String } confirmType 设置键盘右下角按钮的文字,仅在type="text"时生效(默认done) |
| | | * @property {Number } clearSize 清除图标的大小,单位px(默认15) |
| | | * @property {String} prefixIcon 输入框头部图标 |
| | | * @property {String} suffixIcon 输入框尾部图标 |
| | | * @property {String} primaryColor 设置主题色(默认#2979ff) |
| | | * @property {Boolean} trim 是否自动去除两端的空格 |
| | | * @property {Boolean} cursorSpacing 指定光标与键盘的距离,单位 px |
| | | * @value both 去除两端空格 |
| | | * @value left 去除左侧空格 |
| | | * @value right 去除右侧空格 |
| | | * @value start 去除左侧空格 |
| | | * @value end 去除右侧空格 |
| | | * @value all 去除全部空格 |
| | | * @value none 不去除空格 |
| | | * @property {Boolean} inputBorder 是否显示input输入框的边框(默认true) |
| | | * @property {Boolean} passwordIcon type=password时是否显示小眼睛图标 |
| | | * @property {Object} styles 自定义颜色 |
| | | * @event {Function} input 输入框内容发生变化时触发 |
| | | * @event {Function} focus 输入框获得焦点时触发 |
| | | * @event {Function} blur 输入框失去焦点时触发 |
| | | * @event {Function} confirm 点击完成按钮时触发 |
| | | * @event {Function} iconClick 点击图标时触发 |
| | | * @example <uni-easyinput v-model="mobile"></uni-easyinput> |
| | | */ |
| | | function obj2strClass(obj) { |
| | | let classess = ''; |
| | | for (let key in obj) { |
| | | const val = obj[key]; |
| | | if (val) { |
| | | classess += `${key} `; |
| | | } |
| | | } |
| | | return classess; |
| | | } |
| | | |
| | | function obj2strStyle(obj) { |
| | | let style = ''; |
| | | for (let key in obj) { |
| | | const val = obj[key]; |
| | | style += `${key}:${val};`; |
| | | } |
| | | return style; |
| | | } |
| | | export default { |
| | | name: 'uni-easyinput', |
| | | emits: ['click', 'iconClick', 'update:modelValue', 'input', 'focus', 'blur', 'confirm', 'clear', 'eyes', 'change', 'keyboardheightchange'], |
| | | model: { |
| | | prop: 'modelValue', |
| | | event: 'update:modelValue' |
| | | }, |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | inject: { |
| | | form: { |
| | | from: 'uniForm', |
| | | default: null |
| | | }, |
| | | formItem: { |
| | | from: 'uniFormItem', |
| | | default: null |
| | | } |
| | | }, |
| | | props: { |
| | | name: String, |
| | | value: [Number, String], |
| | | modelValue: [Number, String], |
| | | type: { |
| | | type: String, |
| | | default: 'text' |
| | | }, |
| | | clearable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | autoHeight: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: ' ' |
| | | }, |
| | | placeholderStyle: String, |
| | | focus: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | maxlength: { |
| | | type: [Number, String], |
| | | default: 140 |
| | | }, |
| | | confirmType: { |
| | | type: String, |
| | | default: 'done' |
| | | }, |
| | | clearSize: { |
| | | type: [Number, String], |
| | | default: 24 |
| | | }, |
| | | inputBorder: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | prefixIcon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | suffixIcon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | trim: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | cursorSpacing: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | passwordIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | primaryColor: { |
| | | type: String, |
| | | default: '#2979ff' |
| | | }, |
| | | styles: { |
| | | type: Object, |
| | | default() { |
| | | return { |
| | | color: '#333', |
| | | backgroundColor: '#fff', |
| | | disableColor: '#F7F6F6', |
| | | borderColor: '#e5e5e5' |
| | | }; |
| | | } |
| | | }, |
| | | errorMessage: { |
| | | type: [String, Boolean], |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | focused: false, |
| | | val: '', |
| | | showMsg: '', |
| | | border: false, |
| | | isFirstBorder: false, |
| | | showClearIcon: false, |
| | | showPassword: false, |
| | | focusShow: false, |
| | | localMsg: '', |
| | | isEnter: false // 用于判断当前是否是使用回车操作 |
| | | }; |
| | | }, |
| | | computed: { |
| | | // 输入框内是否有值 |
| | | isVal() { |
| | | const val = this.val; |
| | | // fixed by mehaotian 处理值为0的情况,字符串0不在处理范围 |
| | | if (val || val === 0) { |
| | | return true; |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | msg() { |
| | | // console.log('computed', this.form, this.formItem); |
| | | // if (this.form) { |
| | | // return this.errorMessage || this.formItem.errMsg; |
| | | // } |
| | | // TODO 处理头条 formItem 中 errMsg 不更新的问题 |
| | | return this.localMsg || this.errorMessage; |
| | | }, |
| | | // 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值 |
| | | inputMaxlength() { |
| | | return Number(this.maxlength); |
| | | }, |
| | | |
| | | // 处理外层样式的style |
| | | boxStyle() { |
| | | return `color:${this.inputBorder && this.msg ? '#e43d33' : this.styles.color};`; |
| | | }, |
| | | // input 内容的类和样式处理 |
| | | inputContentClass() { |
| | | return obj2strClass({ |
| | | 'is-input-border': this.inputBorder, |
| | | 'is-input-error-border': this.inputBorder && this.msg, |
| | | 'is-textarea': this.type === 'textarea', |
| | | 'is-disabled': this.disabled, |
| | | 'is-focused': this.focusShow |
| | | }); |
| | | }, |
| | | inputContentStyle() { |
| | | const focusColor = this.focusShow ? this.primaryColor : this.styles.borderColor; |
| | | const borderColor = this.inputBorder && this.msg ? '#dd524d' : focusColor; |
| | | return obj2strStyle({ |
| | | 'border-color': borderColor || '#e5e5e5', |
| | | 'background-color': this.disabled ? this.styles.disableColor : this.styles.backgroundColor |
| | | }); |
| | | }, |
| | | // input右侧样式 |
| | | inputStyle() { |
| | | const paddingRight = this.type === 'password' || this.clearable || this.prefixIcon ? '' : '10px'; |
| | | return obj2strStyle({ |
| | | 'padding-right': paddingRight, |
| | | 'padding-left': this.prefixIcon ? '' : '10px' |
| | | }); |
| | | } |
| | | }, |
| | | watch: { |
| | | value(newVal) { |
| | | this.val = newVal; |
| | | }, |
| | | modelValue(newVal) { |
| | | this.val = newVal; |
| | | }, |
| | | focus(newVal) { |
| | | this.$nextTick(() => { |
| | | this.focused = this.focus; |
| | | this.focusShow = this.focus; |
| | | }); |
| | | } |
| | | }, |
| | | created() { |
| | | this.init(); |
| | | // TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg) |
| | | if (this.form && this.formItem) { |
| | | this.$watch('formItem.errMsg', newVal => { |
| | | this.localMsg = newVal; |
| | | }); |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.focused = this.focus; |
| | | this.focusShow = this.focus; |
| | | }); |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 初始化变量值 |
| | | */ |
| | | init() { |
| | | if (this.value || this.value === 0) { |
| | | this.val = this.value; |
| | | } else if (this.modelValue || this.modelValue === 0 || this.modelValue === '') { |
| | | this.val = this.modelValue; |
| | | } else { |
| | | this.val = null; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 点击图标时触发 |
| | | * @param {Object} type |
| | | */ |
| | | onClickIcon(type) { |
| | | this.$emit('iconClick', type); |
| | | }, |
| | | |
| | | /** |
| | | * 显示隐藏内容,密码框时生效 |
| | | */ |
| | | onEyes() { |
| | | this.showPassword = !this.showPassword; |
| | | this.$emit('eyes', this.showPassword); |
| | | }, |
| | | |
| | | /** |
| | | * 输入时触发 |
| | | * @param {Object} event |
| | | */ |
| | | onInput(event) { |
| | | let value = event.detail.value; |
| | | // 判断是否去除空格 |
| | | if (this.trim) { |
| | | if (typeof this.trim === 'boolean' && this.trim) { |
| | | value = this.trimStr(value); |
| | | } |
| | | if (typeof this.trim === 'string') { |
| | | value = this.trimStr(value, this.trim); |
| | | } |
| | | } |
| | | if (this.errMsg) this.errMsg = ''; |
| | | this.val = value; |
| | | // TODO 兼容 vue2 |
| | | this.$emit('input', value); |
| | | // TODO 兼容 vue3 |
| | | this.$emit('update:modelValue', value); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 获取焦点时触发 |
| | | * @param {Object} event |
| | | */ |
| | | onFocus() { |
| | | this.$nextTick(() => { |
| | | this.focused = true; |
| | | }); |
| | | this.$emit('focus', null); |
| | | }, |
| | | |
| | | _Focus(event) { |
| | | this.focusShow = true; |
| | | this.$emit('focus', event); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 失去焦点时触发 |
| | | * @param {Object} event |
| | | */ |
| | | onBlur() { |
| | | this.focused = false; |
| | | this.$emit('focus', null); |
| | | }, |
| | | _Blur(event) { |
| | | let value = event.detail.value; |
| | | this.focusShow = false; |
| | | this.$emit('blur', event); |
| | | // 根据类型返回值,在event中获取的值理论上讲都是string |
| | | if (this.isEnter === false) { |
| | | this.$emit('change', this.val); |
| | | } |
| | | // 失去焦点时参与表单校验 |
| | | if (this.form && this.formItem) { |
| | | const { validateTrigger } = this.form; |
| | | if (validateTrigger === 'blur') { |
| | | this.formItem.onFieldChange(); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 按下键盘的发送键 |
| | | * @param {Object} e |
| | | */ |
| | | onConfirm(e) { |
| | | this.$emit('confirm', this.val); |
| | | this.isEnter = true; |
| | | this.$emit('change', this.val); |
| | | this.$nextTick(() => { |
| | | this.isEnter = false; |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 清理内容 |
| | | * @param {Object} event |
| | | */ |
| | | onClear(event) { |
| | | this.val = ''; |
| | | // TODO 兼容 vue2 |
| | | this.$emit('input', ''); |
| | | // TODO 兼容 vue2 |
| | | // TODO 兼容 vue3 |
| | | this.$emit('update:modelValue', ''); |
| | | // 点击叉号触发 |
| | | this.$emit('clear'); |
| | | }, |
| | | |
| | | /** |
| | | * 键盘高度发生变化的时候触发此事件 |
| | | * 兼容性:微信小程序2.7.0+、App 3.1.0+ |
| | | * @param {Object} event |
| | | */ |
| | | onkeyboardheightchange(event) { |
| | | this.$emit("keyboardheightchange",event); |
| | | }, |
| | | |
| | | /** |
| | | * 去除空格 |
| | | */ |
| | | trimStr(str, pos = 'both') { |
| | | if (pos === 'both') { |
| | | return str.trim(); |
| | | } else if (pos === 'left') { |
| | | return str.trimLeft(); |
| | | } else if (pos === 'right') { |
| | | return str.trimRight(); |
| | | } else if (pos === 'start') { |
| | | return str.trimStart(); |
| | | } else if (pos === 'end') { |
| | | return str.trimEnd(); |
| | | } else if (pos === 'all') { |
| | | return str.replace(/\s+/g, ''); |
| | | } else if (pos === 'none') { |
| | | return str; |
| | | } |
| | | return str; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | $uni-error: #e43d33; |
| | | $uni-border-1: #dcdfe6 !default; |
| | | |
| | | .uni-easyinput { |
| | | /* #ifndef APP-NVUE */ |
| | | width: 100%; |
| | | /* #endif */ |
| | | flex: 1; |
| | | position: relative; |
| | | text-align: left; |
| | | color: #333; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .uni-easyinput__content { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | width: 100%; |
| | | display: flex; |
| | | box-sizing: border-box; |
| | | // min-height: 36px; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | // 处理border动画刚开始显示黑色的问题 |
| | | border-color: #fff; |
| | | transition-property: border-color; |
| | | transition-duration: 0.3s; |
| | | } |
| | | |
| | | .uni-easyinput__content-input { |
| | | /* #ifndef APP-NVUE */ |
| | | width: auto; |
| | | /* #endif */ |
| | | position: relative; |
| | | overflow: hidden; |
| | | flex: 1; |
| | | line-height: 1; |
| | | font-size: 14px; |
| | | height: 35px; |
| | | // min-height: 36px; |
| | | } |
| | | |
| | | .uni-easyinput__placeholder-class { |
| | | color: #999; |
| | | font-size: 12px; |
| | | // font-weight: 200; |
| | | } |
| | | |
| | | .is-textarea { |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .is-textarea-icon { |
| | | margin-top: 5px; |
| | | } |
| | | |
| | | .uni-easyinput__content-textarea { |
| | | position: relative; |
| | | overflow: hidden; |
| | | flex: 1; |
| | | line-height: 1.5; |
| | | font-size: 14px; |
| | | margin: 6px; |
| | | margin-left: 0; |
| | | height: 80px; |
| | | min-height: 80px; |
| | | /* #ifndef APP-NVUE */ |
| | | min-height: 80px; |
| | | width: auto; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .input-padding { |
| | | padding-left: 10px; |
| | | } |
| | | |
| | | .content-clear-icon { |
| | | padding: 0 5px; |
| | | } |
| | | |
| | | .label-icon { |
| | | margin-right: 5px; |
| | | margin-top: -1px; |
| | | } |
| | | |
| | | // 显示边框 |
| | | .is-input-border { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | border: 1px solid $uni-border-1; |
| | | border-radius: 4px; |
| | | /* #ifdef MP-ALIPAY */ |
| | | overflow: hidden; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-error-message { |
| | | position: absolute; |
| | | bottom: -17px; |
| | | left: 0; |
| | | line-height: 12px; |
| | | color: $uni-error; |
| | | font-size: 12px; |
| | | text-align: left; |
| | | } |
| | | |
| | | .uni-error-msg--boeder { |
| | | position: relative; |
| | | bottom: 0; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .is-input-error-border { |
| | | border-color: $uni-error; |
| | | |
| | | .uni-easyinput__placeholder-class { |
| | | color: mix(#fff, $uni-error, 50%); |
| | | } |
| | | } |
| | | |
| | | .uni-easyinput--border { |
| | | margin-bottom: 0; |
| | | padding: 10px 15px; |
| | | // padding-bottom: 0; |
| | | border-top: 1px #eee solid; |
| | | } |
| | | |
| | | .uni-easyinput-error { |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | .is-first-border { |
| | | /* #ifndef APP-NVUE */ |
| | | border: none; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | border-width: 0; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .is-disabled { |
| | | background-color: #f7f6f6; |
| | | color: #d5d5d5; |
| | | |
| | | .uni-easyinput__placeholder-class { |
| | | color: #d5d5d5; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-easyinput", |
| | | "displayName": "uni-easyinput 增强输入框", |
| | | "version": "1.1.9", |
| | | "description": "Easyinput 组件是对原生input组件的增强", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "input", |
| | | "uni-easyinput", |
| | | "输入框" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-icons" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ### Easyinput 增强输入框 |
| | | > **组件名:uni-easyinput** |
| | | > 代码块: `uEasyinput` |
| | | |
| | | |
| | | easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.2.5(2023-03-29) |
| | | - 新增 pattern.icon 属性,可自定义图标 |
| | | ## 1.2.4(2022-09-07) |
| | | 小程序端由于 style 使用了对象导致报错,[详情](https://ask.dcloud.net.cn/question/152790?item_id=211778&rf=false) |
| | | ## 1.2.3(2022-09-05) |
| | | - 修复 nvue 环境下,具有 tabBar 时,fab 组件下部位置无法正常获取 --window-bottom 的bug,详见:[https://ask.dcloud.net.cn/question/110638?notification_id=826310](https://ask.dcloud.net.cn/question/110638?notification_id=826310) |
| | | ## 1.2.2(2021-12-29) |
| | | - 更新 组件依赖 |
| | | ## 1.2.1(2021-11-19) |
| | | - 修复 阴影颜色不正确的bug |
| | | ## 1.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fab](https://uniapp.dcloud.io/component/uniui/uni-fab) |
| | | ## 1.1.1(2021-11-09) |
| | | - 新增 提供组件设计资源,组件样式调整 |
| | | ## 1.1.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.0.7(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.0.6(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
| | | - 优化 按钮背景色调整 |
| | | - 优化 兼容pc端 |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-cursor-point"> |
| | | <view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop) && content.length > 0" :class="{ |
| | | 'uni-fab--leftBottom': leftBottom, |
| | | 'uni-fab--rightBottom': rightBottom, |
| | | 'uni-fab--leftTop': leftTop, |
| | | 'uni-fab--rightTop': rightTop |
| | | }" class="uni-fab" |
| | | :style="nvueBottom" |
| | | > |
| | | <view :class="{ |
| | | 'uni-fab__content--left': horizontal === 'left', |
| | | 'uni-fab__content--right': horizontal === 'right', |
| | | 'uni-fab__content--flexDirection': direction === 'vertical', |
| | | 'uni-fab__content--flexDirectionStart': flexDirectionStart, |
| | | 'uni-fab__content--flexDirectionEnd': flexDirectionEnd, |
| | | 'uni-fab__content--other-platform': !isAndroidNvue |
| | | }" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }" |
| | | class="uni-fab__content" elevation="5"> |
| | | <view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" /> |
| | | <view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }" |
| | | class="uni-fab__item" @click="_onItemClick(index, item)"> |
| | | <image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image" |
| | | mode="aspectFit" /> |
| | | <text class="uni-fab__item-text" |
| | | :style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text> |
| | | </view> |
| | | <view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" /> |
| | | </view> |
| | | </view> |
| | | <view :class="{ |
| | | 'uni-fab__circle--leftBottom': leftBottom, |
| | | 'uni-fab__circle--rightBottom': rightBottom, |
| | | 'uni-fab__circle--leftTop': leftTop, |
| | | 'uni-fab__circle--rightTop': rightTop, |
| | | 'uni-fab__content--other-platform': !isAndroidNvue |
| | | }" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick"> |
| | | <uni-icons class="fab-circle-icon" :type="styles.icon" :color="styles.iconColor" size="32" |
| | | :class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons> |
| | | <!-- <view class="fab-circle-v" :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view> |
| | | <view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view> --> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | let platform = 'other' |
| | | // #ifdef APP-NVUE |
| | | platform = uni.getSystemInfoSync().platform |
| | | // #endif |
| | | |
| | | /** |
| | | * Fab 悬浮按钮 |
| | | * @description 点击可展开一个图形按钮菜单 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=144 |
| | | * @property {Object} pattern 可选样式配置项 |
| | | * @property {Object} horizontal = [left | right] 水平对齐方式 |
| | | * @value left 左对齐 |
| | | * @value right 右对齐 |
| | | * @property {Object} vertical = [bottom | top] 垂直对齐方式 |
| | | * @value bottom 下对齐 |
| | | * @value top 上对齐 |
| | | * @property {Object} direction = [horizontal | vertical] 展开菜单显示方式 |
| | | * @value horizontal 水平显示 |
| | | * @value vertical 垂直显示 |
| | | * @property {Array} content 展开菜单内容配置项 |
| | | * @property {Boolean} popMenu 是否使用弹出菜单 |
| | | * @event {Function} trigger 展开菜单点击事件,返回点击信息 |
| | | * @event {Function} fabClick 悬浮按钮点击事件 |
| | | */ |
| | | export default { |
| | | name: 'UniFab', |
| | | emits: ['fabClick', 'trigger'], |
| | | props: { |
| | | pattern: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | horizontal: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | vertical: { |
| | | type: String, |
| | | default: 'bottom' |
| | | }, |
| | | direction: { |
| | | type: String, |
| | | default: 'horizontal' |
| | | }, |
| | | content: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | show: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | popMenu: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | fabShow: false, |
| | | isShow: false, |
| | | isAndroidNvue: platform === 'android', |
| | | styles: { |
| | | color: '#3c3e49', |
| | | selectedColor: '#007AFF', |
| | | backgroundColor: '#fff', |
| | | buttonColor: '#007AFF', |
| | | iconColor: '#fff', |
| | | icon: 'plusempty' |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | contentWidth(e) { |
| | | return (this.content.length + 1) * 55 + 15 + 'px' |
| | | }, |
| | | contentWidthMin() { |
| | | return '55px' |
| | | }, |
| | | // 动态计算宽度 |
| | | boxWidth() { |
| | | return this.getPosition(3, 'horizontal') |
| | | }, |
| | | // 动态计算高度 |
| | | boxHeight() { |
| | | return this.getPosition(3, 'vertical') |
| | | }, |
| | | // 计算左下位置 |
| | | leftBottom() { |
| | | return this.getPosition(0, 'left', 'bottom') |
| | | }, |
| | | // 计算右下位置 |
| | | rightBottom() { |
| | | return this.getPosition(0, 'right', 'bottom') |
| | | }, |
| | | // 计算左上位置 |
| | | leftTop() { |
| | | return this.getPosition(0, 'left', 'top') |
| | | }, |
| | | rightTop() { |
| | | return this.getPosition(0, 'right', 'top') |
| | | }, |
| | | flexDirectionStart() { |
| | | return this.getPosition(1, 'vertical', 'top') |
| | | }, |
| | | flexDirectionEnd() { |
| | | return this.getPosition(1, 'vertical', 'bottom') |
| | | }, |
| | | horizontalLeft() { |
| | | return this.getPosition(2, 'horizontal', 'left') |
| | | }, |
| | | horizontalRight() { |
| | | return this.getPosition(2, 'horizontal', 'right') |
| | | }, |
| | | // 计算 nvue bottom |
| | | nvueBottom() { |
| | | const safeBottom = uni.getSystemInfoSync().windowBottom; |
| | | // #ifdef APP-NVUE |
| | | return 30 + safeBottom |
| | | // #endif |
| | | // #ifndef APP-NVUE |
| | | return 30 |
| | | // #endif |
| | | } |
| | | }, |
| | | watch: { |
| | | pattern: { |
| | | handler(val, oldVal) { |
| | | this.styles = Object.assign({}, this.styles, val) |
| | | }, |
| | | deep: true |
| | | } |
| | | }, |
| | | created() { |
| | | this.isShow = this.show |
| | | if (this.top === 0) { |
| | | this.fabShow = true |
| | | } |
| | | // 初始化样式 |
| | | this.styles = Object.assign({}, this.styles, this.pattern) |
| | | }, |
| | | methods: { |
| | | _onClick() { |
| | | this.$emit('fabClick') |
| | | if (!this.popMenu) { |
| | | return |
| | | } |
| | | this.isShow = !this.isShow |
| | | }, |
| | | open() { |
| | | this.isShow = true |
| | | }, |
| | | close() { |
| | | this.isShow = false |
| | | }, |
| | | /** |
| | | * 按钮点击事件 |
| | | */ |
| | | _onItemClick(index, item) { |
| | | if (!this.isShow) { |
| | | return |
| | | } |
| | | this.$emit('trigger', { |
| | | index, |
| | | item |
| | | }) |
| | | }, |
| | | /** |
| | | * 获取 位置信息 |
| | | */ |
| | | getPosition(types, paramA, paramB) { |
| | | if (types === 0) { |
| | | return this.horizontal === paramA && this.vertical === paramB |
| | | } else if (types === 1) { |
| | | return this.direction === paramA && this.vertical === paramB |
| | | } else if (types === 2) { |
| | | return this.direction === paramA && this.horizontal === paramB |
| | | } else { |
| | | return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $uni-shadow-base:0 1px 5px 2px rgba($color: #000000, $alpha: 0.3) !default; |
| | | |
| | | .uni-fab { |
| | | position: fixed; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | z-index: 10; |
| | | border-radius: 45px; |
| | | box-shadow: $uni-shadow-base; |
| | | } |
| | | |
| | | .uni-cursor-point { |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fab--active { |
| | | opacity: 1; |
| | | } |
| | | |
| | | .uni-fab--leftBottom { |
| | | left: 15px; |
| | | bottom: 30px; |
| | | /* #ifdef H5 */ |
| | | left: calc(15px + var(--window-left)); |
| | | bottom: calc(30px + var(--window-bottom)); |
| | | /* #endif */ |
| | | // padding: 10px; |
| | | } |
| | | |
| | | .uni-fab--leftTop { |
| | | left: 15px; |
| | | top: 30px; |
| | | /* #ifdef H5 */ |
| | | left: calc(15px + var(--window-left)); |
| | | top: calc(30px + var(--window-top)); |
| | | /* #endif */ |
| | | // padding: 10px; |
| | | } |
| | | |
| | | .uni-fab--rightBottom { |
| | | right: 15px; |
| | | bottom: 30px; |
| | | /* #ifdef H5 */ |
| | | right: calc(15px + var(--window-right)); |
| | | bottom: calc(30px + var(--window-bottom)); |
| | | /* #endif */ |
| | | // padding: 10px; |
| | | } |
| | | |
| | | .uni-fab--rightTop { |
| | | right: 15px; |
| | | top: 30px; |
| | | /* #ifdef H5 */ |
| | | right: calc(15px + var(--window-right)); |
| | | top: calc(30px + var(--window-top)); |
| | | /* #endif */ |
| | | // padding: 10px; |
| | | } |
| | | |
| | | .uni-fab__circle { |
| | | position: fixed; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 55px; |
| | | height: 55px; |
| | | background-color: #3c3e49; |
| | | border-radius: 45px; |
| | | z-index: 11; |
| | | // box-shadow: $uni-shadow-base; |
| | | } |
| | | |
| | | .uni-fab__circle--leftBottom { |
| | | left: 15px; |
| | | bottom: 30px; |
| | | /* #ifdef H5 */ |
| | | left: calc(15px + var(--window-left)); |
| | | bottom: calc(30px + var(--window-bottom)); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fab__circle--leftTop { |
| | | left: 15px; |
| | | top: 30px; |
| | | /* #ifdef H5 */ |
| | | left: calc(15px + var(--window-left)); |
| | | top: calc(30px + var(--window-top)); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fab__circle--rightBottom { |
| | | right: 15px; |
| | | bottom: 30px; |
| | | /* #ifdef H5 */ |
| | | right: calc(15px + var(--window-right)); |
| | | bottom: calc(30px + var(--window-bottom)); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fab__circle--rightTop { |
| | | right: 15px; |
| | | top: 30px; |
| | | /* #ifdef H5 */ |
| | | right: calc(15px + var(--window-right)); |
| | | top: calc(30px + var(--window-top)); |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fab__circle--left { |
| | | left: 0; |
| | | } |
| | | |
| | | .uni-fab__circle--right { |
| | | right: 0; |
| | | } |
| | | |
| | | .uni-fab__circle--top { |
| | | top: 0; |
| | | } |
| | | |
| | | .uni-fab__circle--bottom { |
| | | bottom: 0; |
| | | } |
| | | |
| | | .uni-fab__plus { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | // .fab-circle-v { |
| | | // position: absolute; |
| | | // width: 2px; |
| | | // height: 24px; |
| | | // left: 0; |
| | | // top: 0; |
| | | // right: 0; |
| | | // bottom: 0; |
| | | // /* #ifndef APP-NVUE */ |
| | | // margin: auto; |
| | | // /* #endif */ |
| | | // background-color: white; |
| | | // transform: rotate(0deg); |
| | | // transition: transform 0.3s; |
| | | // } |
| | | |
| | | // .fab-circle-h { |
| | | // position: absolute; |
| | | // width: 24px; |
| | | // height: 2px; |
| | | // left: 0; |
| | | // top: 0; |
| | | // right: 0; |
| | | // bottom: 0; |
| | | // /* #ifndef APP-NVUE */ |
| | | // margin: auto; |
| | | // /* #endif */ |
| | | // background-color: white; |
| | | // transform: rotate(0deg); |
| | | // transition: transform 0.3s; |
| | | // } |
| | | |
| | | .fab-circle-icon { |
| | | transform: rotate(0deg); |
| | | transition: transform 0.3s; |
| | | font-weight: 200; |
| | | } |
| | | |
| | | .uni-fab__plus--active { |
| | | transform: rotate(135deg); |
| | | } |
| | | |
| | | .uni-fab__content { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | border-radius: 55px; |
| | | overflow: hidden; |
| | | transition-property: width, height; |
| | | transition-duration: 0.2s; |
| | | width: 55px; |
| | | border-color: #DDDDDD; |
| | | border-width: 1rpx; |
| | | border-style: solid; |
| | | } |
| | | |
| | | .uni-fab__content--other-platform { |
| | | border-width: 0px; |
| | | box-shadow: $uni-shadow-base; |
| | | } |
| | | |
| | | .uni-fab__content--left { |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .uni-fab__content--right { |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .uni-fab__content--flexDirection { |
| | | flex-direction: column; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .uni-fab__content--flexDirectionStart { |
| | | flex-direction: column; |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .uni-fab__content--flexDirectionEnd { |
| | | flex-direction: column; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .uni-fab__item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 55px; |
| | | height: 55px; |
| | | opacity: 0; |
| | | transition: opacity 0.2s; |
| | | } |
| | | |
| | | .uni-fab__item--active { |
| | | opacity: 1; |
| | | } |
| | | |
| | | .uni-fab__item-image { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .uni-fab__item-text { |
| | | color: #FFFFFF; |
| | | font-size: 12px; |
| | | line-height: 12px; |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .uni-fab__item--first { |
| | | width: 55px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-fab", |
| | | "displayName": "uni-fab 悬浮按钮", |
| | | "version": "1.2.5", |
| | | "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "按钮", |
| | | "悬浮按钮", |
| | | "fab" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss","uni-icons"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | ## Fab 悬浮按钮 |
| | | > **组件名:uni-fab** |
| | | > 代码块: `uFab` |
| | | |
| | | |
| | | 点击可展开一个图形按钮菜单 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fab) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.2.1(2022-05-30) |
| | | - 新增 stat 属性 ,是否开启uni统计功能 |
| | | ## 1.2.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fav](https://uniapp.dcloud.io/component/uniui/uni-fav) |
| | | ## 1.1.1(2021-08-24) |
| | | - 新增 支持国际化 |
| | | ## 1.1.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.0.6(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.0.5(2021-04-21) |
| | | - 优化 添加依赖 uni-icons, 导入后自动下载依赖 |
| | | ## 1.0.4(2021-02-05) |
| | | - 优化 组件引用关系,通过uni_modules引用组件 |
| | | ## 1.0.3(2021-02-05) |
| | | - 优化 组件引用关系,通过uni_modules引用组件 |
| | | ## 1.0.2(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
对比新文件 |
| | |
| | | { |
| | | "uni-fav.collect": "collect", |
| | | "uni-fav.collected": "collected" |
| | | } |
对比新文件 |
| | |
| | | import en from './en.json' |
| | | import zhHans from './zh-Hans.json' |
| | | import zhHant from './zh-Hant.json' |
| | | export default { |
| | | en, |
| | | 'zh-Hans': zhHans, |
| | | 'zh-Hant': zhHant |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-fav.collect": "收藏", |
| | | "uni-fav.collected": "已收藏" |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "uni-fav.collect": "收藏", |
| | | "uni-fav.collected": "已收藏" |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view :class="[circle === true || circle === 'true' ? 'uni-fav--circle' : '']" :style="[{ backgroundColor: checked ? bgColorChecked : bgColor }]" |
| | | @click="onClick" class="uni-fav"> |
| | | <!-- #ifdef MP-ALIPAY --> |
| | | <view class="uni-fav-star" v-if="!checked && (star === true || star === 'true')"> |
| | | <uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" size="14" type="star-filled" /> |
| | | </view> |
| | | <!-- #endif --> |
| | | <!-- #ifndef MP-ALIPAY --> |
| | | <uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-star" size="14" type="star-filled" |
| | | v-if="!checked && (star === true || star === 'true')" /> |
| | | <!-- #endif --> |
| | | <text :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-text">{{ checked ? contentFav : contentDefault }}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | /** |
| | | * Fav 收藏按钮 |
| | | * @description 用于收藏功能,可点击切换选中、不选中的状态 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=864 |
| | | * @property {Boolean} star = [true|false] 按钮是否带星星 |
| | | * @property {String} bgColor 未收藏时的背景色 |
| | | * @property {String} bgColorChecked 已收藏时的背景色 |
| | | * @property {String} fgColor 未收藏时的文字颜色 |
| | | * @property {String} fgColorChecked 已收藏时的文字颜色 |
| | | * @property {Boolean} circle = [true|false] 是否为圆角 |
| | | * @property {Boolean} checked = [true|false] 是否为已收藏 |
| | | * @property {Object} contentText = [true|false] 收藏按钮文字 |
| | | * @property {Boolean} stat 是否开启统计功能 |
| | | * @event {Function} click 点击 fav按钮触发事件 |
| | | * @example <uni-fav :checked="true"/> |
| | | */ |
| | | |
| | | import { |
| | | initVueI18n |
| | | } from '@dcloudio/uni-i18n' |
| | | import messages from './i18n/index.js' |
| | | const { t } = initVueI18n(messages) |
| | | |
| | | export default { |
| | | name: "UniFav", |
| | | // TODO 兼容 vue3,需要注册事件 |
| | | emits: ['click'], |
| | | props: { |
| | | star: { |
| | | type: [Boolean, String], |
| | | default: true |
| | | }, |
| | | bgColor: { |
| | | type: String, |
| | | default: "#eeeeee" |
| | | }, |
| | | fgColor: { |
| | | type: String, |
| | | default: "#666666" |
| | | }, |
| | | bgColorChecked: { |
| | | type: String, |
| | | default: "#007aff" |
| | | }, |
| | | fgColorChecked: { |
| | | type: String, |
| | | default: "#FFFFFF" |
| | | }, |
| | | circle: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | checked: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | contentText: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | contentDefault: "", |
| | | contentFav: "" |
| | | }; |
| | | } |
| | | }, |
| | | stat:{ |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | contentDefault() { |
| | | return this.contentText.contentDefault || t("uni-fav.collect") |
| | | }, |
| | | contentFav() { |
| | | return this.contentText.contentFav || t("uni-fav.collected") |
| | | }, |
| | | }, |
| | | watch: { |
| | | checked() { |
| | | if (uni.report && this.stat) { |
| | | if (this.checked) { |
| | | uni.report("收藏", "收藏"); |
| | | } else { |
| | | uni.report("取消收藏", "取消收藏"); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | onClick() { |
| | | this.$emit("click"); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | $fav-height: 25px; |
| | | |
| | | .uni-fav { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 60px; |
| | | height: $fav-height; |
| | | line-height: $fav-height; |
| | | text-align: center; |
| | | border-radius: 3px; |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-fav--circle { |
| | | border-radius: 30px; |
| | | } |
| | | |
| | | .uni-fav-star { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | height: $fav-height; |
| | | line-height: 24px; |
| | | margin-right: 3px; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .uni-fav-text { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | height: $fav-height; |
| | | line-height: $fav-height; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 12px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-fav", |
| | | "displayName": "uni-fav 收藏按钮", |
| | | "version": "1.2.1", |
| | | "description": " Fav 收藏组件,可自定义颜色、大小。", |
| | | "keywords": [ |
| | | "fav", |
| | | "uni-ui", |
| | | "uniui", |
| | | "收藏" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "category": [ |
| | | "前端组件", |
| | | "通用组件" |
| | | ], |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-icons" |
| | | ], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | |
| | | ## Fav 收藏按钮 |
| | | > **组件名:uni-fav** |
| | | > 代码块: `uFav` |
| | | |
| | | 用于收藏功能,可点击切换选中、不选中的状态。 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fav) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.0.4(2023-03-29) |
| | | - 修复 手动上传删除一个文件后不能再上传的bug |
| | | ## 1.0.3(2022-12-19) |
| | | - 新增 sourceType 属性, 可以自定义图片和视频选择的来源 |
| | | ## 1.0.2(2022-07-04) |
| | | - 修复 在uni-forms下样式不生效的bug |
| | | ## 1.0.1(2021-11-23) |
| | | - 修复 参数为对象的情况下,url在某些情况显示错误的bug |
| | | ## 1.0.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker) |
| | | ## 0.2.16(2021-11-08) |
| | | - 修复 传入空对象 ,显示错误的Bug |
| | | ## 0.2.15(2021-08-30) |
| | | - 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug |
| | | ## 0.2.14(2021-08-23) |
| | | - 新增 参数中返回 fileID 字段 |
| | | ## 0.2.13(2021-08-23) |
| | | - 修复 腾讯云传入fileID 不能回显的bug |
| | | - 修复 选择图片后,不能放大的问题 |
| | | ## 0.2.12(2021-08-17) |
| | | - 修复 由于 0.2.11 版本引起的不能回显图片的Bug |
| | | ## 0.2.11(2021-08-16) |
| | | - 新增 clearFiles(index) 方法,可以手动删除指定文件 |
| | | - 修复 v-model 值设为 null 报错的Bug |
| | | ## 0.2.10(2021-08-13) |
| | | - 修复 return-type="object" 时,无法删除文件的Bug |
| | | ## 0.2.9(2021-08-03) |
| | | - 修复 auto-upload 属性失效的Bug |
| | | ## 0.2.8(2021-07-31) |
| | | - 修复 fileExtname属性不指定值报错的Bug |
| | | ## 0.2.7(2021-07-31) |
| | | - 修复 在某种场景下图片不回显的Bug |
| | | ## 0.2.6(2021-07-30) |
| | | - 修复 return-type为object下,返回值不正确的Bug |
| | | ## 0.2.5(2021-07-30) |
| | | - 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题 |
| | | ## 0.2.3(2021-07-28) |
| | | - 优化 调整示例代码 |
| | | ## 0.2.2(2021-07-27) |
| | | - 修复 vue3 下赋值错误的Bug |
| | | - 优化 h5平台下上传文件导致页面卡死的问题 |
| | | ## 0.2.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 0.1.1(2021-07-02) |
| | | - 修复 sourceType 缺少默认值导致 ios 无法选择文件 |
| | | ## 0.1.0(2021-06-30) |
| | | - 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改 |
| | | ## 0.0.11(2021-06-30) |
| | | - 修复 由 0.0.10 版本引发的 returnType 属性失效的问题 |
| | | ## 0.0.10(2021-06-29) |
| | | - 优化 文件上传后进度条消失时机 |
| | | ## 0.0.9(2021-06-29) |
| | | - 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug |
| | | ## 0.0.8(2021-06-15) |
| | | - 修复 删除文件时无法触发 v-model 的Bug |
| | | ## 0.0.7(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 0.0.6(2021-04-09) |
| | | - 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug |
| | | ## 0.0.5(2021-04-09) |
| | | - 优化 更新组件示例 |
| | | ## 0.0.4(2021-04-09) |
| | | - 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 |
| | | ## 0.0.3(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
| | | - 修复 微信小程序不指定 fileExtname 属性选择失败的Bug |
对比新文件 |
| | |
| | | 'use strict'; |
| | | |
| | | const ERR_MSG_OK = 'chooseAndUploadFile:ok'; |
| | | const ERR_MSG_FAIL = 'chooseAndUploadFile:fail'; |
| | | |
| | | function chooseImage(opts) { |
| | | const { |
| | | count, |
| | | sizeType = ['original', 'compressed'], |
| | | sourceType, |
| | | extension |
| | | } = opts |
| | | return new Promise((resolve, reject) => { |
| | | uni.chooseImage({ |
| | | count, |
| | | sizeType, |
| | | sourceType, |
| | | extension, |
| | | success(res) { |
| | | resolve(normalizeChooseAndUploadFileRes(res, 'image')); |
| | | }, |
| | | fail(res) { |
| | | reject({ |
| | | errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL), |
| | | }); |
| | | }, |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function chooseVideo(opts) { |
| | | const { |
| | | camera, |
| | | compressed, |
| | | maxDuration, |
| | | sourceType, |
| | | extension |
| | | } = opts; |
| | | return new Promise((resolve, reject) => { |
| | | uni.chooseVideo({ |
| | | camera, |
| | | compressed, |
| | | maxDuration, |
| | | sourceType, |
| | | extension, |
| | | success(res) { |
| | | const { |
| | | tempFilePath, |
| | | duration, |
| | | size, |
| | | height, |
| | | width |
| | | } = res; |
| | | resolve(normalizeChooseAndUploadFileRes({ |
| | | errMsg: 'chooseVideo:ok', |
| | | tempFilePaths: [tempFilePath], |
| | | tempFiles: [ |
| | | { |
| | | name: (res.tempFile && res.tempFile.name) || '', |
| | | path: tempFilePath, |
| | | size, |
| | | type: (res.tempFile && res.tempFile.type) || '', |
| | | width, |
| | | height, |
| | | duration, |
| | | fileType: 'video', |
| | | cloudPath: '', |
| | | }, ], |
| | | }, 'video')); |
| | | }, |
| | | fail(res) { |
| | | reject({ |
| | | errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL), |
| | | }); |
| | | }, |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function chooseAll(opts) { |
| | | const { |
| | | count, |
| | | extension |
| | | } = opts; |
| | | return new Promise((resolve, reject) => { |
| | | let chooseFile = uni.chooseFile; |
| | | if (typeof wx !== 'undefined' && |
| | | typeof wx.chooseMessageFile === 'function') { |
| | | chooseFile = wx.chooseMessageFile; |
| | | } |
| | | if (typeof chooseFile !== 'function') { |
| | | return reject({ |
| | | errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。', |
| | | }); |
| | | } |
| | | chooseFile({ |
| | | type: 'all', |
| | | count, |
| | | extension, |
| | | success(res) { |
| | | resolve(normalizeChooseAndUploadFileRes(res)); |
| | | }, |
| | | fail(res) { |
| | | reject({ |
| | | errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL), |
| | | }); |
| | | }, |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function normalizeChooseAndUploadFileRes(res, fileType) { |
| | | res.tempFiles.forEach((item, index) => { |
| | | if (!item.name) { |
| | | item.name = item.path.substring(item.path.lastIndexOf('/') + 1); |
| | | } |
| | | if (fileType) { |
| | | item.fileType = fileType; |
| | | } |
| | | item.cloudPath = |
| | | Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.')); |
| | | }); |
| | | if (!res.tempFilePaths) { |
| | | res.tempFilePaths = res.tempFiles.map((file) => file.path); |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | function uploadCloudFiles(files, max = 5, onUploadProgress) { |
| | | files = JSON.parse(JSON.stringify(files)) |
| | | const len = files.length |
| | | let count = 0 |
| | | let self = this |
| | | return new Promise(resolve => { |
| | | while (count < max) { |
| | | next() |
| | | } |
| | | |
| | | function next() { |
| | | let cur = count++ |
| | | if (cur >= len) { |
| | | !files.find(item => !item.url && !item.errMsg) && resolve(files) |
| | | return |
| | | } |
| | | const fileItem = files[cur] |
| | | const index = self.files.findIndex(v => v.uuid === fileItem.uuid) |
| | | fileItem.url = '' |
| | | delete fileItem.errMsg |
| | | |
| | | uniCloud |
| | | .uploadFile({ |
| | | filePath: fileItem.path, |
| | | cloudPath: fileItem.cloudPath, |
| | | fileType: fileItem.fileType, |
| | | onUploadProgress: res => { |
| | | res.index = index |
| | | onUploadProgress && onUploadProgress(res) |
| | | } |
| | | }) |
| | | .then(res => { |
| | | fileItem.url = res.fileID |
| | | fileItem.index = index |
| | | if (cur < len) { |
| | | next() |
| | | } |
| | | }) |
| | | .catch(res => { |
| | | fileItem.errMsg = res.errMsg || res.message |
| | | fileItem.index = index |
| | | if (cur < len) { |
| | | next() |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | function uploadFiles(choosePromise, { |
| | | onChooseFile, |
| | | onUploadProgress |
| | | }) { |
| | | return choosePromise |
| | | .then((res) => { |
| | | if (onChooseFile) { |
| | | const customChooseRes = onChooseFile(res); |
| | | if (typeof customChooseRes !== 'undefined') { |
| | | return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ? |
| | | res : chooseRes); |
| | | } |
| | | } |
| | | return res; |
| | | }) |
| | | .then((res) => { |
| | | if (res === false) { |
| | | return { |
| | | errMsg: ERR_MSG_OK, |
| | | tempFilePaths: [], |
| | | tempFiles: [], |
| | | }; |
| | | } |
| | | return res |
| | | }) |
| | | } |
| | | |
| | | function chooseAndUploadFile(opts = { |
| | | type: 'all' |
| | | }) { |
| | | if (opts.type === 'image') { |
| | | return uploadFiles(chooseImage(opts), opts); |
| | | } |
| | | else if (opts.type === 'video') { |
| | | return uploadFiles(chooseVideo(opts), opts); |
| | | } |
| | | return uploadFiles(chooseAll(opts), opts); |
| | | } |
| | | |
| | | export { |
| | | chooseAndUploadFile, |
| | | uploadCloudFiles |
| | | }; |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-file-picker"> |
| | | <view v-if="title" class="uni-file-picker__header"> |
| | | <text class="file-title">{{ title }}</text> |
| | | <text class="file-count">{{ filesList.length }}/{{ limitLength }}</text> |
| | | </view> |
| | | <upload-image v-if="fileMediatype === 'image' && showType === 'grid'" :readonly="readonly" |
| | | :image-styles="imageStyles" :files-list="filesList" :limit="limitLength" :disablePreview="disablePreview" |
| | | :delIcon="delIcon" @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile"> |
| | | <slot> |
| | | <view class="is-add"> |
| | | <view class="icon-add"></view> |
| | | <view class="icon-add rotate"></view> |
| | | </view> |
| | | </slot> |
| | | </upload-image> |
| | | <upload-file v-if="fileMediatype !== 'image' || showType !== 'grid'" :readonly="readonly" |
| | | :list-styles="listStyles" :files-list="filesList" :showType="showType" :delIcon="delIcon" |
| | | @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile"> |
| | | <slot><button type="primary" size="mini">选择文件</button></slot> |
| | | </upload-file> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | chooseAndUploadFile, |
| | | uploadCloudFiles |
| | | } from './choose-and-upload-file.js' |
| | | import { |
| | | get_file_ext, |
| | | get_extname, |
| | | get_files_and_is_max, |
| | | get_file_info, |
| | | get_file_data |
| | | } from './utils.js' |
| | | import uploadImage from './upload-image.vue' |
| | | import uploadFile from './upload-file.vue' |
| | | let fileInput = null |
| | | /** |
| | | * FilePicker 文件选择上传 |
| | | * @description 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=4079 |
| | | * @property {Object|Array} value 组件数据,通常用来回显 ,类型由return-type属性决定 |
| | | * @property {Boolean} disabled = [true|false] 组件禁用 |
| | | * @value true 禁用 |
| | | * @value false 取消禁用 |
| | | * @property {Boolean} readonly = [true|false] 组件只读,不可选择,不显示进度,不显示删除按钮 |
| | | * @value true 只读 |
| | | * @value false 取消只读 |
| | | * @property {String} return-type = [array|object] 限制 value 格式,当为 object 时 ,组件只能单选,且会覆盖 |
| | | * @value array 规定 value 属性的类型为数组 |
| | | * @value object 规定 value 属性的类型为对象 |
| | | * @property {Boolean} disable-preview = [true|false] 禁用图片预览,仅 mode:grid 时生效 |
| | | * @value true 禁用图片预览 |
| | | * @value false 取消禁用图片预览 |
| | | * @property {Boolean} del-icon = [true|false] 是否显示删除按钮 |
| | | * @value true 显示删除按钮 |
| | | * @value false 不显示删除按钮 |
| | | * @property {Boolean} auto-upload = [true|false] 是否自动上传,值为true则只触发@select,可自行上传 |
| | | * @value true 自动上传 |
| | | * @value false 取消自动上传 |
| | | * @property {Number|String} limit 最大选择个数 ,h5 会自动忽略多选的部分 |
| | | * @property {String} title 组件标题,右侧显示上传计数 |
| | | * @property {String} mode = [list|grid] 选择文件后的文件列表样式 |
| | | * @value list 列表显示 |
| | | * @value grid 宫格显示 |
| | | * @property {String} file-mediatype = [image|video|all] 选择文件类型 |
| | | * @value image 只选择图片 |
| | | * @value video 只选择视频 |
| | | * @value all 选择所有文件 |
| | | * @property {Array} file-extname 选择文件后缀,根据 file-mediatype 属性而不同 |
| | | * @property {Object} list-style mode:list 时的样式 |
| | | * @property {Object} image-styles 选择文件后缀,根据 file-mediatype 属性而不同 |
| | | * @event {Function} select 选择文件后触发 |
| | | * @event {Function} progress 文件上传时触发 |
| | | * @event {Function} success 上传成功触发 |
| | | * @event {Function} fail 上传失败触发 |
| | | * @event {Function} delete 文件从列表移除时触发 |
| | | */ |
| | | export default { |
| | | name: 'uniFilePicker', |
| | | components: { |
| | | uploadImage, |
| | | uploadFile |
| | | }, |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'input'], |
| | | props: { |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | type: [Array, Object], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | // #endif |
| | | |
| | | // #ifndef VUE3 |
| | | value: { |
| | | type: [Array, Object], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | // #endif |
| | | |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | disablePreview: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | delIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 自动上传 |
| | | autoUpload: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 最大选择个数 ,h5只能限制单选或是多选 |
| | | limit: { |
| | | type: [Number, String], |
| | | default: 9 |
| | | }, |
| | | // 列表样式 grid | list | list-card |
| | | mode: { |
| | | type: String, |
| | | default: 'grid' |
| | | }, |
| | | // 选择文件类型 image/video/all |
| | | fileMediatype: { |
| | | type: String, |
| | | default: 'image' |
| | | }, |
| | | // 文件类型筛选 |
| | | fileExtname: { |
| | | type: [Array, String], |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | listStyles: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | // 是否显示边框 |
| | | border: true, |
| | | // 是否显示分隔线 |
| | | dividline: true, |
| | | // 线条样式 |
| | | borderStyle: {} |
| | | } |
| | | } |
| | | }, |
| | | imageStyles: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | width: 'auto', |
| | | height: 'auto' |
| | | } |
| | | } |
| | | }, |
| | | readonly: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | returnType: { |
| | | type: String, |
| | | default: 'array' |
| | | }, |
| | | sizeType: { |
| | | type: Array, |
| | | default () { |
| | | return ['original', 'compressed'] |
| | | } |
| | | }, |
| | | sourceType: { |
| | | type: Array, |
| | | default () { |
| | | return ['album', 'camera'] |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | files: [], |
| | | localValue: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | // #ifndef VUE3 |
| | | value: { |
| | | handler(newVal, oldVal) { |
| | | this.setValue(newVal, oldVal) |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | modelValue: { |
| | | handler(newVal, oldVal) { |
| | | this.setValue(newVal, oldVal) |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // #endif |
| | | }, |
| | | computed: { |
| | | filesList() { |
| | | let files = [] |
| | | this.files.forEach(v => { |
| | | files.push(v) |
| | | }) |
| | | return files |
| | | }, |
| | | showType() { |
| | | if (this.fileMediatype === 'image') { |
| | | return this.mode |
| | | } |
| | | return 'list' |
| | | }, |
| | | limitLength() { |
| | | if (this.returnType === 'object') { |
| | | return 1 |
| | | } |
| | | if (!this.limit) { |
| | | return 1 |
| | | } |
| | | if (this.limit >= 9) { |
| | | return 9 |
| | | } |
| | | return this.limit |
| | | } |
| | | }, |
| | | created() { |
| | | // TODO 兼容不开通服务空间的情况 |
| | | if (!(uniCloud.config && uniCloud.config.provider)) { |
| | | this.noSpace = true |
| | | uniCloud.chooseAndUploadFile = chooseAndUploadFile |
| | | } |
| | | this.form = this.getForm('uniForms') |
| | | this.formItem = this.getForm('uniFormsItem') |
| | | if (this.form && this.formItem) { |
| | | if (this.formItem.name) { |
| | | this.rename = this.formItem.name |
| | | this.form.inputChildrens.push(this) |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 公开用户使用,清空文件 |
| | | * @param {Object} index |
| | | */ |
| | | clearFiles(index) { |
| | | if (index !== 0 && !index) { |
| | | this.files = [] |
| | | this.$nextTick(() => { |
| | | this.setEmit() |
| | | }) |
| | | } else { |
| | | this.files.splice(index, 1) |
| | | } |
| | | this.$nextTick(() => { |
| | | this.setEmit() |
| | | }) |
| | | }, |
| | | /** |
| | | * 公开用户使用,继续上传 |
| | | */ |
| | | upload() { |
| | | let files = [] |
| | | this.files.forEach((v, index) => { |
| | | if (v.status === 'ready' || v.status === 'error') { |
| | | files.push(Object.assign({}, v)) |
| | | } |
| | | }) |
| | | return this.uploadFiles(files) |
| | | }, |
| | | async setValue(newVal, oldVal) { |
| | | const newData = async (v) => { |
| | | const reg = /cloud:\/\/([\w.]+\/?)\S*/ |
| | | let url = '' |
| | | if(v.fileID){ |
| | | url = v.fileID |
| | | }else{ |
| | | url = v.url |
| | | } |
| | | if (reg.test(url)) { |
| | | v.fileID = url |
| | | v.url = await this.getTempFileURL(url) |
| | | } |
| | | if(v.url) v.path = v.url |
| | | return v |
| | | } |
| | | if (this.returnType === 'object') { |
| | | if (newVal) { |
| | | await newData(newVal) |
| | | } else { |
| | | newVal = {} |
| | | } |
| | | } else { |
| | | if (!newVal) newVal = [] |
| | | for(let i =0 ;i < newVal.length ;i++){ |
| | | let v = newVal[i] |
| | | await newData(v) |
| | | } |
| | | } |
| | | this.localValue = newVal |
| | | if (this.form && this.formItem &&!this.is_reset) { |
| | | this.is_reset = false |
| | | this.formItem.setValue(this.localValue) |
| | | } |
| | | let filesData = Object.keys(newVal).length > 0 ? newVal : []; |
| | | this.files = [].concat(filesData) |
| | | }, |
| | | |
| | | /** |
| | | * 选择文件 |
| | | */ |
| | | choose() { |
| | | |
| | | if (this.disabled) return |
| | | if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType === |
| | | 'array') { |
| | | uni.showToast({ |
| | | title: `您最多选择 ${this.limitLength} 个文件`, |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | this.chooseFiles() |
| | | }, |
| | | |
| | | /** |
| | | * 选择文件并上传 |
| | | */ |
| | | chooseFiles() { |
| | | const _extname = get_extname(this.fileExtname) |
| | | // 获取后缀 |
| | | uniCloud |
| | | .chooseAndUploadFile({ |
| | | type: this.fileMediatype, |
| | | compressed: false, |
| | | sizeType: this.sizeType, |
| | | sourceType: this.sourceType, |
| | | // TODO 如果为空,video 有问题 |
| | | extension: _extname.length > 0 ? _extname : undefined, |
| | | count: this.limitLength - this.files.length, //默认9 |
| | | onChooseFile: this.chooseFileCallback, |
| | | onUploadProgress: progressEvent => { |
| | | this.setProgress(progressEvent, progressEvent.index) |
| | | } |
| | | }) |
| | | .then(result => { |
| | | this.setSuccessAndError(result.tempFiles) |
| | | }) |
| | | .catch(err => { |
| | | console.log('选择失败', err) |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 选择文件回调 |
| | | * @param {Object} res |
| | | */ |
| | | async chooseFileCallback(res) { |
| | | const _extname = get_extname(this.fileExtname) |
| | | const is_one = (Number(this.limitLength) === 1 && |
| | | this.disablePreview && |
| | | !this.disabled) || |
| | | this.returnType === 'object' |
| | | // 如果这有一个文件 ,需要清空本地缓存数据 |
| | | if (is_one) { |
| | | this.files = [] |
| | | } |
| | | |
| | | let { |
| | | filePaths, |
| | | files |
| | | } = get_files_and_is_max(res, _extname) |
| | | if (!(_extname && _extname.length > 0)) { |
| | | filePaths = res.tempFilePaths |
| | | files = res.tempFiles |
| | | } |
| | | |
| | | let currentData = [] |
| | | for (let i = 0; i < files.length; i++) { |
| | | if (this.limitLength - this.files.length <= 0) break |
| | | files[i].uuid = Date.now() |
| | | let filedata = await get_file_data(files[i], this.fileMediatype) |
| | | filedata.progress = 0 |
| | | filedata.status = 'ready' |
| | | this.files.push(filedata) |
| | | currentData.push({ |
| | | ...filedata, |
| | | file: files[i] |
| | | }) |
| | | } |
| | | this.$emit('select', { |
| | | tempFiles: currentData, |
| | | tempFilePaths: filePaths |
| | | }) |
| | | res.tempFiles = files |
| | | // 停止自动上传 |
| | | if (!this.autoUpload || this.noSpace) { |
| | | res.tempFiles = [] |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 批传 |
| | | * @param {Object} e |
| | | */ |
| | | uploadFiles(files) { |
| | | files = [].concat(files) |
| | | return uploadCloudFiles.call(this, files, 5, res => { |
| | | this.setProgress(res, res.index, true) |
| | | }) |
| | | .then(result => { |
| | | this.setSuccessAndError(result) |
| | | return result; |
| | | }) |
| | | .catch(err => { |
| | | console.log(err) |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 成功或失败 |
| | | */ |
| | | async setSuccessAndError(res, fn) { |
| | | let successData = [] |
| | | let errorData = [] |
| | | let tempFilePath = [] |
| | | let errorTempFilePath = [] |
| | | for (let i = 0; i < res.length; i++) { |
| | | const item = res[i] |
| | | const index = item.uuid ? this.files.findIndex(p => p.uuid === item.uuid) : item.index |
| | | |
| | | if (index === -1 || !this.files) break |
| | | if (item.errMsg === 'request:fail') { |
| | | this.files[index].url = item.path |
| | | this.files[index].status = 'error' |
| | | this.files[index].errMsg = item.errMsg |
| | | // this.files[index].progress = -1 |
| | | errorData.push(this.files[index]) |
| | | errorTempFilePath.push(this.files[index].url) |
| | | } else { |
| | | this.files[index].errMsg = '' |
| | | this.files[index].fileID = item.url |
| | | const reg = /cloud:\/\/([\w.]+\/?)\S*/ |
| | | if (reg.test(item.url)) { |
| | | this.files[index].url = await this.getTempFileURL(item.url) |
| | | }else{ |
| | | this.files[index].url = item.url |
| | | } |
| | | |
| | | this.files[index].status = 'success' |
| | | this.files[index].progress += 1 |
| | | successData.push(this.files[index]) |
| | | tempFilePath.push(this.files[index].fileID) |
| | | } |
| | | } |
| | | |
| | | if (successData.length > 0) { |
| | | this.setEmit() |
| | | // 状态改变返回 |
| | | this.$emit('success', { |
| | | tempFiles: this.backObject(successData), |
| | | tempFilePaths: tempFilePath |
| | | }) |
| | | } |
| | | |
| | | if (errorData.length > 0) { |
| | | this.$emit('fail', { |
| | | tempFiles: this.backObject(errorData), |
| | | tempFilePaths: errorTempFilePath |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 获取进度 |
| | | * @param {Object} progressEvent |
| | | * @param {Object} index |
| | | * @param {Object} type |
| | | */ |
| | | setProgress(progressEvent, index, type) { |
| | | const fileLenth = this.files.length |
| | | const percentNum = (index / fileLenth) * 100 |
| | | const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total) |
| | | let idx = index |
| | | if (!type) { |
| | | idx = this.files.findIndex(p => p.uuid === progressEvent.tempFile.uuid) |
| | | } |
| | | if (idx === -1 || !this.files[idx]) return |
| | | // fix by mehaotian 100 就会消失,-1 是为了让进度条消失 |
| | | this.files[idx].progress = percentCompleted - 1 |
| | | // 上传中 |
| | | this.$emit('progress', { |
| | | index: idx, |
| | | progress: parseInt(percentCompleted), |
| | | tempFile: this.files[idx] |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 删除文件 |
| | | * @param {Object} index |
| | | */ |
| | | delFile(index) { |
| | | this.$emit('delete', { |
| | | tempFile: this.files[index], |
| | | tempFilePath: this.files[index].url |
| | | }) |
| | | this.files.splice(index, 1) |
| | | this.$nextTick(() => { |
| | | this.setEmit() |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 获取文件名和后缀 |
| | | * @param {Object} name |
| | | */ |
| | | getFileExt(name) { |
| | | const last_len = name.lastIndexOf('.') |
| | | const len = name.length |
| | | return { |
| | | name: name.substring(0, last_len), |
| | | ext: name.substring(last_len + 1, len) |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 处理返回事件 |
| | | */ |
| | | setEmit() { |
| | | let data = [] |
| | | if (this.returnType === 'object') { |
| | | data = this.backObject(this.files)[0] |
| | | this.localValue = data?data:null |
| | | } else { |
| | | data = this.backObject(this.files) |
| | | if (!this.localValue) { |
| | | this.localValue = [] |
| | | } |
| | | this.localValue = [...data] |
| | | } |
| | | // #ifdef VUE3 |
| | | this.$emit('update:modelValue', this.localValue) |
| | | // #endif |
| | | // #ifndef VUE3 |
| | | this.$emit('input', this.localValue) |
| | | // #endif |
| | | }, |
| | | |
| | | /** |
| | | * 处理返回参数 |
| | | * @param {Object} files |
| | | */ |
| | | backObject(files) { |
| | | let newFilesData = [] |
| | | files.forEach(v => { |
| | | newFilesData.push({ |
| | | extname: v.extname, |
| | | fileType: v.fileType, |
| | | image: v.image, |
| | | name: v.name, |
| | | path: v.path, |
| | | size: v.size, |
| | | fileID:v.fileID, |
| | | url: v.url, |
| | | // 修改删除一个文件后不能再上传的bug, #694 |
| | | uuid: v.uuid, |
| | | status: v.status, |
| | | cloudPath: v.cloudPath |
| | | }) |
| | | }) |
| | | return newFilesData |
| | | }, |
| | | async getTempFileURL(fileList) { |
| | | fileList = { |
| | | fileList: [].concat(fileList) |
| | | } |
| | | const urls = await uniCloud.getTempFileURL(fileList) |
| | | return urls.fileList[0].tempFileURL || '' |
| | | }, |
| | | /** |
| | | * 获取父元素实例 |
| | | */ |
| | | getForm(name = 'uniForms') { |
| | | let parent = this.$parent; |
| | | let parentName = parent.$options.name; |
| | | while (parentName !== name) { |
| | | parent = parent.$parent; |
| | | if (!parent) return false; |
| | | parentName = parent.$options.name; |
| | | } |
| | | return parent; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .uni-file-picker { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | overflow: hidden; |
| | | width: 100%; |
| | | /* #endif */ |
| | | flex: 1; |
| | | } |
| | | |
| | | .uni-file-picker__header { |
| | | padding-top: 5px; |
| | | padding-bottom: 10px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .file-title { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | |
| | | .file-count { |
| | | font-size: 14px; |
| | | color: #999; |
| | | } |
| | | |
| | | .is-add { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .icon-add { |
| | | width: 50px; |
| | | height: 5px; |
| | | background-color: #f1f1f1; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .rotate { |
| | | position: absolute; |
| | | transform: rotate(90deg); |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-file-picker__files"> |
| | | <view v-if="!readonly" class="files-button" @click="choose"> |
| | | <slot></slot> |
| | | </view> |
| | | <!-- :class="{'is-text-box':showType === 'list'}" --> |
| | | <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle"> |
| | | <!-- ,'is-list-card':showType === 'list-card' --> |
| | | |
| | | <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{ |
| | | 'files-border':index !== 0 && styles.dividline}" |
| | | :style="index !== 0 && styles.dividline &&borderLineStyle"> |
| | | <view class="uni-file-picker__item"> |
| | | <!-- :class="{'is-text-image':showType === 'list'}" --> |
| | | <!-- <view class="files__image is-text-image"> |
| | | <image class="header-image" :src="item.logo" mode="aspectFit"></image> |
| | | </view> --> |
| | | <view class="files__name">{{item.name}}</view> |
| | | <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)"> |
| | | <view class="icon-del icon-files"></view> |
| | | <view class="icon-del rotate"></view> |
| | | </view> |
| | | </view> |
| | | <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress"> |
| | | <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" |
| | | :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" /> |
| | | </view> |
| | | <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)"> |
| | | 点击重试 |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "uploadFile", |
| | | emits:['uploadFiles','choose','delFile'], |
| | | props: { |
| | | filesList: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | delIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | limit: { |
| | | type: [Number, String], |
| | | default: 9 |
| | | }, |
| | | showType: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | listStyles: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | // 是否显示边框 |
| | | border: true, |
| | | // 是否显示分隔线 |
| | | dividline: true, |
| | | // 线条样式 |
| | | borderStyle: {} |
| | | } |
| | | } |
| | | }, |
| | | readonly:{ |
| | | type:Boolean, |
| | | default:false |
| | | } |
| | | }, |
| | | computed: { |
| | | list() { |
| | | let files = [] |
| | | this.filesList.forEach(v => { |
| | | files.push(v) |
| | | }) |
| | | return files |
| | | }, |
| | | styles() { |
| | | let styles = { |
| | | border: true, |
| | | dividline: true, |
| | | 'border-style': {} |
| | | } |
| | | return Object.assign(styles, this.listStyles) |
| | | }, |
| | | borderStyle() { |
| | | let { |
| | | borderStyle, |
| | | border |
| | | } = this.styles |
| | | let obj = {} |
| | | if (!border) { |
| | | obj.border = 'none' |
| | | } else { |
| | | let width = (borderStyle && borderStyle.width) || 1 |
| | | width = this.value2px(width) |
| | | let radius = (borderStyle && borderStyle.radius) || 5 |
| | | radius = this.value2px(radius) |
| | | obj = { |
| | | 'border-width': width, |
| | | 'border-style': (borderStyle && borderStyle.style) || 'solid', |
| | | 'border-color': (borderStyle && borderStyle.color) || '#eee', |
| | | 'border-radius': radius |
| | | } |
| | | } |
| | | let classles = '' |
| | | for (let i in obj) { |
| | | classles += `${i}:${obj[i]};` |
| | | } |
| | | return classles |
| | | }, |
| | | borderLineStyle() { |
| | | let obj = {} |
| | | let { |
| | | borderStyle |
| | | } = this.styles |
| | | if (borderStyle && borderStyle.color) { |
| | | obj['border-color'] = borderStyle.color |
| | | } |
| | | if (borderStyle && borderStyle.width) { |
| | | let width = borderStyle && borderStyle.width || 1 |
| | | let style = borderStyle && borderStyle.style || 0 |
| | | if (typeof width === 'number') { |
| | | width += 'px' |
| | | } else { |
| | | width = width.indexOf('px') ? width : width + 'px' |
| | | } |
| | | obj['border-width'] = width |
| | | |
| | | if (typeof style === 'number') { |
| | | style += 'px' |
| | | } else { |
| | | style = style.indexOf('px') ? style : style + 'px' |
| | | } |
| | | obj['border-top-style'] = style |
| | | } |
| | | let classles = '' |
| | | for (let i in obj) { |
| | | classles += `${i}:${obj[i]};` |
| | | } |
| | | return classles |
| | | } |
| | | }, |
| | | |
| | | methods: { |
| | | uploadFiles(item, index) { |
| | | this.$emit("uploadFiles", { |
| | | item, |
| | | index |
| | | }) |
| | | }, |
| | | choose() { |
| | | this.$emit("choose") |
| | | }, |
| | | delFile(index) { |
| | | this.$emit('delFile', index) |
| | | }, |
| | | value2px(value) { |
| | | if (typeof value === 'number') { |
| | | value += 'px' |
| | | } else { |
| | | value = value.indexOf('px') !== -1 ? value : value + 'px' |
| | | } |
| | | return value |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-file-picker__files { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .files-button { |
| | | // border: 1px red solid; |
| | | } |
| | | |
| | | .uni-file-picker__lists { |
| | | position: relative; |
| | | margin-top: 5px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .file-picker__mask { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | right: 0; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | color: #fff; |
| | | font-size: 14px; |
| | | background-color: rgba(0, 0, 0, 0.4); |
| | | } |
| | | |
| | | .uni-file-picker__lists-box { |
| | | position: relative; |
| | | } |
| | | |
| | | .uni-file-picker__item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | padding: 8px 10px; |
| | | padding-right: 5px; |
| | | padding-left: 10px; |
| | | } |
| | | |
| | | .files-border { |
| | | border-top: 1px #eee solid; |
| | | } |
| | | |
| | | .files__name { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #666; |
| | | margin-right: 25px; |
| | | /* #ifndef APP-NVUE */ |
| | | word-break: break-all; |
| | | word-wrap: break-word; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .icon-files { |
| | | /* #ifndef APP-NVUE */ |
| | | position: static; |
| | | background-color: initial; |
| | | /* #endif */ |
| | | } |
| | | |
| | | // .icon-files .icon-del { |
| | | // background-color: #333; |
| | | // width: 12px; |
| | | // height: 1px; |
| | | // } |
| | | |
| | | |
| | | .is-list-card { |
| | | border: 1px #eee solid; |
| | | margin-bottom: 5px; |
| | | border-radius: 5px; |
| | | box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1); |
| | | padding: 5px; |
| | | } |
| | | |
| | | .files__image { |
| | | width: 40px; |
| | | height: 40px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .header-image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .is-text-box { |
| | | border: 1px #eee solid; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .is-text-image { |
| | | width: 25px; |
| | | height: 25px; |
| | | margin-left: 5px; |
| | | } |
| | | |
| | | .rotate { |
| | | position: absolute; |
| | | transform: rotate(90deg); |
| | | } |
| | | |
| | | .icon-del-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | margin: auto 0; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | top: 0px; |
| | | bottom: 0; |
| | | right: 5px; |
| | | height: 26px; |
| | | width: 26px; |
| | | // border-radius: 50%; |
| | | // background-color: rgba(0, 0, 0, 0.5); |
| | | z-index: 2; |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .icon-del { |
| | | width: 15px; |
| | | height: 1px; |
| | | background-color: #333; |
| | | // border-radius: 1px; |
| | | } |
| | | |
| | | /* #ifdef H5 */ |
| | | @media all and (min-width: 768px) { |
| | | .uni-file-picker__files { |
| | | max-width: 375px; |
| | | } |
| | | } |
| | | |
| | | /* #endif */ |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-file-picker__container"> |
| | | <view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle"> |
| | | <view class="file-picker__box-content" :style="borderStyle"> |
| | | <image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image> |
| | | <view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)"> |
| | | <view class="icon-del"></view> |
| | | <view class="icon-del rotate"></view> |
| | | </view> |
| | | <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress"> |
| | | <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" |
| | | :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" /> |
| | | </view> |
| | | <view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)"> |
| | | 点击重试 |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle"> |
| | | <view class="file-picker__box-content is-add" :style="borderStyle" @click="choose"> |
| | | <slot> |
| | | <view class="icon-add"></view> |
| | | <view class="icon-add rotate"></view> |
| | | </slot> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "uploadImage", |
| | | emits:['uploadFiles','choose','delFile'], |
| | | props: { |
| | | filesList: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | disabled:{ |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | disablePreview: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | limit: { |
| | | type: [Number, String], |
| | | default: 9 |
| | | }, |
| | | imageStyles: { |
| | | type: Object, |
| | | default () { |
| | | return { |
| | | width: 'auto', |
| | | height: 'auto', |
| | | border: {} |
| | | } |
| | | } |
| | | }, |
| | | delIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | readonly:{ |
| | | type:Boolean, |
| | | default:false |
| | | } |
| | | }, |
| | | computed: { |
| | | styles() { |
| | | let styles = { |
| | | width: 'auto', |
| | | height: 'auto', |
| | | border: {} |
| | | } |
| | | return Object.assign(styles, this.imageStyles) |
| | | }, |
| | | boxStyle() { |
| | | const { |
| | | width = 'auto', |
| | | height = 'auto' |
| | | } = this.styles |
| | | let obj = {} |
| | | if (height === 'auto') { |
| | | if (width !== 'auto') { |
| | | obj.height = this.value2px(width) |
| | | obj['padding-top'] = 0 |
| | | } else { |
| | | obj.height = 0 |
| | | } |
| | | } else { |
| | | obj.height = this.value2px(height) |
| | | obj['padding-top'] = 0 |
| | | } |
| | | |
| | | if (width === 'auto') { |
| | | if (height !== 'auto') { |
| | | obj.width = this.value2px(height) |
| | | } else { |
| | | obj.width = '33.3%' |
| | | } |
| | | } else { |
| | | obj.width = this.value2px(width) |
| | | } |
| | | |
| | | let classles = '' |
| | | for(let i in obj){ |
| | | classles+= `${i}:${obj[i]};` |
| | | } |
| | | return classles |
| | | }, |
| | | borderStyle() { |
| | | let { |
| | | border |
| | | } = this.styles |
| | | let obj = {} |
| | | const widthDefaultValue = 1 |
| | | const radiusDefaultValue = 3 |
| | | if (typeof border === 'boolean') { |
| | | obj.border = border ? '1px #eee solid' : 'none' |
| | | } else { |
| | | let width = (border && border.width) || widthDefaultValue |
| | | width = this.value2px(width) |
| | | let radius = (border && border.radius) || radiusDefaultValue |
| | | radius = this.value2px(radius) |
| | | obj = { |
| | | 'border-width': width, |
| | | 'border-style': (border && border.style) || 'solid', |
| | | 'border-color': (border && border.color) || '#eee', |
| | | 'border-radius': radius |
| | | } |
| | | } |
| | | let classles = '' |
| | | for(let i in obj){ |
| | | classles+= `${i}:${obj[i]};` |
| | | } |
| | | return classles |
| | | } |
| | | }, |
| | | methods: { |
| | | uploadFiles(item, index) { |
| | | this.$emit("uploadFiles", item) |
| | | }, |
| | | choose() { |
| | | this.$emit("choose") |
| | | }, |
| | | delFile(index) { |
| | | this.$emit('delFile', index) |
| | | }, |
| | | prviewImage(img, index) { |
| | | let urls = [] |
| | | if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){ |
| | | this.$emit("choose") |
| | | } |
| | | if(this.disablePreview) return |
| | | this.filesList.forEach(i => { |
| | | urls.push(i.url) |
| | | }) |
| | | |
| | | uni.previewImage({ |
| | | urls: urls, |
| | | current: index |
| | | }); |
| | | }, |
| | | value2px(value) { |
| | | if (typeof value === 'number') { |
| | | value += 'px' |
| | | } else { |
| | | if (value.indexOf('%') === -1) { |
| | | value = value.indexOf('px') !== -1 ? value : value + 'px' |
| | | } |
| | | } |
| | | return value |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-file-picker__container { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-wrap: wrap; |
| | | margin: -5px; |
| | | } |
| | | |
| | | .file-picker__box { |
| | | position: relative; |
| | | // flex: 0 0 33.3%; |
| | | width: 33.3%; |
| | | height: 0; |
| | | padding-top: 33.33%; |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .file-picker__box-content { |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | margin: 5px; |
| | | border: 1px #eee solid; |
| | | border-radius: 5px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .file-picker__progress { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | /* border: 1px red solid; */ |
| | | z-index: 2; |
| | | } |
| | | |
| | | .file-picker__progress-item { |
| | | width: 100%; |
| | | } |
| | | |
| | | .file-picker__mask { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | right: 0; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | color: #fff; |
| | | font-size: 12px; |
| | | background-color: rgba(0, 0, 0, 0.4); |
| | | } |
| | | |
| | | .file-image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .is-add { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .icon-add { |
| | | width: 50px; |
| | | height: 5px; |
| | | background-color: #f1f1f1; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .rotate { |
| | | position: absolute; |
| | | transform: rotate(90deg); |
| | | } |
| | | |
| | | .icon-del-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | top: 3px; |
| | | right: 3px; |
| | | height: 26px; |
| | | width: 26px; |
| | | border-radius: 50%; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | z-index: 2; |
| | | transform: rotate(-45deg); |
| | | } |
| | | |
| | | .icon-del { |
| | | width: 15px; |
| | | height: 2px; |
| | | background-color: #fff; |
| | | border-radius: 2px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | /** |
| | | * 获取文件名和后缀 |
| | | * @param {String} name |
| | | */ |
| | | export const get_file_ext = (name) => { |
| | | const last_len = name.lastIndexOf('.') |
| | | const len = name.length |
| | | return { |
| | | name: name.substring(0, last_len), |
| | | ext: name.substring(last_len + 1, len) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取扩展名 |
| | | * @param {Array} fileExtname |
| | | */ |
| | | export const get_extname = (fileExtname) => { |
| | | if (!Array.isArray(fileExtname)) { |
| | | let extname = fileExtname.replace(/(\[|\])/g, '') |
| | | return extname.split(',') |
| | | } else { |
| | | return fileExtname |
| | | } |
| | | return [] |
| | | } |
| | | |
| | | /** |
| | | * 获取文件和检测是否可选 |
| | | */ |
| | | export const get_files_and_is_max = (res, _extname) => { |
| | | let filePaths = [] |
| | | let files = [] |
| | | if(!_extname || _extname.length === 0){ |
| | | return { |
| | | filePaths, |
| | | files |
| | | } |
| | | } |
| | | res.tempFiles.forEach(v => { |
| | | let fileFullName = get_file_ext(v.name) |
| | | const extname = fileFullName.ext.toLowerCase() |
| | | if (_extname.indexOf(extname) !== -1) { |
| | | files.push(v) |
| | | filePaths.push(v.path) |
| | | } |
| | | }) |
| | | if (files.length !== res.tempFiles.length) { |
| | | uni.showToast({ |
| | | title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`, |
| | | icon: 'none', |
| | | duration: 5000 |
| | | }) |
| | | } |
| | | |
| | | return { |
| | | filePaths, |
| | | files |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取图片信息 |
| | | * @param {Object} filepath |
| | | */ |
| | | export const get_file_info = (filepath) => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.getImageInfo({ |
| | | src: filepath, |
| | | success(res) { |
| | | resolve(res) |
| | | }, |
| | | fail(err) { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | /** |
| | | * 获取封装数据 |
| | | */ |
| | | export const get_file_data = async (files, type = 'image') => { |
| | | // 最终需要上传数据库的数据 |
| | | let fileFullName = get_file_ext(files.name) |
| | | const extname = fileFullName.ext.toLowerCase() |
| | | let filedata = { |
| | | name: files.name, |
| | | uuid: files.uuid, |
| | | extname: extname || '', |
| | | cloudPath: files.cloudPath, |
| | | fileType: files.fileType, |
| | | url: files.path || files.path, |
| | | size: files.size, //单位是字节 |
| | | image: {}, |
| | | path: files.path, |
| | | video: {} |
| | | } |
| | | if (type === 'image') { |
| | | const imageinfo = await get_file_info(files.path) |
| | | delete filedata.video |
| | | filedata.image.width = imageinfo.width |
| | | filedata.image.height = imageinfo.height |
| | | filedata.image.location = imageinfo.path |
| | | } else { |
| | | delete filedata.image |
| | | } |
| | | return filedata |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "id": "uni-file-picker", |
| | | "displayName": "uni-file-picker 文件选择上传", |
| | | "version": "1.0.4", |
| | | "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "图片上传", |
| | | "文件上传" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "n" |
| | | }, |
| | | "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" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | |
| | | ## FilePicker 文件选择上传 |
| | | |
| | | > **组件名:uni-file-picker** |
| | | > 代码块: `uFilePicker` |
| | | |
| | | |
| | | 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
对比新文件 |
| | |
| | | ## 1.4.9(2023-02-10) |
| | | - 修复 required 参数无法动态绑定 |
| | | ## 1.4.8(2022-08-23) |
| | | - 优化 根据 rules 自动添加 required 的问题 |
| | | ## 1.4.7(2022-08-22) |
| | | - 修复 item 未设置 require 属性,rules 设置 require 后,星号也显示的 bug,详见:[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540) |
| | | ## 1.4.6(2022-07-13) |
| | | - 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug |
| | | ## 1.4.5(2022-07-05) |
| | | - 新增 更多表单示例 |
| | | - 优化 子表单组件过期提示的问题 |
| | | - 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式 |
| | | ## 1.4.4(2022-07-04) |
| | | - 更新 删除组件日志 |
| | | ## 1.4.3(2022-07-04) |
| | | - 修复 由 1.4.0 引发的 label 插槽不生效的bug |
| | | ## 1.4.2(2022-07-04) |
| | | - 修复 子组件找不到 setValue 报错的bug |
| | | ## 1.4.1(2022-07-04) |
| | | - 修复 uni-data-picker 在 uni-forms-item 中报错的bug |
| | | - 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug |
| | | ## 1.4.0(2022-06-30) |
| | | - 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题 |
| | | - 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力 |
| | | - 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃 |
| | | - 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效 |
| | | - 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法 |
| | | - 新增 子表单的 setRules 方法,配合自定义校验函数使用 |
| | | - 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则 |
| | | - 优化 动态表单校验方式,废弃拼接name的方式 |
| | | ## 1.3.3(2022-06-22) |
| | | - 修复 表单校验顺序无序问题 |
| | | ## 1.3.2(2021-12-09) |
| | | - |
| | | ## 1.3.1(2021-11-19) |
| | | - 修复 label 插槽不生效的bug |
| | | ## 1.3.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms) |
| | | ## 1.2.7(2021-08-13) |
| | | - 修复 没有添加校验规则的字段依然报错的Bug |
| | | ## 1.2.6(2021-08-11) |
| | | - 修复 重置表单错误信息无法清除的问题 |
| | | ## 1.2.5(2021-08-11) |
| | | - 优化 组件文档 |
| | | ## 1.2.4(2021-08-11) |
| | | - 修复 表单验证只生效一次的问题 |
| | | ## 1.2.3(2021-07-30) |
| | | - 优化 vue3下事件警告的问题 |
| | | ## 1.2.2(2021-07-26) |
| | | - 修复 vue2 下条件编译导致destroyed生命周期失效的Bug |
| | | - 修复 1.2.1 引起的示例在小程序平台报错的Bug |
| | | ## 1.2.1(2021-07-22) |
| | | - 修复 动态校验表单,默认值为空的情况下校验失效的Bug |
| | | - 修复 不指定name属性时,运行报错的Bug |
| | | - 优化 label默认宽度从65调整至70,使required为true且四字时不换行 |
| | | - 优化 组件示例,新增动态校验示例代码 |
| | | - 优化 组件文档,使用方式更清晰 |
| | | ## 1.2.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.1.2(2021-06-25) |
| | | - 修复 pattern 属性在微信小程序平台无效的问题 |
| | | ## 1.1.1(2021-06-22) |
| | | - 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug |
| | | ## 1.1.0(2021-06-22) |
| | | - 修复 只写setRules方法而导致校验不生效的Bug |
| | | - 修复 由上个办法引发的错误提示文字错位的Bug |
| | | ## 1.0.48(2021-06-21) |
| | | - 修复 不设置 label 属性 ,无法设置label插槽的问题 |
| | | ## 1.0.47(2021-06-21) |
| | | - 修复 不设置label属性,label-width属性不生效的bug |
| | | - 修复 setRules 方法与rules属性冲突的问题 |
| | | ## 1.0.46(2021-06-04) |
| | | - 修复 动态删减数据导致报错的问题 |
| | | ## 1.0.45(2021-06-04) |
| | | - 新增 modelValue 属性 ,value 即将废弃 |
| | | ## 1.0.44(2021-06-02) |
| | | - 新增 uni-forms-item 可以设置单独的 rules |
| | | - 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤 |
| | | - 优化 submit 事件重命名为 validate |
| | | ## 1.0.43(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.0.42(2021-04-30) |
| | | - 修复 自定义检验器失效的问题 |
| | | ## 1.0.41(2021-03-05) |
| | | - 更新 校验器 |
| | | - 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug |
| | | ## 1.0.40(2021-03-04) |
| | | - 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug |
| | | ## 1.0.39(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
| | | - 修复 校验器传入 int 等类型 ,返回String类型的Bug |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-forms-item" |
| | | :class="['is-direction-' + localLabelPos ,border?'uni-forms-item--border':'' ,border && isFirstBorder?'is-first-border':'']"> |
| | | <slot name="label"> |
| | | <view class="uni-forms-item__label" :class="{'no-label':!label && !required}" |
| | | :style="{width:localLabelWidth,justifyContent: localLabelAlign}"> |
| | | <text v-if="required" class="is-required">*</text> |
| | | <text>{{label}}</text> |
| | | </view> |
| | | </slot> |
| | | <!-- #ifndef APP-NVUE --> |
| | | <view class="uni-forms-item__content"> |
| | | <slot></slot> |
| | | <view class="uni-forms-item__error" :class="{'msg--active':msg}"> |
| | | <text>{{msg}}</text> |
| | | </view> |
| | | </view> |
| | | <!-- #endif --> |
| | | <!-- #ifdef APP-NVUE --> |
| | | <view class="uni-forms-item__nuve-content"> |
| | | <view class="uni-forms-item__content"> |
| | | <slot></slot> |
| | | </view> |
| | | <view class="uni-forms-item__error" :class="{'msg--active':msg}"> |
| | | <text class="error-text">{{msg}}</text> |
| | | </view> |
| | | </view> |
| | | <!-- #endif --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * uni-fomrs-item 表单子组件 |
| | | * @description uni-fomrs-item 表单子组件,提供了基础布局已经校验能力 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=2773 |
| | | * @property {Boolean} required 是否必填,左边显示红色"*"号 |
| | | * @property {String } label 输入框左边的文字提示 |
| | | * @property {Number } labelWidth label的宽度,单位px(默认65) |
| | | * @property {String } labelAlign = [left|center|right] label的文字对齐方式(默认left) |
| | | * @value left label 左侧显示 |
| | | * @value center label 居中 |
| | | * @value right label 右侧对齐 |
| | | * @property {String } errorMessage 显示的错误提示内容,如果为空字符串或者false,则不显示错误信息 |
| | | * @property {String } name 表单域的属性名,在使用校验规则时必填 |
| | | * @property {String } leftIcon 【1.4.0废弃】label左边的图标,限 uni-ui 的图标名称 |
| | | * @property {String } iconColor 【1.4.0废弃】左边通过icon配置的图标的颜色(默认#606266) |
| | | * @property {String} validateTrigger = [bind|submit|blur] 【1.4.0废弃】校验触发器方式 默认 submit |
| | | * @value bind 发生变化时触发 |
| | | * @value submit 提交时触发 |
| | | * @value blur 失去焦点触发 |
| | | * @property {String } labelPosition = [top|left] 【1.4.0废弃】label的文字的位置(默认left) |
| | | * @value top 顶部显示 label |
| | | * @value left 左侧显示 label |
| | | */ |
| | | |
| | | export default { |
| | | name: 'uniFormsItem', |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | provide() { |
| | | return { |
| | | uniFormItem: this |
| | | } |
| | | }, |
| | | inject: { |
| | | form: { |
| | | from: 'uniForm', |
| | | default: null |
| | | }, |
| | | }, |
| | | props: { |
| | | // 表单校验规则 |
| | | rules: { |
| | | type: Array, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // 表单域的属性名,在使用校验规则时必填 |
| | | name: { |
| | | type: [String, Array], |
| | | default: '' |
| | | }, |
| | | required: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | label: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // label的宽度 ,默认 80 |
| | | labelWidth: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // label 居中方式,默认 left 取值 left/center/right |
| | | labelAlign: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 强制显示错误信息 |
| | | errorMessage: { |
| | | type: [String, Boolean], |
| | | default: '' |
| | | }, |
| | | // 1.4.0 弃用,统一使用 form 的校验时机 |
| | | // validateTrigger: { |
| | | // type: String, |
| | | // default: '' |
| | | // }, |
| | | // 1.4.0 弃用,统一使用 form 的label 位置 |
| | | // labelPosition: { |
| | | // type: String, |
| | | // default: '' |
| | | // }, |
| | | // 1.4.0 以下属性已经废弃,请使用 #label 插槽代替 |
| | | leftIcon: String, |
| | | iconColor: { |
| | | type: String, |
| | | default: '#606266' |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | errMsg: '', |
| | | userRules: null, |
| | | localLabelAlign: 'left', |
| | | localLabelWidth: '65px', |
| | | localLabelPos: 'left', |
| | | border: false, |
| | | isFirstBorder: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | // 处理错误信息 |
| | | msg() { |
| | | return this.errorMessage || this.errMsg; |
| | | } |
| | | }, |
| | | watch: { |
| | | // 规则发生变化通知子组件更新 |
| | | 'form.formRules'(val) { |
| | | // TODO 处理头条vue3 watch不生效的问题 |
| | | // #ifndef MP-TOUTIAO |
| | | this.init() |
| | | // #endif |
| | | }, |
| | | 'form.labelWidth'(val) { |
| | | // 宽度 |
| | | this.localLabelWidth = this._labelWidthUnit(val) |
| | | |
| | | }, |
| | | 'form.labelPosition'(val) { |
| | | // 标签位置 |
| | | this.localLabelPos = this._labelPosition() |
| | | }, |
| | | 'form.labelAlign'(val) { |
| | | |
| | | } |
| | | }, |
| | | created() { |
| | | this.init(true) |
| | | if (this.name && this.form) { |
| | | // TODO 处理头条vue3 watch不生效的问题 |
| | | // #ifdef MP-TOUTIAO |
| | | this.$watch('form.formRules', () => { |
| | | this.init() |
| | | }) |
| | | // #endif |
| | | |
| | | // 监听变化 |
| | | this.$watch( |
| | | () => { |
| | | const val = this.form._getDataValue(this.name, this.form.localData) |
| | | return val |
| | | }, |
| | | (value, oldVal) => { |
| | | const isEqual = this.form._isEqual(value, oldVal) |
| | | // 简单判断前后值的变化,只有发生变化才会发生校验 |
| | | // TODO 如果 oldVal = undefined ,那么大概率是源数据里没有值导致 ,这个情况不哦校验 ,可能不严谨 ,需要在做观察 |
| | | // fix by mehaotian 暂时取消 && oldVal !== undefined ,如果formData 中不存在,可能会不校验 |
| | | if (!isEqual) { |
| | | const val = this.itemSetValue(value) |
| | | this.onFieldChange(val, false) |
| | | } |
| | | }, { |
| | | immediate: false |
| | | } |
| | | ); |
| | | } |
| | | |
| | | }, |
| | | // #ifndef VUE3 |
| | | destroyed() { |
| | | if (this.__isUnmounted) return |
| | | this.unInit() |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | unmounted() { |
| | | this.__isUnmounted = true |
| | | this.unInit() |
| | | }, |
| | | // #endif |
| | | methods: { |
| | | /** |
| | | * 外部调用方法 |
| | | * 设置规则 ,主要用于小程序自定义检验规则 |
| | | * @param {Array} rules 规则源数据 |
| | | */ |
| | | setRules(rules = null) { |
| | | this.userRules = rules |
| | | this.init(false) |
| | | }, |
| | | // 兼容老版本表单组件 |
| | | setValue() { |
| | | // console.log('setValue 方法已经弃用,请使用最新版本的 uni-forms 表单组件以及其他关联组件。'); |
| | | }, |
| | | /** |
| | | * 外部调用方法 |
| | | * 校验数据 |
| | | * @param {any} value 需要校验的数据 |
| | | * @param {boolean} 是否立即校验 |
| | | * @return {Array|null} 校验内容 |
| | | */ |
| | | async onFieldChange(value, formtrigger = true) { |
| | | const { |
| | | formData, |
| | | localData, |
| | | errShowType, |
| | | validateCheck, |
| | | validateTrigger, |
| | | _isRequiredField, |
| | | _realName |
| | | } = this.form |
| | | const name = _realName(this.name) |
| | | if (!value) { |
| | | value = this.form.formData[name] |
| | | } |
| | | // fixd by mehaotian 不在校验前清空信息,解决闪屏的问题 |
| | | // this.errMsg = ''; |
| | | |
| | | // fix by mehaotian 解决没有检验规则的情况下,抛出错误的问题 |
| | | const ruleLen = this.itemRules.rules && this.itemRules.rules.length |
| | | if (!this.validator || !ruleLen || ruleLen === 0) return; |
| | | |
| | | // 检验时机 |
| | | // let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger); |
| | | const isRequiredField = _isRequiredField(this.itemRules.rules || []); |
| | | let result = null; |
| | | // 只有等于 bind 时 ,才能开启时实校验 |
| | | if (validateTrigger === 'bind' || formtrigger) { |
| | | // 校验当前表单项 |
| | | result = await this.validator.validateUpdate({ |
| | | [name]: value |
| | | }, |
| | | formData |
| | | ); |
| | | |
| | | // 判断是否必填,非必填,不填不校验,填写才校验 ,暂时只处理 undefined 和空的情况 |
| | | if (!isRequiredField && (value === undefined || value === '')) { |
| | | result = null; |
| | | } |
| | | |
| | | // 判断错误信息显示类型 |
| | | if (result && result.errorMessage) { |
| | | if (errShowType === 'undertext') { |
| | | // 获取错误信息 |
| | | this.errMsg = !result ? '' : result.errorMessage; |
| | | } |
| | | if (errShowType === 'toast') { |
| | | uni.showToast({ |
| | | title: result.errorMessage || '校验错误', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | if (errShowType === 'modal') { |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: result.errorMessage || '校验错误' |
| | | }); |
| | | } |
| | | } else { |
| | | this.errMsg = '' |
| | | } |
| | | // 通知 form 组件更新事件 |
| | | validateCheck(result ? result : null) |
| | | } else { |
| | | this.errMsg = '' |
| | | } |
| | | return result ? result : null; |
| | | }, |
| | | /** |
| | | * 初始组件数据 |
| | | */ |
| | | init(type = false) { |
| | | const { |
| | | validator, |
| | | formRules, |
| | | childrens, |
| | | formData, |
| | | localData, |
| | | _realName, |
| | | labelWidth, |
| | | _getDataValue, |
| | | _setDataValue |
| | | } = this.form || {} |
| | | // 对齐方式 |
| | | this.localLabelAlign = this._justifyContent() |
| | | // 宽度 |
| | | this.localLabelWidth = this._labelWidthUnit(labelWidth) |
| | | // 标签位置 |
| | | this.localLabelPos = this._labelPosition() |
| | | // 将需要校验的子组件加入form 队列 |
| | | this.form && type && childrens.push(this) |
| | | |
| | | if (!validator || !formRules) return |
| | | // 判断第一个 item |
| | | if (!this.form.isFirstBorder) { |
| | | this.form.isFirstBorder = true; |
| | | this.isFirstBorder = true; |
| | | } |
| | | |
| | | // 判断 group 里的第一个 item |
| | | if (this.group) { |
| | | if (!this.group.isFirstBorder) { |
| | | this.group.isFirstBorder = true; |
| | | this.isFirstBorder = true; |
| | | } |
| | | } |
| | | this.border = this.form.border; |
| | | // 获取子域的真实名称 |
| | | const name = _realName(this.name) |
| | | const itemRule = this.userRules || this.rules |
| | | if (typeof formRules === 'object' && itemRule) { |
| | | // 子规则替换父规则 |
| | | formRules[name] = { |
| | | rules: itemRule |
| | | } |
| | | validator.updateSchema(formRules); |
| | | } |
| | | // 注册校验规则 |
| | | const itemRules = formRules[name] || {} |
| | | this.itemRules = itemRules |
| | | // 注册校验函数 |
| | | this.validator = validator |
| | | // 默认值赋予 |
| | | this.itemSetValue(_getDataValue(this.name, localData)) |
| | | }, |
| | | unInit() { |
| | | if (this.form) { |
| | | const { |
| | | childrens, |
| | | formData, |
| | | _realName |
| | | } = this.form |
| | | childrens.forEach((item, index) => { |
| | | if (item === this) { |
| | | this.form.childrens.splice(index, 1) |
| | | delete formData[_realName(item.name)] |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | // 设置item 的值 |
| | | itemSetValue(value) { |
| | | const name = this.form._realName(this.name) |
| | | const rules = this.itemRules.rules || [] |
| | | const val = this.form._getValue(name, value, rules) |
| | | this.form._setDataValue(name, this.form.formData, val) |
| | | return val |
| | | }, |
| | | |
| | | /** |
| | | * 移除该表单项的校验结果 |
| | | */ |
| | | clearValidate() { |
| | | this.errMsg = ''; |
| | | }, |
| | | |
| | | // 是否显示星号 |
| | | _isRequired() { |
| | | // TODO 不根据规则显示 星号,考虑后续兼容 |
| | | // if (this.form) { |
| | | // if (this.form._isRequiredField(this.itemRules.rules || []) && this.required) { |
| | | // return true |
| | | // } |
| | | // return false |
| | | // } |
| | | return this.required |
| | | }, |
| | | |
| | | // 处理对齐方式 |
| | | _justifyContent() { |
| | | if (this.form) { |
| | | const { |
| | | labelAlign |
| | | } = this.form |
| | | let labelAli = this.labelAlign ? this.labelAlign : labelAlign; |
| | | if (labelAli === 'left') return 'flex-start'; |
| | | if (labelAli === 'center') return 'center'; |
| | | if (labelAli === 'right') return 'flex-end'; |
| | | } |
| | | return 'flex-start'; |
| | | }, |
| | | // 处理 label宽度单位 ,继承父元素的值 |
| | | _labelWidthUnit(labelWidth) { |
| | | |
| | | // if (this.form) { |
| | | // const { |
| | | // labelWidth |
| | | // } = this.form |
| | | return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 65 : 'auto'))) |
| | | // } |
| | | // return '65px' |
| | | }, |
| | | // 处理 label 位置 |
| | | _labelPosition() { |
| | | if (this.form) return this.form.labelPosition || 'left' |
| | | return 'left' |
| | | |
| | | }, |
| | | |
| | | /** |
| | | * 触发时机 |
| | | * @param {Object} rule 当前规则内时机 |
| | | * @param {Object} itemRlue 当前组件时机 |
| | | * @param {Object} parentRule 父组件时机 |
| | | */ |
| | | isTrigger(rule, itemRlue, parentRule) { |
| | | // bind submit |
| | | if (rule === 'submit' || !rule) { |
| | | if (rule === undefined) { |
| | | if (itemRlue !== 'bind') { |
| | | if (!itemRlue) { |
| | | return parentRule === '' ? 'bind' : 'submit'; |
| | | } |
| | | return 'submit'; |
| | | } |
| | | return 'bind'; |
| | | } |
| | | return 'submit'; |
| | | } |
| | | return 'bind'; |
| | | }, |
| | | num2px(num) { |
| | | if (typeof num === 'number') { |
| | | return `${num}px` |
| | | } |
| | | return num |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-forms-item { |
| | | position: relative; |
| | | display: flex; |
| | | /* #ifdef APP-NVUE */ |
| | | // 在 nvue 中,使用 margin-bottom error 信息会被隐藏 |
| | | padding-bottom: 22px; |
| | | /* #endif */ |
| | | /* #ifndef APP-NVUE */ |
| | | margin-bottom: 22px; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | |
| | | &__label { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | text-align: left; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | height: 36px; |
| | | padding: 0 12px 0 0; |
| | | /* #ifndef APP-NVUE */ |
| | | vertical-align: middle; |
| | | flex-shrink: 0; |
| | | /* #endif */ |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | |
| | | /* #endif */ |
| | | &.no-label { |
| | | padding: 0; |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | /* #ifndef MP-TOUTIAO */ |
| | | // display: flex; |
| | | // align-items: center; |
| | | /* #endif */ |
| | | position: relative; |
| | | font-size: 14px; |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | |
| | | /* #ifndef APP || H5 || MP-WEIXIN || APP-NVUE */ |
| | | // TODO 因为小程序平台会多一层标签节点 ,所以需要在多余节点继承当前样式 |
| | | &>uni-easyinput, |
| | | &>uni-data-picker { |
| | | width: 100%; |
| | | } |
| | | |
| | | /* #endif */ |
| | | |
| | | } |
| | | |
| | | & .uni-forms-item__nuve-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | flex: 1; |
| | | } |
| | | |
| | | &__error { |
| | | color: #f56c6c; |
| | | font-size: 12px; |
| | | line-height: 1; |
| | | padding-top: 4px; |
| | | position: absolute; |
| | | /* #ifndef APP-NVUE */ |
| | | top: 100%; |
| | | left: 0; |
| | | transition: transform 0.3s; |
| | | transform: translateY(-100%); |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | bottom: 5px; |
| | | /* #endif */ |
| | | |
| | | opacity: 0; |
| | | |
| | | .error-text { |
| | | // 只有 nvue 下这个样式才生效 |
| | | color: #f56c6c; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | &.msg--active { |
| | | opacity: 1; |
| | | transform: translateY(0%); |
| | | } |
| | | } |
| | | |
| | | // 位置修饰样式 |
| | | &.is-direction-left { |
| | | flex-direction: row; |
| | | } |
| | | |
| | | &.is-direction-top { |
| | | flex-direction: column; |
| | | |
| | | .uni-forms-item__label { |
| | | padding: 0 0 8px; |
| | | line-height: 1.5715; |
| | | text-align: left; |
| | | /* #ifndef APP-NVUE */ |
| | | white-space: initial; |
| | | /* #endif */ |
| | | } |
| | | } |
| | | |
| | | .is-required { |
| | | // color: $uni-color-error; |
| | | color: #dd524d; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | |
| | | .uni-forms-item--border { |
| | | margin-bottom: 0; |
| | | padding: 10px 0; |
| | | // padding-bottom: 0; |
| | | border-top: 1px #eee solid; |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | .uni-forms-item__content { |
| | | flex-direction: column; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | |
| | | .uni-forms-item__error { |
| | | position: relative; |
| | | top: 5px; |
| | | left: 0; |
| | | padding-top: 0; |
| | | } |
| | | } |
| | | |
| | | /* #endif */ |
| | | |
| | | /* #ifdef APP-NVUE */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .uni-forms-item__error { |
| | | position: relative; |
| | | top: 0px; |
| | | left: 0; |
| | | padding-top: 0; |
| | | margin-top: 5px; |
| | | } |
| | | |
| | | /* #endif */ |
| | | |
| | | } |
| | | |
| | | .is-first-border { |
| | | /* #ifndef APP-NVUE */ |
| | | border: none; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | border-width: 0; |
| | | /* #endif */ |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="uni-forms"> |
| | | <form> |
| | | <slot></slot> |
| | | </form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Validator from './validate.js'; |
| | | import { |
| | | deepCopy, |
| | | getValue, |
| | | isRequiredField, |
| | | setDataValue, |
| | | getDataValue, |
| | | realName, |
| | | isRealName, |
| | | rawData, |
| | | isEqual |
| | | } from './utils.js' |
| | | |
| | | // #ifndef VUE3 |
| | | // 后续会慢慢废弃这个方法 |
| | | import Vue from 'vue'; |
| | | Vue.prototype.binddata = function(name, value, formName) { |
| | | if (formName) { |
| | | this.$refs[formName].setValue(name, value); |
| | | } else { |
| | | let formVm; |
| | | for (let i in this.$refs) { |
| | | const vm = this.$refs[i]; |
| | | if (vm && vm.$options && vm.$options.name === 'uniForms') { |
| | | formVm = vm; |
| | | break; |
| | | } |
| | | } |
| | | if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性'); |
| | | formVm.setValue(name, value); |
| | | } |
| | | }; |
| | | // #endif |
| | | /** |
| | | * Forms 表单 |
| | | * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=2773 |
| | | * @property {Object} rules 表单校验规则 |
| | | * @property {String} validateTrigger = [bind|submit|blur] 校验触发器方式 默认 submit |
| | | * @value bind 发生变化时触发 |
| | | * @value submit 提交时触发 |
| | | * @value blur 失去焦点时触发 |
| | | * @property {String} labelPosition = [top|left] label 位置 默认 left |
| | | * @value top 顶部显示 label |
| | | * @value left 左侧显示 label |
| | | * @property {String} labelWidth label 宽度,默认 65px |
| | | * @property {String} labelAlign = [left|center|right] label 居中方式 默认 left |
| | | * @value left label 左侧显示 |
| | | * @value center label 居中 |
| | | * @value right label 右侧对齐 |
| | | * @property {String} errShowType = [undertext|toast|modal] 校验错误信息提示方式 |
| | | * @value undertext 错误信息在底部显示 |
| | | * @value toast 错误信息toast显示 |
| | | * @value modal 错误信息modal显示 |
| | | * @event {Function} submit 提交时触发 |
| | | * @event {Function} validate 校验结果发生变化触发 |
| | | */ |
| | | export default { |
| | | name: 'uniForms', |
| | | emits: ['validate', 'submit'], |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | props: { |
| | | // 即将弃用 |
| | | value: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // vue3 替换 value 属性 |
| | | modelValue: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue |
| | | model: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // 表单校验规则 |
| | | rules: { |
| | | type: Object, |
| | | default () { |
| | | return {}; |
| | | } |
| | | }, |
| | | //校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal] |
| | | errShowType: { |
| | | type: String, |
| | | default: 'undertext' |
| | | }, |
| | | // 校验触发器方式 默认 bind 取值 [bind|submit] |
| | | validateTrigger: { |
| | | type: String, |
| | | default: 'submit' |
| | | }, |
| | | // label 位置,默认 left 取值 top/left |
| | | labelPosition: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // label 宽度 |
| | | labelWidth: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // label 居中方式,默认 left 取值 left/center/right |
| | | labelAlign: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | provide() { |
| | | return { |
| | | uniForm: this |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 表单本地值的记录,不应该与传如的值进行关联 |
| | | formData: {}, |
| | | formRules: {} |
| | | }; |
| | | }, |
| | | computed: { |
| | | // 计算数据源变化的 |
| | | localData() { |
| | | const localVal = this.model || this.modelValue || this.value |
| | | if (localVal) { |
| | | return deepCopy(localVal) |
| | | } |
| | | return {} |
| | | } |
| | | }, |
| | | watch: { |
| | | // 监听数据变化 ,暂时不使用,需要单独赋值 |
| | | // localData: {}, |
| | | // 监听规则变化 |
| | | rules: { |
| | | handler: function(val, oldVal) { |
| | | this.setRules(val) |
| | | }, |
| | | deep: true, |
| | | immediate: true |
| | | } |
| | | }, |
| | | created() { |
| | | // #ifdef VUE3 |
| | | let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata |
| | | if (!getbinddata) { |
| | | getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) { |
| | | if (formName) { |
| | | this.$refs[formName].setValue(name, value); |
| | | } else { |
| | | let formVm; |
| | | for (let i in this.$refs) { |
| | | const vm = this.$refs[i]; |
| | | if (vm && vm.$options && vm.$options.name === 'uniForms') { |
| | | formVm = vm; |
| | | break; |
| | | } |
| | | } |
| | | if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性'); |
| | | formVm.setValue(name, value); |
| | | } |
| | | } |
| | | } |
| | | // #endif |
| | | |
| | | // 子组件实例数组 |
| | | this.childrens = [] |
| | | // TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错 |
| | | this.inputChildrens = [] |
| | | this.setRules(this.rules) |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 外部调用方法 |
| | | * 设置规则 ,主要用于小程序自定义检验规则 |
| | | * @param {Array} rules 规则源数据 |
| | | */ |
| | | setRules(rules) { |
| | | // TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖 |
| | | this.formRules = Object.assign({}, this.formRules, rules) |
| | | // 初始化校验函数 |
| | | this.validator = new Validator(rules); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用 |
| | | * @param {Object} key |
| | | * @param {Object} value |
| | | */ |
| | | setValue(key, value) { |
| | | let example = this.childrens.find(child => child.name === key); |
| | | if (!example) return null; |
| | | this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || []) |
| | | return example.onFieldChange(this.formData[key]); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 手动提交校验表单 |
| | | * 对整个表单进行校验的方法,参数为一个回调函数。 |
| | | * @param {Array} keepitem 保留不参与校验的字段 |
| | | * @param {type} callback 方法回调 |
| | | */ |
| | | validate(keepitem, callback) { |
| | | return this.checkAll(this.formData, keepitem, callback); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 部分表单校验 |
| | | * @param {Array|String} props 需要校验的字段 |
| | | * @param {Function} 回调函数 |
| | | */ |
| | | validateField(props = [], callback) { |
| | | props = [].concat(props); |
| | | let invalidFields = {}; |
| | | this.childrens.forEach(item => { |
| | | const name = realName(item.name) |
| | | if (props.indexOf(name) !== -1) { |
| | | invalidFields = Object.assign({}, invalidFields, { |
| | | [name]: this.formData[name] |
| | | }); |
| | | } |
| | | }); |
| | | return this.checkAll(invalidFields, [], callback); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果 |
| | | * @param {Array|String} props 需要移除校验的字段 ,不填为所有 |
| | | */ |
| | | clearValidate(props = []) { |
| | | props = [].concat(props); |
| | | this.childrens.forEach(item => { |
| | | if (props.length === 0) { |
| | | item.errMsg = ''; |
| | | } else { |
| | | const name = realName(item.name) |
| | | if (props.indexOf(name) !== -1) { |
| | | item.errMsg = ''; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 ,即将废弃 |
| | | * 手动提交校验表单 |
| | | * 对整个表单进行校验的方法,参数为一个回调函数。 |
| | | * @param {Array} keepitem 保留不参与校验的字段 |
| | | * @param {type} callback 方法回调 |
| | | */ |
| | | submit(keepitem, callback, type) { |
| | | for (let i in this.dataValue) { |
| | | const itemData = this.childrens.find(v => v.name === i); |
| | | if (itemData) { |
| | | if (this.formData[i] === undefined) { |
| | | this.formData[i] = this._getValue(i, this.dataValue[i]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!type) { |
| | | console.warn('submit 方法即将废弃,请使用validate方法代替!'); |
| | | } |
| | | |
| | | return this.checkAll(this.formData, keepitem, callback, 'submit'); |
| | | }, |
| | | |
| | | // 校验所有 |
| | | async checkAll(invalidFields, keepitem, callback, type) { |
| | | // 不存在校验规则 ,则停止校验流程 |
| | | if (!this.validator) return |
| | | let childrens = [] |
| | | // 处理参与校验的item实例 |
| | | for (let i in invalidFields) { |
| | | const item = this.childrens.find(v => realName(v.name) === i) |
| | | if (item) { |
| | | childrens.push(item) |
| | | } |
| | | } |
| | | |
| | | // 如果validate第一个参数是funciont ,那就走回调 |
| | | if (!callback && typeof keepitem === 'function') { |
| | | callback = keepitem; |
| | | } |
| | | |
| | | let promise; |
| | | // 如果不存在回调,那么使用 Promise 方式返回 |
| | | if (!callback && typeof callback !== 'function' && Promise) { |
| | | promise = new Promise((resolve, reject) => { |
| | | callback = function(valid, invalidFields) { |
| | | !valid ? resolve(invalidFields) : reject(valid); |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | let results = []; |
| | | // 避免引用错乱 ,建议拷贝对象处理 |
| | | let tempFormData = JSON.parse(JSON.stringify(invalidFields)) |
| | | // 所有子组件参与校验,使用 for 可以使用 awiat |
| | | for (let i in childrens) { |
| | | const child = childrens[i] |
| | | let name = realName(child.name); |
| | | const result = await child.onFieldChange(tempFormData[name]); |
| | | if (result) { |
| | | results.push(result); |
| | | // toast ,modal 只需要执行第一次就可以 |
| | | if (this.errShowType === 'toast' || this.errShowType === 'modal') break; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (Array.isArray(results)) { |
| | | if (results.length === 0) results = null; |
| | | } |
| | | if (Array.isArray(keepitem)) { |
| | | keepitem.forEach(v => { |
| | | let vName = realName(v); |
| | | let value = getDataValue(v, this.localData) |
| | | if (value !== undefined) { |
| | | tempFormData[vName] = value |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // TODO submit 即将废弃 |
| | | if (type === 'submit') { |
| | | this.$emit('submit', { |
| | | detail: { |
| | | value: tempFormData, |
| | | errors: results |
| | | } |
| | | }); |
| | | } else { |
| | | this.$emit('validate', results); |
| | | } |
| | | |
| | | // const resetFormData = rawData(tempFormData, this.localData, this.name) |
| | | let resetFormData = {} |
| | | resetFormData = rawData(tempFormData, this.name) |
| | | callback && typeof callback === 'function' && callback(results, resetFormData); |
| | | |
| | | if (promise && callback) { |
| | | return promise; |
| | | } else { |
| | | return null; |
| | | } |
| | | |
| | | }, |
| | | |
| | | /** |
| | | * 返回validate事件 |
| | | * @param {Object} result |
| | | */ |
| | | validateCheck(result) { |
| | | this.$emit('validate', result); |
| | | }, |
| | | _getValue: getValue, |
| | | _isRequiredField: isRequiredField, |
| | | _setDataValue: setDataValue, |
| | | _getDataValue: getDataValue, |
| | | _realName: realName, |
| | | _isRealName: isRealName, |
| | | _isEqual: isEqual |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-forms {} |
| | | </style> |
uni_modules/uni-forms/components/uni-forms/utils.js
uni_modules/uni-forms/components/uni-forms/validate.js
uni_modules/uni-forms/package.json
uni_modules/uni-forms/readme.md
uni_modules/uni-goods-nav/changelog.md
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
uni_modules/uni-goods-nav/package.json
uni_modules/uni-goods-nav/readme.md
uni_modules/uni-grid/changelog.md
uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
uni_modules/uni-grid/components/uni-grid/uni-grid.vue
uni_modules/uni-grid/package.json
uni_modules/uni-grid/readme.md
uni_modules/uni-group/changelog.md
uni_modules/uni-group/components/uni-group/uni-group.vue
uni_modules/uni-group/package.json
uni_modules/uni-group/readme.md
uni_modules/uni-icons/changelog.md
uni_modules/uni-icons/components/uni-icons/icons.js
uni_modules/uni-icons/components/uni-icons/uni-icons.vue
uni_modules/uni-icons/components/uni-icons/uniicons.css
uni_modules/uni-icons/components/uni-icons/uniicons.ttf
uni_modules/uni-icons/package.json
uni_modules/uni-icons/readme.md
uni_modules/uni-indexed-list/changelog.md
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
uni_modules/uni-indexed-list/package.json
uni_modules/uni-indexed-list/readme.md
uni_modules/uni-link/changelog.md
uni_modules/uni-link/components/uni-link/uni-link.vue
uni_modules/uni-link/package.json
uni_modules/uni-link/readme.md
uni_modules/uni-list/changelog.md
uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
uni_modules/uni-list/components/uni-list/uni-list.vue
uni_modules/uni-list/components/uni-list/uni-refresh.vue
uni_modules/uni-list/components/uni-list/uni-refresh.wxs
uni_modules/uni-list/package.json
uni_modules/uni-list/readme.md
uni_modules/uni-load-more/changelog.md
uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
uni_modules/uni-load-more/package.json
uni_modules/uni-load-more/readme.md
uni_modules/uni-nav-bar/changelog.md
uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
uni_modules/uni-nav-bar/package.json
uni_modules/uni-nav-bar/readme.md
uni_modules/uni-notice-bar/changelog.md
uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
uni_modules/uni-notice-bar/package.json
uni_modules/uni-notice-bar/readme.md
uni_modules/uni-number-box/changelog.md
uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
uni_modules/uni-number-box/package.json
uni_modules/uni-number-box/readme.md
uni_modules/uni-pagination/changelog.md
uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
uni_modules/uni-pagination/package.json
uni_modules/uni-pagination/readme.md
uni_modules/uni-popup/changelog.md
uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
uni_modules/uni-popup/components/uni-popup/i18n/en.json
uni_modules/uni-popup/components/uni-popup/i18n/index.js
uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
uni_modules/uni-popup/components/uni-popup/keypress.js
uni_modules/uni-popup/components/uni-popup/popup.js
uni_modules/uni-popup/components/uni-popup/uni-popup.vue
uni_modules/uni-popup/package.json
uni_modules/uni-popup/readme.md
uni_modules/uni-rate/changelog.md
uni_modules/uni-rate/components/uni-rate/uni-rate.vue
uni_modules/uni-rate/package.json
uni_modules/uni-rate/readme.md
uni_modules/uni-row/changelog.md
uni_modules/uni-row/components/uni-col/uni-col.vue
uni_modules/uni-row/components/uni-row/uni-row.vue
uni_modules/uni-row/package.json
uni_modules/uni-row/readme.md
uni_modules/uni-scss/changelog.md
uni_modules/uni-scss/index.scss
uni_modules/uni-scss/package.json
uni_modules/uni-scss/readme.md
uni_modules/uni-scss/styles/index.scss
uni_modules/uni-scss/styles/setting/_border.scss
uni_modules/uni-scss/styles/setting/_color.scss
uni_modules/uni-scss/styles/setting/_radius.scss
uni_modules/uni-scss/styles/setting/_space.scss
uni_modules/uni-scss/styles/setting/_styles.scss
uni_modules/uni-scss/styles/setting/_text.scss
uni_modules/uni-scss/styles/setting/_variables.scss
uni_modules/uni-scss/styles/tools/functions.scss
uni_modules/uni-scss/theme.scss
uni_modules/uni-scss/variables.scss
uni_modules/uni-search-bar/changelog.md
uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
uni_modules/uni-search-bar/package.json
uni_modules/uni-search-bar/readme.md
uni_modules/uni-section/changelog.md
uni_modules/uni-section/components/uni-section/uni-section.vue
uni_modules/uni-section/package.json
uni_modules/uni-section/readme.md
uni_modules/uni-segmented-control/changelog.md
uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
uni_modules/uni-segmented-control/package.json
uni_modules/uni-segmented-control/readme.md
uni_modules/uni-steps/changelog.md
uni_modules/uni-steps/components/uni-steps/uni-steps.vue
uni_modules/uni-steps/package.json
uni_modules/uni-steps/readme.md
uni_modules/uni-swipe-action/changelog.md
uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
uni_modules/uni-swipe-action/package.json
uni_modules/uni-swipe-action/readme.md
uni_modules/uni-swiper-dot/changelog.md
uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
uni_modules/uni-swiper-dot/package.json
uni_modules/uni-swiper-dot/readme.md
uni_modules/uni-table/changelog.md
uni_modules/uni-table/components/uni-table/uni-table.vue
uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
uni_modules/uni-table/components/uni-td/uni-td.vue
uni_modules/uni-table/components/uni-th/filter-dropdown.vue
uni_modules/uni-table/components/uni-th/uni-th.vue
uni_modules/uni-table/components/uni-thead/uni-thead.vue
uni_modules/uni-table/components/uni-tr/table-checkbox.vue
uni_modules/uni-table/components/uni-tr/uni-tr.vue
uni_modules/uni-table/i18n/en.json
uni_modules/uni-table/i18n/es.json
uni_modules/uni-table/i18n/fr.json
uni_modules/uni-table/i18n/index.js
uni_modules/uni-table/i18n/zh-Hans.json
uni_modules/uni-table/i18n/zh-Hant.json
uni_modules/uni-table/package.json
uni_modules/uni-table/readme.md
uni_modules/uni-tag/changelog.md
uni_modules/uni-tag/components/uni-tag/uni-tag.vue
uni_modules/uni-tag/package.json
uni_modules/uni-tag/readme.md
uni_modules/uni-test/changelog.md
uni_modules/uni-test/components/uni-test/uni-test.vue
uni_modules/uni-test/package.json
uni_modules/uni-test/readme.md
uni_modules/uni-title/changelog.md
uni_modules/uni-title/components/uni-title/uni-title.vue
uni_modules/uni-title/package.json
uni_modules/uni-title/readme.md
uni_modules/uni-tooltip/changelog.md
uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
uni_modules/uni-tooltip/package.json
uni_modules/uni-tooltip/readme.md
uni_modules/uni-transition/changelog.md
uni_modules/uni-transition/components/uni-transition/createAnimation.js
uni_modules/uni-transition/components/uni-transition/uni-transition.vue
uni_modules/uni-transition/package.json
uni_modules/uni-transition/readme.md
uni_modules/uni-ui/changelog.md
uni_modules/uni-ui/components/uni-ui/uni-ui.vue
uni_modules/uni-ui/package.json
uni_modules/uni-ui/readme.md
uni_modules/uview-ui/LICENSE
uni_modules/uview-ui/README.md
uni_modules/uview-ui/changelog.md
uni_modules/uview-ui/components/u--form/u--form.vue
uni_modules/uview-ui/components/u--image/u--image.vue
uni_modules/uview-ui/components/u--input/u--input.vue
uni_modules/uview-ui/components/u--text/u--text.vue
uni_modules/uview-ui/components/u--textarea/u--textarea.vue
uni_modules/uview-ui/components/u-action-sheet/props.js
uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
uni_modules/uview-ui/components/u-album/props.js
uni_modules/uview-ui/components/u-album/u-album.vue
uni_modules/uview-ui/components/u-alert/props.js
uni_modules/uview-ui/components/u-alert/u-alert.vue
uni_modules/uview-ui/components/u-avatar-group/props.js
uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue
uni_modules/uview-ui/components/u-avatar/props.js
uni_modules/uview-ui/components/u-avatar/u-avatar.vue
uni_modules/uview-ui/components/u-back-top/props.js
uni_modules/uview-ui/components/u-back-top/u-back-top.vue
uni_modules/uview-ui/components/u-badge/props.js
uni_modules/uview-ui/components/u-badge/u-badge.vue
uni_modules/uview-ui/components/u-button/nvue.scss
uni_modules/uview-ui/components/u-button/props.js
uni_modules/uview-ui/components/u-button/u-button.vue
uni_modules/uview-ui/components/u-button/vue.scss
uni_modules/uview-ui/components/u-calendar/header.vue
uni_modules/uview-ui/components/u-calendar/month.vue
uni_modules/uview-ui/components/u-calendar/props.js
uni_modules/uview-ui/components/u-calendar/u-calendar.vue
uni_modules/uview-ui/components/u-calendar/util.js
uni_modules/uview-ui/components/u-car-keyboard/props.js
uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue
uni_modules/uview-ui/components/u-cell-group/props.js
uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue
uni_modules/uview-ui/components/u-cell/props.js
uni_modules/uview-ui/components/u-cell/u-cell.vue
uni_modules/uview-ui/components/u-checkbox-group/props.js
uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
uni_modules/uview-ui/components/u-checkbox/props.js
uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue
uni_modules/uview-ui/components/u-circle-progress/props.js
uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue
uni_modules/uview-ui/components/u-code-input/props.js
uni_modules/uview-ui/components/u-code-input/u-code-input.vue
uni_modules/uview-ui/components/u-code/props.js
uni_modules/uview-ui/components/u-code/u-code.vue
uni_modules/uview-ui/components/u-col/props.js
uni_modules/uview-ui/components/u-col/u-col.vue
uni_modules/uview-ui/components/u-collapse-item/props.js
uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue
uni_modules/uview-ui/components/u-collapse/props.js
uni_modules/uview-ui/components/u-collapse/u-collapse.vue
uni_modules/uview-ui/components/u-column-notice/props.js
uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue
uni_modules/uview-ui/components/u-count-down/props.js
uni_modules/uview-ui/components/u-count-down/u-count-down.vue
uni_modules/uview-ui/components/u-count-down/utils.js
uni_modules/uview-ui/components/u-count-to/props.js
uni_modules/uview-ui/components/u-count-to/u-count-to.vue
uni_modules/uview-ui/components/u-datetime-picker/props.js
uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue
uni_modules/uview-ui/components/u-divider/props.js
uni_modules/uview-ui/components/u-divider/u-divider.vue
uni_modules/uview-ui/components/u-dropdown-item/props.js
uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue
uni_modules/uview-ui/components/u-dropdown/props.js
uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue
uni_modules/uview-ui/components/u-empty/props.js
uni_modules/uview-ui/components/u-empty/u-empty.vue
uni_modules/uview-ui/components/u-form-item/props.js
uni_modules/uview-ui/components/u-form-item/u-form-item.vue
uni_modules/uview-ui/components/u-form/props.js
uni_modules/uview-ui/components/u-form/u-form.vue
uni_modules/uview-ui/components/u-gap/props.js
uni_modules/uview-ui/components/u-gap/u-gap.vue
uni_modules/uview-ui/components/u-grid-item/props.js
uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue
uni_modules/uview-ui/components/u-grid/props.js
uni_modules/uview-ui/components/u-grid/u-grid.vue
uni_modules/uview-ui/components/u-icon/icons.js
uni_modules/uview-ui/components/u-icon/props.js
uni_modules/uview-ui/components/u-icon/u-icon.vue
uni_modules/uview-ui/components/u-image/props.js
uni_modules/uview-ui/components/u-image/u-image.vue
uni_modules/uview-ui/components/u-index-anchor/props.js
uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue
uni_modules/uview-ui/components/u-index-item/props.js
uni_modules/uview-ui/components/u-index-item/u-index-item.vue
uni_modules/uview-ui/components/u-index-list/props.js
uni_modules/uview-ui/components/u-index-list/u-index-list.vue
uni_modules/uview-ui/components/u-input/props.js
uni_modules/uview-ui/components/u-input/u-input.vue
uni_modules/uview-ui/components/u-keyboard/props.js
uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue
uni_modules/uview-ui/components/u-line-progress/props.js
uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue
uni_modules/uview-ui/components/u-line/props.js
uni_modules/uview-ui/components/u-line/u-line.vue
uni_modules/uview-ui/components/u-link/props.js
uni_modules/uview-ui/components/u-link/u-link.vue
uni_modules/uview-ui/components/u-list-item/props.js
uni_modules/uview-ui/components/u-list-item/u-list-item.vue
uni_modules/uview-ui/components/u-list/props.js
uni_modules/uview-ui/components/u-list/u-list.vue
uni_modules/uview-ui/components/u-loading-icon/props.js
uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue
uni_modules/uview-ui/components/u-loading-page/props.js
uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue
uni_modules/uview-ui/components/u-loadmore/props.js
uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue
uni_modules/uview-ui/components/u-modal/props.js
uni_modules/uview-ui/components/u-modal/u-modal.vue
uni_modules/uview-ui/components/u-navbar/props.js
uni_modules/uview-ui/components/u-navbar/u-navbar.vue
uni_modules/uview-ui/components/u-no-network/props.js
uni_modules/uview-ui/components/u-no-network/u-no-network.vue
uni_modules/uview-ui/components/u-notice-bar/props.js
uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue
uni_modules/uview-ui/components/u-notify/props.js
uni_modules/uview-ui/components/u-notify/u-notify.vue
uni_modules/uview-ui/components/u-number-box/props.js
uni_modules/uview-ui/components/u-number-box/u-number-box.vue
uni_modules/uview-ui/components/u-number-keyboard/props.js
uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue
uni_modules/uview-ui/components/u-overlay/props.js
uni_modules/uview-ui/components/u-overlay/u-overlay.vue
uni_modules/uview-ui/components/u-parse/node/node.vue
uni_modules/uview-ui/components/u-parse/parser.js
uni_modules/uview-ui/components/u-parse/props.js
uni_modules/uview-ui/components/u-parse/u-parse.vue
uni_modules/uview-ui/components/u-picker-column/props.js
uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue
uni_modules/uview-ui/components/u-picker/props.js
uni_modules/uview-ui/components/u-picker/u-picker.vue
uni_modules/uview-ui/components/u-popup/props.js
uni_modules/uview-ui/components/u-popup/u-popup.vue
uni_modules/uview-ui/components/u-radio-group/props.js
uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue
uni_modules/uview-ui/components/u-radio/props.js
uni_modules/uview-ui/components/u-radio/u-radio.vue
uni_modules/uview-ui/components/u-rate/props.js
uni_modules/uview-ui/components/u-rate/u-rate.vue
uni_modules/uview-ui/components/u-read-more/props.js
uni_modules/uview-ui/components/u-read-more/u-read-more.vue
uni_modules/uview-ui/components/u-row-notice/props.js
uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue
uni_modules/uview-ui/components/u-row/props.js
uni_modules/uview-ui/components/u-row/u-row.vue
uni_modules/uview-ui/components/u-safe-bottom/props.js
uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue
uni_modules/uview-ui/components/u-scroll-list/nvue.js
uni_modules/uview-ui/components/u-scroll-list/other.js
uni_modules/uview-ui/components/u-scroll-list/props.js
uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs
uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue
uni_modules/uview-ui/components/u-search/props.js
uni_modules/uview-ui/components/u-search/u-search.vue
uni_modules/uview-ui/components/u-skeleton/props.js
uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue
uni_modules/uview-ui/components/u-slider/mpother.js
uni_modules/uview-ui/components/u-slider/mpwxs.js
uni_modules/uview-ui/components/u-slider/mpwxs.wxs
uni_modules/uview-ui/components/u-slider/nvue - 副本.js
uni_modules/uview-ui/components/u-slider/nvue.js
uni_modules/uview-ui/components/u-slider/props.js
uni_modules/uview-ui/components/u-slider/u-slider.vue
uni_modules/uview-ui/components/u-status-bar/props.js
uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue
uni_modules/uview-ui/components/u-steps-item/props.js
uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue
uni_modules/uview-ui/components/u-steps/props.js
uni_modules/uview-ui/components/u-steps/u-steps.vue
uni_modules/uview-ui/components/u-sticky/props.js
uni_modules/uview-ui/components/u-sticky/u-sticky.vue
uni_modules/uview-ui/components/u-subsection/props.js
uni_modules/uview-ui/components/u-subsection/u-subsection.vue
uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs
uni_modules/uview-ui/components/u-swipe-action-item/index.wxs
uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js
uni_modules/uview-ui/components/u-swipe-action-item/nvue.js
uni_modules/uview-ui/components/u-swipe-action-item/props.js
uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue
uni_modules/uview-ui/components/u-swipe-action-item/wxs.js
uni_modules/uview-ui/components/u-swipe-action/props.js
uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue
uni_modules/uview-ui/components/u-swiper-indicator/props.js
uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue
uni_modules/uview-ui/components/u-swiper/props.js
uni_modules/uview-ui/components/u-swiper/u-swiper.vue
uni_modules/uview-ui/components/u-switch/props.js
uni_modules/uview-ui/components/u-switch/u-switch.vue
uni_modules/uview-ui/components/u-tabbar-item/props.js
uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue
uni_modules/uview-ui/components/u-tabbar/props.js
uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue
uni_modules/uview-ui/components/u-table/props.js
uni_modules/uview-ui/components/u-table/u-table.vue
uni_modules/uview-ui/components/u-tabs-item/props.js
uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue
uni_modules/uview-ui/components/u-tabs/props.js
uni_modules/uview-ui/components/u-tabs/u-tabs.vue
uni_modules/uview-ui/components/u-tag/props.js
uni_modules/uview-ui/components/u-tag/u-tag.vue
uni_modules/uview-ui/components/u-td/props.js
uni_modules/uview-ui/components/u-td/u-td.vue
uni_modules/uview-ui/components/u-text/props.js
uni_modules/uview-ui/components/u-text/u-text.vue
uni_modules/uview-ui/components/u-text/value.js
uni_modules/uview-ui/components/u-textarea/props.js
uni_modules/uview-ui/components/u-textarea/u-textarea.vue
uni_modules/uview-ui/components/u-toast/u-toast.vue
uni_modules/uview-ui/components/u-toolbar/props.js
uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue
uni_modules/uview-ui/components/u-tooltip/clipboard.min.js
uni_modules/uview-ui/components/u-tooltip/props.js
uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue
uni_modules/uview-ui/components/u-tr/props.js
uni_modules/uview-ui/components/u-tr/u-tr.vue
uni_modules/uview-ui/components/u-transition/nvue.ani-map.js
uni_modules/uview-ui/components/u-transition/props.js
uni_modules/uview-ui/components/u-transition/transition.js
uni_modules/uview-ui/components/u-transition/u-transition.vue
uni_modules/uview-ui/components/u-transition/vue.ani-style.scss
uni_modules/uview-ui/components/u-upload/mixin.js
uni_modules/uview-ui/components/u-upload/props.js
uni_modules/uview-ui/components/u-upload/u-upload.vue
uni_modules/uview-ui/components/u-upload/utils.js
uni_modules/uview-ui/components/uview-ui/uview-ui.vue
uni_modules/uview-ui/index.js
uni_modules/uview-ui/index.scss
uni_modules/uview-ui/libs/config/color.js
uni_modules/uview-ui/libs/config/config.js
uni_modules/uview-ui/libs/config/props.js
uni_modules/uview-ui/libs/config/props/actionSheet.js
uni_modules/uview-ui/libs/config/props/album.js
uni_modules/uview-ui/libs/config/props/alert.js
uni_modules/uview-ui/libs/config/props/avatar.js
uni_modules/uview-ui/libs/config/props/avatarGroup.js
uni_modules/uview-ui/libs/config/props/backtop.js
uni_modules/uview-ui/libs/config/props/badge.js
uni_modules/uview-ui/libs/config/props/button.js
uni_modules/uview-ui/libs/config/props/calendar.js
uni_modules/uview-ui/libs/config/props/carKeyboard.js
uni_modules/uview-ui/libs/config/props/cell.js
uni_modules/uview-ui/libs/config/props/cellGroup.js
uni_modules/uview-ui/libs/config/props/checkbox.js
uni_modules/uview-ui/libs/config/props/checkboxGroup.js
uni_modules/uview-ui/libs/config/props/circleProgress.js
uni_modules/uview-ui/libs/config/props/code.js
uni_modules/uview-ui/libs/config/props/codeInput.js
uni_modules/uview-ui/libs/config/props/col.js
uni_modules/uview-ui/libs/config/props/collapse.js
uni_modules/uview-ui/libs/config/props/collapseItem.js
uni_modules/uview-ui/libs/config/props/columnNotice.js
uni_modules/uview-ui/libs/config/props/countDown.js
uni_modules/uview-ui/libs/config/props/countTo.js
uni_modules/uview-ui/libs/config/props/datetimePicker.js
uni_modules/uview-ui/libs/config/props/divider.js
uni_modules/uview-ui/libs/config/props/empty.js
uni_modules/uview-ui/libs/config/props/form.js
uni_modules/uview-ui/libs/config/props/formItem.js
uni_modules/uview-ui/libs/config/props/gap.js
uni_modules/uview-ui/libs/config/props/grid.js
uni_modules/uview-ui/libs/config/props/gridItem.js
uni_modules/uview-ui/libs/config/props/icon.js
uni_modules/uview-ui/libs/config/props/image.js
uni_modules/uview-ui/libs/config/props/indexAnchor.js
uni_modules/uview-ui/libs/config/props/indexList.js
uni_modules/uview-ui/libs/config/props/input.js
uni_modules/uview-ui/libs/config/props/keyboard.js
uni_modules/uview-ui/libs/config/props/line.js
uni_modules/uview-ui/libs/config/props/lineProgress.js
uni_modules/uview-ui/libs/config/props/link.js
uni_modules/uview-ui/libs/config/props/list.js
uni_modules/uview-ui/libs/config/props/listItem.js
uni_modules/uview-ui/libs/config/props/loadingIcon.js
uni_modules/uview-ui/libs/config/props/loadingPage.js
uni_modules/uview-ui/libs/config/props/loadmore.js
uni_modules/uview-ui/libs/config/props/modal.js
uni_modules/uview-ui/libs/config/props/navbar.js
uni_modules/uview-ui/libs/config/props/noNetwork.js
uni_modules/uview-ui/libs/config/props/noticeBar.js
uni_modules/uview-ui/libs/config/props/notify.js
uni_modules/uview-ui/libs/config/props/numberBox.js
uni_modules/uview-ui/libs/config/props/numberKeyboard.js
uni_modules/uview-ui/libs/config/props/overlay.js
uni_modules/uview-ui/libs/config/props/parse.js
uni_modules/uview-ui/libs/config/props/picker.js
uni_modules/uview-ui/libs/config/props/popup.js
uni_modules/uview-ui/libs/config/props/radio.js
uni_modules/uview-ui/libs/config/props/radioGroup.js
uni_modules/uview-ui/libs/config/props/rate.js
uni_modules/uview-ui/libs/config/props/readMore.js
uni_modules/uview-ui/libs/config/props/row.js
uni_modules/uview-ui/libs/config/props/rowNotice.js
uni_modules/uview-ui/libs/config/props/scrollList.js
uni_modules/uview-ui/libs/config/props/search.js
uni_modules/uview-ui/libs/config/props/section.js
uni_modules/uview-ui/libs/config/props/skeleton.js
uni_modules/uview-ui/libs/config/props/slider.js
uni_modules/uview-ui/libs/config/props/statusBar.js
uni_modules/uview-ui/libs/config/props/steps.js
uni_modules/uview-ui/libs/config/props/stepsItem.js
uni_modules/uview-ui/libs/config/props/sticky.js
uni_modules/uview-ui/libs/config/props/subsection.js
uni_modules/uview-ui/libs/config/props/swipeAction.js
uni_modules/uview-ui/libs/config/props/swipeActionItem.js
uni_modules/uview-ui/libs/config/props/swiper.js
uni_modules/uview-ui/libs/config/props/swipterIndicator.js
uni_modules/uview-ui/libs/config/props/switch.js
uni_modules/uview-ui/libs/config/props/tabbar.js
uni_modules/uview-ui/libs/config/props/tabbarItem.js
uni_modules/uview-ui/libs/config/props/tabs.js
uni_modules/uview-ui/libs/config/props/tag.js
uni_modules/uview-ui/libs/config/props/text.js
uni_modules/uview-ui/libs/config/props/textarea.js
uni_modules/uview-ui/libs/config/props/toast.js
uni_modules/uview-ui/libs/config/props/toolbar.js
uni_modules/uview-ui/libs/config/props/tooltip.js
uni_modules/uview-ui/libs/config/props/transition.js
uni_modules/uview-ui/libs/config/props/upload.js
uni_modules/uview-ui/libs/config/zIndex.js
uni_modules/uview-ui/libs/css/color.scss
uni_modules/uview-ui/libs/css/common.scss
uni_modules/uview-ui/libs/css/components.scss
uni_modules/uview-ui/libs/css/flex.scss
uni_modules/uview-ui/libs/css/h5.scss
uni_modules/uview-ui/libs/css/mixin.scss
uni_modules/uview-ui/libs/css/mp.scss
uni_modules/uview-ui/libs/css/nvue.scss
uni_modules/uview-ui/libs/css/vue.scss
uni_modules/uview-ui/libs/function/colorGradient.js
uni_modules/uview-ui/libs/function/debounce.js
uni_modules/uview-ui/libs/function/digit.js
uni_modules/uview-ui/libs/function/index.js
uni_modules/uview-ui/libs/function/platform.js
uni_modules/uview-ui/libs/function/test.js
uni_modules/uview-ui/libs/function/throttle.js
uni_modules/uview-ui/libs/luch-request/adapters/index.js
uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js
uni_modules/uview-ui/libs/luch-request/core/Request.js
uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js
uni_modules/uview-ui/libs/luch-request/core/defaults.js
uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js
uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js
uni_modules/uview-ui/libs/luch-request/core/settle.js
uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js
uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js
uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js
uni_modules/uview-ui/libs/luch-request/index.d.ts
uni_modules/uview-ui/libs/luch-request/index.js
uni_modules/uview-ui/libs/luch-request/utils.js
uni_modules/uview-ui/libs/luch-request/utils/clone.js
uni_modules/uview-ui/libs/mixin/button.js
uni_modules/uview-ui/libs/mixin/mixin.js
uni_modules/uview-ui/libs/mixin/mpMixin.js
uni_modules/uview-ui/libs/mixin/mpShare.js
uni_modules/uview-ui/libs/mixin/openType.js
uni_modules/uview-ui/libs/mixin/style.js
uni_modules/uview-ui/libs/mixin/touch.js
uni_modules/uview-ui/libs/util/async-validator.js
uni_modules/uview-ui/libs/util/calendar.js
uni_modules/uview-ui/libs/util/dayjs.js
uni_modules/uview-ui/libs/util/emitter.js
uni_modules/uview-ui/libs/util/route.js
uni_modules/uview-ui/package.json
uni_modules/uview-ui/theme.scss
unpackage/cache/apk/__UNI__843A1A3_cm.apk
unpackage/cache/apk/apkurl
unpackage/cache/apk/cmManifestCache.json
unpackage/cache/certdata
unpackage/cache/cloudcertificate/certini
unpackage/cache/cloudcertificate/package.keystore
unpackage/cache/wgt/__UNI__843A1A3/.manifest/icon-android-hdpi.png
unpackage/cache/wgt/__UNI__843A1A3/.manifest/icon-android-xhdpi.png
unpackage/cache/wgt/__UNI__843A1A3/.manifest/icon-android-xxhdpi.png
unpackage/cache/wgt/__UNI__843A1A3/.manifest/icon-android-xxxhdpi.png
unpackage/cache/wgt/__UNI__843A1A3/__uniappchooselocation.js
unpackage/cache/wgt/__UNI__843A1A3/__uniapperror.png
unpackage/cache/wgt/__UNI__843A1A3/__uniappes6.js
unpackage/cache/wgt/__UNI__843A1A3/__uniappopenlocation.js
unpackage/cache/wgt/__UNI__843A1A3/__uniapppicker.js
unpackage/cache/wgt/__UNI__843A1A3/__uniappquill.js
unpackage/cache/wgt/__UNI__843A1A3/__uniappquillimageresize.js
unpackage/cache/wgt/__UNI__843A1A3/__uniappscan.js
unpackage/cache/wgt/__UNI__843A1A3/__uniappsuccess.png
unpackage/cache/wgt/__UNI__843A1A3/__uniappview.html
unpackage/cache/wgt/__UNI__843A1A3/app-config-service.js
unpackage/cache/wgt/__UNI__843A1A3/app-config.js
unpackage/cache/wgt/__UNI__843A1A3/app-service.js
unpackage/cache/wgt/__UNI__843A1A3/app-view.js
unpackage/cache/wgt/__UNI__843A1A3/manifest.json
unpackage/cache/wgt/__UNI__843A1A3/static/bg.jpeg
unpackage/cache/wgt/__UNI__843A1A3/static/c1.png
unpackage/cache/wgt/__UNI__843A1A3/static/c2.png
unpackage/cache/wgt/__UNI__843A1A3/static/c3.png
unpackage/cache/wgt/__UNI__843A1A3/static/c4.png
unpackage/cache/wgt/__UNI__843A1A3/static/c5.png
unpackage/cache/wgt/__UNI__843A1A3/static/c6.png
unpackage/cache/wgt/__UNI__843A1A3/static/c7.png
unpackage/cache/wgt/__UNI__843A1A3/static/c8.png
unpackage/cache/wgt/__UNI__843A1A3/static/c9.png
unpackage/cache/wgt/__UNI__843A1A3/static/customicons.css
unpackage/cache/wgt/__UNI__843A1A3/static/customicons.ttf
unpackage/cache/wgt/__UNI__843A1A3/static/logo.png
unpackage/cache/wgt/__UNI__843A1A3/static/mine1-selected.png
unpackage/cache/wgt/__UNI__843A1A3/static/mine1.png
unpackage/cache/wgt/__UNI__843A1A3/static/notice1-selected.png
unpackage/cache/wgt/__UNI__843A1A3/static/notice1.png
unpackage/cache/wgt/__UNI__843A1A3/static/uni.png
unpackage/cache/wgt/__UNI__843A1A3/view.css
unpackage/cache/wgt/__UNI__843A1A3/view.umd.min.js
unpackage/dist/build/.automator/app-plus/.automator.json
unpackage/dist/build/app-plus/__uniappchooselocation.js
unpackage/dist/build/app-plus/__uniapperror.png
unpackage/dist/build/app-plus/__uniappes6.js
unpackage/dist/build/app-plus/__uniappopenlocation.js
unpackage/dist/build/app-plus/__uniapppicker.js
unpackage/dist/build/app-plus/__uniappquill.js
unpackage/dist/build/app-plus/__uniappquillimageresize.js
unpackage/dist/build/app-plus/__uniappscan.js
unpackage/dist/build/app-plus/__uniappsuccess.png
unpackage/dist/build/app-plus/__uniappview.html
unpackage/dist/build/app-plus/app-config-service.js
unpackage/dist/build/app-plus/app-config.js
unpackage/dist/build/app-plus/app-service.js
unpackage/dist/build/app-plus/app-view.js
unpackage/dist/build/app-plus/manifest.json
unpackage/dist/build/app-plus/static/bg.jpeg
unpackage/dist/build/app-plus/static/c1.png
unpackage/dist/build/app-plus/static/c2.png
unpackage/dist/build/app-plus/static/c3.png
unpackage/dist/build/app-plus/static/c4.png
unpackage/dist/build/app-plus/static/c5.png
unpackage/dist/build/app-plus/static/c6.png
unpackage/dist/build/app-plus/static/c7.png
unpackage/dist/build/app-plus/static/c8.png
unpackage/dist/build/app-plus/static/c9.png
unpackage/dist/build/app-plus/static/customicons.css
unpackage/dist/build/app-plus/static/customicons.ttf
unpackage/dist/build/app-plus/static/logo.png
unpackage/dist/build/app-plus/static/mine1-selected.png
unpackage/dist/build/app-plus/static/mine1.png
unpackage/dist/build/app-plus/static/notice1-selected.png
unpackage/dist/build/app-plus/static/notice1.png
unpackage/dist/build/app-plus/static/uni.png
unpackage/dist/build/app-plus/view.css
unpackage/dist/build/app-plus/view.umd.min.js
unpackage/dist/dev/.automator/app-plus/.automator.json
unpackage/dist/dev/app-plus/__uniappchooselocation.js
unpackage/dist/dev/app-plus/__uniapperror.png
unpackage/dist/dev/app-plus/__uniappes6.js
unpackage/dist/dev/app-plus/__uniappopenlocation.js
unpackage/dist/dev/app-plus/__uniapppicker.js
unpackage/dist/dev/app-plus/__uniappquill.js
unpackage/dist/dev/app-plus/__uniappquillimageresize.js
unpackage/dist/dev/app-plus/__uniappscan.js
unpackage/dist/dev/app-plus/__uniappsuccess.png
unpackage/dist/dev/app-plus/__uniappview.html
unpackage/dist/dev/app-plus/app-config-service.js
unpackage/dist/dev/app-plus/app-config.js
unpackage/dist/dev/app-plus/app-service.js
unpackage/dist/dev/app-plus/app-view.js
unpackage/dist/dev/app-plus/manifest.json
unpackage/dist/dev/app-plus/static/bg.jpeg
unpackage/dist/dev/app-plus/static/c1.png
unpackage/dist/dev/app-plus/static/c2.png
unpackage/dist/dev/app-plus/static/c3.png
unpackage/dist/dev/app-plus/static/c4.png
unpackage/dist/dev/app-plus/static/c5.png
unpackage/dist/dev/app-plus/static/c6.png
unpackage/dist/dev/app-plus/static/c7.png
unpackage/dist/dev/app-plus/static/c8.png
unpackage/dist/dev/app-plus/static/c9.png
unpackage/dist/dev/app-plus/static/customicons.css
unpackage/dist/dev/app-plus/static/customicons.ttf
unpackage/dist/dev/app-plus/static/logo.png
unpackage/dist/dev/app-plus/static/mine1-selected.png
unpackage/dist/dev/app-plus/static/mine1.png
unpackage/dist/dev/app-plus/static/notice1-selected.png
unpackage/dist/dev/app-plus/static/notice1.png
unpackage/dist/dev/app-plus/static/uni.png
unpackage/dist/dev/app-plus/view.css
unpackage/dist/dev/app-plus/view.umd.min.js
unpackage/release/apk/__UNI__843A1A3__20230615093737.apk
unpackage/release/apk/应急响应.apk
unpackage/release/apk/应急响应1.apk
unpackage/res/icons/1024x1024.png
unpackage/res/icons/120x120.png
unpackage/res/icons/144x144.png
unpackage/res/icons/152x152.png
unpackage/res/icons/167x167.png
unpackage/res/icons/180x180.png
unpackage/res/icons/192x192.png
unpackage/res/icons/20x20.png
unpackage/res/icons/29x29.png
unpackage/res/icons/40x40.png
unpackage/res/icons/58x58.png
unpackage/res/icons/60x60.png
unpackage/res/icons/72x72.png
unpackage/res/icons/76x76.png
unpackage/res/icons/80x80.png
unpackage/res/icons/87x87.png
unpackage/res/icons/96x96.png |