¶Ô±ÈÐÂÎļþ |
| | |
| | | unpackage |
| | | node_modules |
| | | uview-ui |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script> |
| | | export default { |
| | | onLaunch: function() { |
| | | console.log('App Launch') |
| | | }, |
| | | onShow: function() { |
| | | console.log('App Show') |
| | | }, |
| | | onHide: function() { |
| | | console.log('App Hide') |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | /* 注æè¦åå¨ç¬¬ä¸è¡ï¼åæ¶ç»styleæ ç¾å å
¥lang="scss"屿§ */ |
| | | @import './tuniao-ui/index.scss'; |
| | | @import './tuniao-ui/iconfont.css'; |
| | | @import "uview-ui/index.scss"; |
| | | /*æ¯ä¸ªé¡µé¢å
Œ
±css */ |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | MIT License |
| | | |
| | | Copyright (c) 2020 www.uviewui.com |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | of this software and associated documentation files (the "Software"), to deal |
| | | in the Software without restriction, including without limitation the rights |
| | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | copies of the Software, and to permit persons to whom the Software is |
| | | furnished to do so, subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in all |
| | | copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| | | SOFTWARE. |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // let baseUrl = 'http://192.168.11.186:8098' |
| | | // let baseUrl = 'http://192.168.12.83:8098' |
| | | // let baseUrl = 'http://127.0.0.1:8098' |
| | | let baseUrl = 'http://192.168.12.101:8098' |
| | | |
| | | const install = (Vue, vm) => { |
| | | // æ¤ä¸ºèªå®ä¹é
ç½®åæ°ï¼å
·ä½åæ°è§ä¸æ¹è¯´æ |
| | | Vue.prototype.$u.http.setConfig({ |
| | | baseUrl: baseUrl, |
| | | loadingText: 'åªåå è½½ä¸~', |
| | | loadingTime: 5000, |
| | | originalData: true, |
| | | // ...... |
| | | }); |
| | | |
| | | // è¯·æ±æ¦æªï¼é
ç½®Tokençåæ° |
| | | Vue.prototype.$u.http.interceptor.request = (config) => { |
| | | // å¼ç¨token |
| | | // æ¹å¼ä¸ï¼åæ¾å¨vuexçtokenï¼å设使ç¨äºuViewå°è£
çvuexæ¹å¼ |
| | | // è§ï¼https://uviewui.com/components/globalVariable.html |
| | | // config.header.token = vm.token; |
| | | |
| | | // æ¹å¼äºï¼å¦ææ²¡æä½¿ç¨uViewå°è£
çvuexæ¹æ³ï¼é£ä¹éè¦ä½¿ç¨$store.stateè·å |
| | | // config.header.token = vm.$store.state.token; |
| | | |
| | | // æ¹å¼ä¸ï¼å¦ætokenæ¾å¨äºglobalDataï¼éè¿getApp().globalDataè·å |
| | | // config.header.token = getApp().globalData.username; |
| | | |
| | | // æ¹å¼åï¼å¦ætokenæ¾å¨äºStorageæ¬å°åå¨ä¸ï¼æ¦æªæ¯æ¯æ¬¡è¯·æ±é½æ§è¡ç |
| | | // æä»¥åªææ¨éæ°ç»å½ä¿®æ¹äºStorageï¼ä¸ä¸æ¬¡ç请æ±å°ä¼æ¯ææ°å¼ |
| | | // const token = uni.getStorageSync('token'); |
| | | // config.header.token = token; |
| | | config.header.Token = 'xxxxxx'; |
| | | config.header.Authorization = "Bearer " + uni.getStorageSync('jo_id_token'); |
| | | // å¯ä»¥å¯¹æä¸ªurlè¿è¡ç¹å«å¤çï¼æ¤urlåæ°ä¸ºthis.$u.get(url)ä¸çurlå¼ |
| | | if(config.url == '/api/User/login') config.header.noToken = true; |
| | | // æåéè¦å°configè¿è¡return |
| | | return config; |
| | | // 妿returnä¸ä¸ªfalseå¼ï¼åä¼åæ¶æ¬æ¬¡è¯·æ± |
| | | // if(config.url == '/user/rest') return false; // åæ¶ææ¬¡è¯·æ± |
| | | } |
| | | |
| | | // ååºæ¦æªï¼å¤æç¶æç æ¯å¦éè¿ |
| | | Vue.prototype.$u.http.interceptor.response = (res) => { |
| | | if(res.statusCode == 200) { |
| | | // res为æå¡ç«¯è¿åå¼ï¼å¯è½æcodeï¼resultçåæ®µ |
| | | // è¿é对res.resultè¿è¡è¿åï¼å°ä¼å¨this.$u.post(url).then(res => {})çthenåè°ä¸çresçå° |
| | | // 妿é
ç½®äºoriginalData为trueï¼è¯·çæè¿éçè¿åå¼ |
| | | return res.data; |
| | | } else if(res.statusCode == 401) { |
| | | // å设201为token失æï¼è¿é跳转ç»å½ |
| | | vm.$u.toast('éªè¯å¤±è´¥ï¼è¯·éæ°ç»å½'); |
| | | setTimeout(() => { |
| | | // æ¤ä¸ºuViewçæ¹æ³ï¼è¯¦è§è·¯ç±ç¸å
³ææ¡£ |
| | | vm.$u.route('/pages/login/login') |
| | | }, 1500) |
| | | return false; |
| | | } else if(res.statusCode == 202){ |
| | | // 妿è¿åfalseï¼åä¼è°ç¨Promiseçrejectåè°ï¼ |
| | | // å¹¶å°è¿å
¥this.$u.post(url).then().catch(res=>{})çcatchåè°ä¸ï¼res为æå¡ç«¯çè¿åå¼ |
| | | vm.$u.post("/api/User/replaceToken").then(res=>{ |
| | | if (x.data.status) { |
| | | vm.$u.vuex('vuex_token',x.data.data) |
| | | vm.$u.route({ |
| | | type: "navigateBack", |
| | | delta: -1 |
| | | }) |
| | | } else { |
| | | console.log(x.data.message); |
| | | vm.$u.toast('éªè¯è¿æï¼è¯·éæ°ç»å½'); |
| | | setTimeout(() => { |
| | | // æ¤ä¸ºuViewçæ¹æ³ï¼è¯¦è§è·¯ç±ç¸å
³ææ¡£ |
| | | vm.$u.route('/pages/login/login') |
| | | }, 1500) |
| | | } |
| | | }).catch(err=>{ |
| | | uni.reLaunch({ |
| | | url: '/pages/login/login' |
| | | }); |
| | | }) |
| | | // uni.request({ |
| | | // url: "http://192.168.12.245:8099/api/User/replaceToken", |
| | | // param: {}, |
| | | // method: 'POST', |
| | | // responseType: "text", |
| | | // header: { |
| | | // Authorization: "Bearer " + vm.vuex_token |
| | | // }, |
| | | // async: false, |
| | | // success: function(x) { |
| | | // if (x.data.status) { |
| | | // vm.$u.vuex('vuex_token',x.data.data) |
| | | // vm.$u.route({ |
| | | // type: "navigateBack", |
| | | // delta: -1 |
| | | // }) |
| | | // } else { |
| | | // console.log(x.data.message); |
| | | // vm.$u.toast('éªè¯è¿æï¼è¯·éæ°ç»å½'); |
| | | // setTimeout(() => { |
| | | // // æ¤ä¸ºuViewçæ¹æ³ï¼è¯¦è§è·¯ç±ç¸å
³ææ¡£ |
| | | // vm.$u.route('/pages/user/login') |
| | | // }, 1500) |
| | | // } |
| | | // }, |
| | | // errror: function(ex) { |
| | | // console.log(ex); |
| | | // uni.reLaunch({ |
| | | // url: '/pages/user/login' |
| | | // }); |
| | | // }, |
| | | // }); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | install, |
| | | baseUrl |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | .uni-flex { |
| | | display: flex; |
| | | } |
| | | |
| | | .uni-flex-row { |
| | | @extend .uni-flex; |
| | | flex-direction: row; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .uni-flex-column { |
| | | @extend .uni-flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .uni-color-gary { |
| | | color: #3b4144; |
| | | } |
| | | |
| | | /* æ é¢ */ |
| | | .uni-title { |
| | | display: flex; |
| | | margin-bottom: $uni-spacing-col-base; |
| | | font-size: $uni-font-size-lg; |
| | | font-weight: bold; |
| | | color: #3b4144; |
| | | } |
| | | |
| | | .uni-title-sub { |
| | | display: flex; |
| | | // margin-bottom: $uni-spacing-col-base; |
| | | font-size: $uni-font-size-base; |
| | | font-weight: 500; |
| | | color: #3b4144; |
| | | } |
| | | |
| | | /* æè¿° é¢å¤ææ¬ */ |
| | | .uni-note { |
| | | margin-top: 10px; |
| | | color: #999; |
| | | font-size: $uni-font-size-sm; |
| | | } |
| | | |
| | | /* å表å
容 */ |
| | | .uni-list-box { |
| | | @extend .uni-flex-row; |
| | | flex: 1; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | /* ç¥ç¼©å¾ */ |
| | | .uni-thumb { |
| | | flex-shrink: 0; |
| | | margin-right: $uni-spacing-row-base; |
| | | width: 125px; |
| | | height: 75px; |
| | | border-radius: $uni-border-radius-lg; |
| | | overflow: hidden; |
| | | border: 1px #f5f5f5 solid; |
| | | image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .uni-media-box { |
| | | @extend .uni-flex-row; |
| | | // margin-bottom: $uni-spacing-col-base; |
| | | border-radius: $uni-border-radius-lg; |
| | | overflow: hidden; |
| | | .uni-thumb { |
| | | margin: 0; |
| | | margin-left: 4px; |
| | | flex-shrink: 1; |
| | | width: 33%; |
| | | border-radius:0; |
| | | &:first-child { |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* å
容 */ |
| | | .uni-content { |
| | | @extend .uni-flex-column; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | /* å表footer */ |
| | | .uni-footer { |
| | | @extend .uni-flex-row; |
| | | justify-content: space-between; |
| | | margin-top: $uni-spacing-col-lg; |
| | | } |
| | | .uni-footer-text { |
| | | font-size: $uni-font-size-sm; |
| | | color: $uni-text-color-grey; |
| | | margin-left: 5px; |
| | | } |
| | | |
| | | /* æ ç¾ */ |
| | | |
| | | .uni-tag { |
| | | flex-shrink: 0; |
| | | padding: 0 5px; |
| | | border: 1px $uni-border-color solid; |
| | | margin-right: $uni-spacing-row-sm; |
| | | border-radius: $uni-border-radius-base; |
| | | background: $uni-bg-color-grey; |
| | | color: $uni-text-color; |
| | | font-size: $uni-font-size-sm; |
| | | } |
| | | |
| | | /* 龿¥ */ |
| | | .uni-link { |
| | | margin-left: 10px; |
| | | color: $uni-text-color; |
| | | text-decoration: underline; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import buildURL from '../helpers/buildURL' |
| | | import buildFullPath from '../core/buildFullPath' |
| | | import settle from '../core/settle' |
| | | import {isUndefined} from "../utils" |
| | | |
| | | /** |
| | | * è¿åå¯éå¼åå¨çé
ç½® |
| | | * @param {Array} keys - å¯é弿°ç» |
| | | * @param {Object} config2 - é
ç½® |
| | | * @return {{}} - åå¨çé
置项 |
| | | */ |
| | | const mergeKeys = (keys, config2) => { |
| | | let config = {} |
| | | keys.forEach(prop => { |
| | | if (!isUndefined(config2[prop])) { |
| | | config[prop] = config2[prop] |
| | | } |
| | | }) |
| | | return config |
| | | } |
| | | export default (config) => { |
| | | return new Promise((resolve, reject) => { |
| | | let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer) |
| | | const _config = { |
| | | url: fullPath, |
| | | header: config.header, |
| | | complete: (response) => { |
| | | config.fullPath = fullPath |
| | | response.config = config |
| | | response.rawData = response.data |
| | | try { |
| | | // 对å¯è½åç¬¦ä¸²ä¸æ¯json çæ
åµå®¹é |
| | | if (typeof response.data === 'string') { |
| | | response.data = JSON.parse(response.data) |
| | | } |
| | | // eslint-disable-next-line no-empty |
| | | } catch (e) { |
| | | } |
| | | settle(resolve, reject, response) |
| | | } |
| | | } |
| | | let requestTask |
| | | if (config.method === 'UPLOAD') { |
| | | delete _config.header['content-type'] |
| | | delete _config.header['Content-Type'] |
| | | let otherConfig = { |
| | | // #ifdef MP-ALIPAY |
| | | fileType: config.fileType, |
| | | // #endif |
| | | filePath: config.filePath, |
| | | name: config.name |
| | | } |
| | | const optionalKeys = [ |
| | | // #ifdef APP-PLUS || H5 |
| | | 'files', |
| | | // #endif |
| | | // #ifdef H5 |
| | | 'file', |
| | | // #endif |
| | | // #ifdef H5 || APP-PLUS |
| | | 'timeout', |
| | | // #endif |
| | | 'formData' |
| | | ] |
| | | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)}) |
| | | } else if (config.method === 'DOWNLOAD') { |
| | | // #ifdef H5 || APP-PLUS |
| | | if (!isUndefined(config['timeout'])) { |
| | | _config['timeout'] = config['timeout'] |
| | | } |
| | | // #endif |
| | | requestTask = uni.downloadFile(_config) |
| | | } else { |
| | | const optionalKeys = [ |
| | | 'data', |
| | | 'method', |
| | | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN |
| | | 'timeout', |
| | | // #endif |
| | | 'dataType', |
| | | // #ifndef MP-ALIPAY |
| | | 'responseType', |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | 'sslVerify', |
| | | // #endif |
| | | // #ifdef H5 |
| | | 'withCredentials', |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | 'firstIpv4', |
| | | // #endif |
| | | ] |
| | | requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)}) |
| | | } |
| | | if (config.getTask) { |
| | | config.getTask(requestTask, config) |
| | | } |
| | | }) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | |
| | | function InterceptorManager() { |
| | | this.handlers = [] |
| | | } |
| | | |
| | | /** |
| | | * Add a new interceptor to the stack |
| | | * |
| | | * @param {Function} fulfilled The function to handle `then` for a `Promise` |
| | | * @param {Function} rejected The function to handle `reject` for a `Promise` |
| | | * |
| | | * @return {Number} An ID used to remove interceptor later |
| | | */ |
| | | InterceptorManager.prototype.use = function use(fulfilled, rejected) { |
| | | this.handlers.push({ |
| | | fulfilled: fulfilled, |
| | | rejected: rejected |
| | | }) |
| | | return this.handlers.length - 1 |
| | | } |
| | | |
| | | /** |
| | | * Remove an interceptor from the stack |
| | | * |
| | | * @param {Number} id The ID that was returned by `use` |
| | | */ |
| | | InterceptorManager.prototype.eject = function eject(id) { |
| | | if (this.handlers[id]) { |
| | | this.handlers[id] = null |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Iterate over all the registered interceptors |
| | | * |
| | | * This method is particularly useful for skipping over any |
| | | * interceptors that may have become `null` calling `eject`. |
| | | * |
| | | * @param {Function} fn The function to call for each interceptor |
| | | */ |
| | | InterceptorManager.prototype.forEach = function forEach(fn) { |
| | | this.handlers.forEach(h => { |
| | | if (h !== null) { |
| | | fn(h) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export default InterceptorManager |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * @Class Request |
| | | * @description luch-request httpè¯·æ±æä»¶ |
| | | * @Author lu-ch |
| | | * @Email webwork.s@qq.com |
| | | * ææ¡£: https://www.quanzhan.co/luch-request/ |
| | | * github: https://github.com/lei-mu/luch-request |
| | | * DCloud: http://ext.dcloud.net.cn/plugin?id=392 |
| | | */ |
| | | |
| | | |
| | | import dispatchRequest from './dispatchRequest' |
| | | import InterceptorManager from './InterceptorManager' |
| | | import mergeConfig from './mergeConfig' |
| | | import defaults from './defaults' |
| | | import { isPlainObject } from '../utils' |
| | | import clone from '../utils/clone' |
| | | |
| | | export default class Request { |
| | | /** |
| | | * @param {Object} arg - å
¨å±é
ç½® |
| | | * @param {String} arg.baseURL - å
¨å±æ ¹è·¯å¾ |
| | | * @param {Object} arg.header - å
¨å±header |
| | | * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - å
¨å±é»è®¤è¯·æ±æ¹å¼ |
| | | * @param {String} arg.dataType = [json] - å
¨å±é»è®¤çdataType |
| | | * @param {String} arg.responseType = [text|arraybuffer] - å
¨å±é»è®¤çresponseTypeãæ¯ä»å®å°ç¨åºä¸æ¯æ |
| | | * @param {Object} arg.custom - å
¨å±é»è®¤çèªå®ä¹åæ° |
| | | * @param {Number} arg.timeout - å
¨å±é»è®¤çè¶
æ¶æ¶é´ï¼åä½ msãé»è®¤60000ãH5(HBuilderX 2.9.9+)ãAPP(HBuilderX 2.9.9+)ã微信å°ç¨åºï¼2.10.0ï¼ãæ¯ä»å®å°ç¨åº |
| | | * @param {Boolean} arg.sslVerify - å
¨å±é»è®¤çæ¯å¦éªè¯ ssl è¯ä¹¦ãé»è®¤true.ä»
Appå®åç«¯æ¯æï¼HBuilderX 2.3.3+ï¼ |
| | | * @param {Boolean} arg.withCredentials - å
¨å±é»è®¤çè·¨åè¯·æ±æ¶æ¯å¦æºå¸¦åè¯ï¼cookiesï¼ãé»è®¤falseãä»
H5æ¯æï¼HBuilderX 2.6.15+ï¼ |
| | | * @param {Boolean} arg.firstIpv4 - å
¨DNSè§£ææ¶ä¼å
使ç¨ipv4ãé»è®¤falseãä»
App-Android æ¯æ (HBuilderX 2.8.0+) |
| | | * @param {Function(statusCode):Boolean} arg.validateStatus - å
¨å±é»è®¤çèªå®ä¹éªè¯å¨ãé»è®¤statusCode >= 200 && statusCode < 300 |
| | | */ |
| | | constructor(arg = {}) { |
| | | if (!isPlainObject(arg)) { |
| | | arg = {} |
| | | console.warn('设置å
¨å±åæ°å¿
é¡»æ¥æ¶ä¸ä¸ªObject') |
| | | } |
| | | this.config = clone({...defaults, ...arg}) |
| | | this.interceptors = { |
| | | request: new InterceptorManager(), |
| | | response: new InterceptorManager() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @Function |
| | | * @param {Request~setConfigCallback} f - 设置å
¨å±é»è®¤é
ç½® |
| | | */ |
| | | setConfig(f) { |
| | | this.config = f(this.config) |
| | | } |
| | | |
| | | middleware(config) { |
| | | config = mergeConfig(this.config, config) |
| | | let chain = [dispatchRequest, undefined] |
| | | let promise = Promise.resolve(config) |
| | | |
| | | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { |
| | | chain.unshift(interceptor.fulfilled, interceptor.rejected) |
| | | }) |
| | | |
| | | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { |
| | | chain.push(interceptor.fulfilled, interceptor.rejected) |
| | | }) |
| | | |
| | | while (chain.length) { |
| | | promise = promise.then(chain.shift(), chain.shift()) |
| | | } |
| | | |
| | | return promise |
| | | } |
| | | |
| | | /** |
| | | * @Function |
| | | * @param {Object} config - 请æ±é
置项 |
| | | * @prop {String} options.url - 请æ±è·¯å¾ |
| | | * @prop {Object} options.data - 请æ±åæ° |
| | | * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - ååºçæ°æ®ç±»å |
| | | * @prop {Object} [options.dataType = config.dataType] - å¦æè®¾ä¸º jsonï¼ä¼å°è¯å¯¹è¿åçæ°æ®å䏿¬¡ JSON.parse |
| | | * @prop {Object} [options.header = config.header] - 请æ±header |
| | | * @prop {Object} [options.method = config.method] - è¯·æ±æ¹æ³ |
| | | * @returns {Promise<unknown>} |
| | | */ |
| | | request(config = {}) { |
| | | return this.middleware(config) |
| | | } |
| | | |
| | | get(url, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | method: 'GET', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | post(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'POST', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD |
| | | put(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'PUT', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU |
| | | delete(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'DELETE', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | // #ifdef H5 || MP-WEIXIN |
| | | connect(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'CONNECT', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | // #ifdef H5 || MP-WEIXIN || MP-BAIDU |
| | | head(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'HEAD', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU |
| | | options(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'OPTIONS', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | // #ifdef H5 || MP-WEIXIN |
| | | trace(url, data, options = {}) { |
| | | return this.middleware({ |
| | | url, |
| | | data, |
| | | method: 'TRACE', |
| | | ...options |
| | | }) |
| | | } |
| | | |
| | | // #endif |
| | | |
| | | upload(url, config = {}) { |
| | | config.url = url |
| | | config.method = 'UPLOAD' |
| | | return this.middleware(config) |
| | | } |
| | | |
| | | download(url, config = {}) { |
| | | config.url = url |
| | | config.method = 'DOWNLOAD' |
| | | return this.middleware(config) |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * setConfigåè° |
| | | * @return {Object} - è¿åæä½åçconfig |
| | | * @callback Request~setConfigCallback |
| | | * @param {Object} config - å
¨å±é»è®¤config |
| | | */ |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | import isAbsoluteURL from '../helpers/isAbsoluteURL' |
| | | import combineURLs from '../helpers/combineURLs' |
| | | |
| | | /** |
| | | * Creates a new URL by combining the baseURL with the requestedURL, |
| | | * only when the requestedURL is not already an absolute URL. |
| | | * If the requestURL is absolute, this function returns the requestedURL untouched. |
| | | * |
| | | * @param {string} baseURL The base URL |
| | | * @param {string} requestedURL Absolute or relative URL to combine |
| | | * @returns {string} The combined full path |
| | | */ |
| | | export default function buildFullPath(baseURL, requestedURL) { |
| | | if (baseURL && !isAbsoluteURL(requestedURL)) { |
| | | return combineURLs(baseURL, requestedURL) |
| | | } |
| | | return requestedURL |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * é»è®¤çå
¨å±é
ç½® |
| | | */ |
| | | |
| | | |
| | | export default { |
| | | baseURL: '', |
| | | header: {}, |
| | | method: 'GET', |
| | | dataType: 'json', |
| | | paramsSerializer: null, |
| | | // #ifndef MP-ALIPAY |
| | | responseType: 'text', |
| | | // #endif |
| | | custom: {}, |
| | | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN |
| | | timeout: 60000, |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | sslVerify: true, |
| | | // #endif |
| | | // #ifdef H5 |
| | | withCredentials: false, |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | firstIpv4: false, |
| | | // #endif |
| | | validateStatus: function validateStatus(status) { |
| | | return status >= 200 && status < 300 |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import adapter from '../adapters/index' |
| | | |
| | | |
| | | export default (config) => { |
| | | return adapter(config) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import {deepMerge, isUndefined} from '../utils' |
| | | |
| | | /** |
| | | * åå¹¶å±é¨é
ç½®ä¼å
çé
ç½®ï¼å¦æå±é¨æè¯¥é
置项åç¨å±é¨ï¼å¦æå
¨å±æè¯¥é
置项åç¨å
¨å± |
| | | * @param {Array} keys - é
置项 |
| | | * @param {Object} globalsConfig - å½åçå
¨å±é
ç½® |
| | | * @param {Object} config2 - å±é¨é
ç½® |
| | | * @return {{}} |
| | | */ |
| | | const mergeKeys = (keys, globalsConfig, config2) => { |
| | | let config = {} |
| | | keys.forEach(prop => { |
| | | if (!isUndefined(config2[prop])) { |
| | | config[prop] = config2[prop] |
| | | } else if (!isUndefined(globalsConfig[prop])) { |
| | | config[prop] = globalsConfig[prop] |
| | | } |
| | | }) |
| | | return config |
| | | } |
| | | /** |
| | | * |
| | | * @param globalsConfig - å½åå®ä¾çå
¨å±é
ç½® |
| | | * @param config2 - å½åçå±é¨é
ç½® |
| | | * @return - åå¹¶åçé
ç½® |
| | | */ |
| | | export default (globalsConfig, config2 = {}) => { |
| | | const method = config2.method || globalsConfig.method || 'GET' |
| | | let config = { |
| | | baseURL: config2.baseURL || globalsConfig.baseURL || '', |
| | | method: method, |
| | | url: config2.url || '', |
| | | params: config2.params || {}, |
| | | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})}, |
| | | header: deepMerge(globalsConfig.header || {}, config2.header || {}) |
| | | } |
| | | const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer'] |
| | | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)} |
| | | |
| | | // eslint-disable-next-line no-empty |
| | | if (method === 'DOWNLOAD') { |
| | | // #ifdef H5 || APP-PLUS |
| | | if (!isUndefined(config2.timeout)) { |
| | | config['timeout'] = config2['timeout'] |
| | | } else if (!isUndefined(globalsConfig.timeout)) { |
| | | config['timeout'] = globalsConfig['timeout'] |
| | | } |
| | | // #endif |
| | | } else if (method === 'UPLOAD') { |
| | | delete config.header['content-type'] |
| | | delete config.header['Content-Type'] |
| | | const uploadKeys = [ |
| | | // #ifdef APP-PLUS || H5 |
| | | 'files', |
| | | // #endif |
| | | // #ifdef MP-ALIPAY |
| | | 'fileType', |
| | | // #endif |
| | | // #ifdef H5 |
| | | 'file', |
| | | // #endif |
| | | 'filePath', |
| | | 'name', |
| | | // #ifdef H5 || APP-PLUS |
| | | 'timeout', |
| | | // #endif |
| | | 'formData', |
| | | ] |
| | | uploadKeys.forEach(prop => { |
| | | if (!isUndefined(config2[prop])) { |
| | | config[prop] = config2[prop] |
| | | } |
| | | }) |
| | | // #ifdef H5 || APP-PLUS |
| | | if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) { |
| | | config['timeout'] = globalsConfig['timeout'] |
| | | } |
| | | // #endif |
| | | } else { |
| | | const defaultsKeys = [ |
| | | 'data', |
| | | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN |
| | | 'timeout', |
| | | // #endif |
| | | 'dataType', |
| | | // #ifndef MP-ALIPAY |
| | | 'responseType', |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | 'sslVerify', |
| | | // #endif |
| | | // #ifdef H5 |
| | | 'withCredentials', |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | 'firstIpv4', |
| | | // #endif |
| | | ] |
| | | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)} |
| | | } |
| | | |
| | | return config |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * Resolve or reject a Promise based on response status. |
| | | * |
| | | * @param {Function} resolve A function that resolves the promise. |
| | | * @param {Function} reject A function that rejects the promise. |
| | | * @param {object} response The response. |
| | | */ |
| | | export default function settle(resolve, reject, response) { |
| | | const validateStatus = response.config.validateStatus |
| | | const status = response.statusCode |
| | | if (status && (!validateStatus || validateStatus(status))) { |
| | | resolve(response) |
| | | } else { |
| | | reject(response) |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | import * as utils from './../utils' |
| | | |
| | | function encode(val) { |
| | | return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']') |
| | | } |
| | | |
| | | /** |
| | | * Build a URL by appending params to the end |
| | | * |
| | | * @param {string} url The base of the url (e.g., http://www.google.com) |
| | | * @param {object} [params] The params to be appended |
| | | * @returns {string} The formatted url |
| | | */ |
| | | export default function buildURL(url, params, paramsSerializer) { |
| | | /*eslint no-param-reassign:0*/ |
| | | if (!params) { |
| | | return url |
| | | } |
| | | |
| | | var serializedParams |
| | | if (paramsSerializer) { |
| | | serializedParams = paramsSerializer(params) |
| | | } else if (utils.isURLSearchParams(params)) { |
| | | serializedParams = params.toString() |
| | | } else { |
| | | var parts = [] |
| | | |
| | | utils.forEach(params, function serialize(val, key) { |
| | | if (val === null || typeof val === 'undefined') { |
| | | return |
| | | } |
| | | |
| | | if (utils.isArray(val)) { |
| | | key = key + '[]' |
| | | } else { |
| | | val = [val] |
| | | } |
| | | |
| | | utils.forEach(val, function parseValue(v) { |
| | | if (utils.isDate(v)) { |
| | | v = v.toISOString() |
| | | } else if (utils.isObject(v)) { |
| | | v = JSON.stringify(v) |
| | | } |
| | | parts.push(encode(key) + '=' + encode(v)) |
| | | }) |
| | | }) |
| | | |
| | | serializedParams = parts.join('&') |
| | | } |
| | | |
| | | if (serializedParams) { |
| | | var hashmarkIndex = url.indexOf('#') |
| | | if (hashmarkIndex !== -1) { |
| | | url = url.slice(0, hashmarkIndex) |
| | | } |
| | | |
| | | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams |
| | | } |
| | | |
| | | return url |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | /** |
| | | * Creates a new URL by combining the specified URLs |
| | | * |
| | | * @param {string} baseURL The base URL |
| | | * @param {string} relativeURL The relative URL |
| | | * @returns {string} The combined URL |
| | | */ |
| | | export default function combineURLs(baseURL, relativeURL) { |
| | | return relativeURL |
| | | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') |
| | | : baseURL |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | /** |
| | | * Determines whether the specified URL is absolute |
| | | * |
| | | * @param {string} url The URL to test |
| | | * @returns {boolean} True if the specified URL is absolute, otherwise false |
| | | */ |
| | | export default function isAbsoluteURL(url) { |
| | | // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL). |
| | | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed |
| | | // by any combination of letters, digits, plus, period, or hyphen. |
| | | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | type AnyObject = Record<string | number | symbol, any> |
| | | type HttpPromise<T> = Promise<HttpResponse<T>>; |
| | | type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask |
| | | export interface RequestTask { |
| | | abort: () => void; |
| | | offHeadersReceived: () => void; |
| | | onHeadersReceived: () => void; |
| | | } |
| | | export interface HttpRequestConfig<T = Tasks> { |
| | | /** 请æ±åºå°å */ |
| | | baseURL?: string; |
| | | /** è¯·æ±æå¡å¨æ¥å£å°å */ |
| | | url?: string; |
| | | |
| | | /** è¯·æ±æ¥è¯¢åæ°ï¼èªå¨æ¼æ¥ä¸ºæ¥è¯¢å符串 */ |
| | | params?: AnyObject; |
| | | /** 请æ±ä½åæ° */ |
| | | data?: AnyObject; |
| | | |
| | | /** æä»¶å¯¹åºç key */ |
| | | name?: string; |
| | | /** HTTP 请æ±ä¸å
¶ä»é¢å¤ç form data */ |
| | | formData?: AnyObject; |
| | | /** è¦ä¸ä¼ æä»¶èµæºçè·¯å¾ã */ |
| | | filePath?: string; |
| | | /** éè¦ä¸ä¼ çæä»¶å表ãä½¿ç¨ files æ¶ï¼filePath å name ä¸çæï¼AppãH5ï¼ 2.6.15+ï¼ */ |
| | | files?: Array<{ |
| | | name?: string; |
| | | file?: File; |
| | | uri: string; |
| | | }>; |
| | | /** è¦ä¸ä¼ çæä»¶å¯¹è±¡ï¼ä»
H5ï¼2.6.15+ï¼æ¯æ */ |
| | | file?: File; |
| | | |
| | | /** 请æ±å¤´ä¿¡æ¯ */ |
| | | header?: AnyObject; |
| | | /** è¯·æ±æ¹å¼ */ |
| | | method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD"; |
| | | /** å¦æè®¾ä¸º jsonï¼ä¼å°è¯å¯¹è¿åçæ°æ®å䏿¬¡ JSON.parse */ |
| | | dataType?: string; |
| | | /** 设置ååºçæ°æ®ç±»åï¼æ¯ä»å®å°ç¨åºä¸æ¯æ */ |
| | | responseType?: "text" | "arraybuffer"; |
| | | /** èªå®ä¹åæ° */ |
| | | custom?: AnyObject; |
| | | /** è¶
æ¶æ¶é´ï¼ä»
微信å°ç¨åºï¼2.10.0ï¼ãæ¯ä»å®å°ç¨åºæ¯æ */ |
| | | timeout?: number; |
| | | /** DNSè§£ææ¶ä¼å
使ç¨ipv4ï¼ä»
App-Android æ¯æ (HBuilderX 2.8.0+) */ |
| | | firstIpv4?: boolean; |
| | | /** éªè¯ ssl è¯ä¹¦ ä»
5+Appå®åç«¯æ¯æï¼HBuilderX 2.3.3+ï¼ */ |
| | | sslVerify?: boolean; |
| | | /** è·¨åè¯·æ±æ¶æ¯å¦æºå¸¦åè¯ï¼cookiesï¼ä»
H5æ¯æï¼HBuilderX 2.6.15+ï¼ */ |
| | | withCredentials?: boolean; |
| | | |
| | | /** è¿åå½å请æ±çtask, optionsã请å¿å¨æ¤å¤ä¿®æ¹optionsã */ |
| | | getTask?: (task: T, options: HttpRequestConfig<T>) => void; |
| | | /** å
¨å±èªå®ä¹éªè¯å¨ */ |
| | | validateStatus?: (statusCode: number) => boolean | void; |
| | | /** params åæ°èªå®ä¹å¤ç */ |
| | | paramsSerializer?: (params: AnyObject) => string | void; |
| | | } |
| | | export interface HttpResponse<T = any> { |
| | | config: HttpRequestConfig; |
| | | statusCode: number; |
| | | cookies: Array<string>; |
| | | data: T; |
| | | errMsg: string; |
| | | header: AnyObject; |
| | | rawData: T; |
| | | } |
| | | export interface HttpUploadResponse<T = any> { |
| | | config: HttpRequestConfig; |
| | | statusCode: number; |
| | | data: T; |
| | | errMsg: string; |
| | | rawData: T; |
| | | } |
| | | export interface HttpDownloadResponse extends HttpResponse { |
| | | tempFilePath: string; |
| | | } |
| | | export interface HttpError { |
| | | config: HttpRequestConfig; |
| | | statusCode?: number; |
| | | cookies?: Array<string>; |
| | | data?: any; |
| | | errMsg: string; |
| | | header?: AnyObject; |
| | | } |
| | | export interface HttpInterceptorManager<V, E = V> { |
| | | use( |
| | | onFulfilled?: (config: V) => Promise<V> | V, |
| | | onRejected?: (config: E) => Promise<E> | E |
| | | ): void; |
| | | eject(id: number): void; |
| | | } |
| | | export abstract class HttpRequestAbstract { |
| | | constructor(config?: HttpRequestConfig); |
| | | config: HttpRequestConfig; |
| | | interceptors: { |
| | | request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>; |
| | | response: HttpInterceptorManager<HttpResponse, HttpError>; |
| | | } |
| | | middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>; |
| | | request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>; |
| | | delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>; |
| | | |
| | | download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>; |
| | | |
| | | setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void; |
| | | } |
| | | |
| | | declare class HttpRequest extends HttpRequestAbstract { } |
| | | export default HttpRequest; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import Request from './core/Request' |
| | | export default Request |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | |
| | | // utils is a library of generic helper functions non-specific to axios |
| | | |
| | | var toString = Object.prototype.toString |
| | | |
| | | /** |
| | | * Determine if a value is an Array |
| | | * |
| | | * @param {Object} val The value to test |
| | | * @returns {boolean} True if value is an Array, otherwise false |
| | | */ |
| | | export function isArray (val) { |
| | | return toString.call(val) === '[object Array]' |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Determine if a value is an Object |
| | | * |
| | | * @param {Object} val The value to test |
| | | * @returns {boolean} True if value is an Object, otherwise false |
| | | */ |
| | | export function isObject (val) { |
| | | return val !== null && typeof val === 'object' |
| | | } |
| | | |
| | | /** |
| | | * Determine if a value is a Date |
| | | * |
| | | * @param {Object} val The value to test |
| | | * @returns {boolean} True if value is a Date, otherwise false |
| | | */ |
| | | export function isDate (val) { |
| | | return toString.call(val) === '[object Date]' |
| | | } |
| | | |
| | | /** |
| | | * Determine if a value is a URLSearchParams object |
| | | * |
| | | * @param {Object} val The value to test |
| | | * @returns {boolean} True if value is a URLSearchParams object, otherwise false |
| | | */ |
| | | export function isURLSearchParams (val) { |
| | | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Iterate over an Array or an Object invoking a function for each item. |
| | | * |
| | | * If `obj` is an Array callback will be called passing |
| | | * the value, index, and complete array for each item. |
| | | * |
| | | * If 'obj' is an Object callback will be called passing |
| | | * the value, key, and complete object for each property. |
| | | * |
| | | * @param {Object|Array} obj The object to iterate |
| | | * @param {Function} fn The callback to invoke for each item |
| | | */ |
| | | export function forEach (obj, fn) { |
| | | // Don't bother if no value provided |
| | | if (obj === null || typeof obj === 'undefined') { |
| | | return |
| | | } |
| | | |
| | | // Force an array if not already something iterable |
| | | if (typeof obj !== 'object') { |
| | | /*eslint no-param-reassign:0*/ |
| | | obj = [obj] |
| | | } |
| | | |
| | | if (isArray(obj)) { |
| | | // Iterate over array values |
| | | for (var i = 0, l = obj.length; i < l; i++) { |
| | | fn.call(null, obj[i], i, obj) |
| | | } |
| | | } else { |
| | | // Iterate over object keys |
| | | for (var key in obj) { |
| | | if (Object.prototype.hasOwnProperty.call(obj, key)) { |
| | | fn.call(null, obj[key], key, obj) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºboolean å¼ |
| | | * @param val |
| | | * @returns {boolean} |
| | | */ |
| | | export function isBoolean(val) { |
| | | return typeof val === 'boolean' |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºçæ£ç对象{} new Object |
| | | * @param {any} obj - æ£æµç对象 |
| | | * @returns {boolean} |
| | | */ |
| | | export function isPlainObject(obj) { |
| | | return Object.prototype.toString.call(obj) === '[object Object]' |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Function equal to merge with the difference being that no reference |
| | | * to original objects is kept. |
| | | * |
| | | * @see merge |
| | | * @param {Object} obj1 Object to merge |
| | | * @returns {Object} Result of all merge properties |
| | | */ |
| | | export function deepMerge(/* obj1, obj2, obj3, ... */) { |
| | | let result = {} |
| | | function assignValue(val, key) { |
| | | if (typeof result[key] === 'object' && typeof val === 'object') { |
| | | result[key] = deepMerge(result[key], val) |
| | | } else if (typeof val === 'object') { |
| | | result[key] = deepMerge({}, val) |
| | | } else { |
| | | result[key] = val |
| | | } |
| | | } |
| | | for (let i = 0, l = arguments.length; i < l; i++) { |
| | | forEach(arguments[i], assignValue) |
| | | } |
| | | return result |
| | | } |
| | | |
| | | export function isUndefined (val) { |
| | | return typeof val === 'undefined' |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* eslint-disable */ |
| | | var clone = (function() { |
| | | 'use strict'; |
| | | |
| | | function _instanceof(obj, type) { |
| | | return type != null && obj instanceof type; |
| | | } |
| | | |
| | | var nativeMap; |
| | | try { |
| | | nativeMap = Map; |
| | | } catch(_) { |
| | | // maybe a reference error because no `Map`. Give it a dummy value that no |
| | | // value will ever be an instanceof. |
| | | nativeMap = function() {}; |
| | | } |
| | | |
| | | var nativeSet; |
| | | try { |
| | | nativeSet = Set; |
| | | } catch(_) { |
| | | nativeSet = function() {}; |
| | | } |
| | | |
| | | var nativePromise; |
| | | try { |
| | | nativePromise = Promise; |
| | | } catch(_) { |
| | | nativePromise = function() {}; |
| | | } |
| | | |
| | | /** |
| | | * Clones (copies) an Object using deep copying. |
| | | * |
| | | * This function supports circular references by default, but if you are certain |
| | | * there are no circular references in your object, you can save some CPU time |
| | | * by calling clone(obj, false). |
| | | * |
| | | * Caution: if `circular` is false and `parent` contains circular references, |
| | | * your program may enter an infinite loop and crash. |
| | | * |
| | | * @param `parent` - the object to be cloned |
| | | * @param `circular` - set to true if the object to be cloned may contain |
| | | * circular references. (optional - true by default) |
| | | * @param `depth` - set to a number if the object is only to be cloned to |
| | | * a particular depth. (optional - defaults to Infinity) |
| | | * @param `prototype` - sets the prototype to be used when cloning an object. |
| | | * (optional - defaults to parent prototype). |
| | | * @param `includeNonEnumerable` - set to true if the non-enumerable properties |
| | | * should be cloned as well. Non-enumerable properties on the prototype |
| | | * chain will be ignored. (optional - false by default) |
| | | */ |
| | | function clone(parent, circular, depth, prototype, includeNonEnumerable) { |
| | | if (typeof circular === 'object') { |
| | | depth = circular.depth; |
| | | prototype = circular.prototype; |
| | | includeNonEnumerable = circular.includeNonEnumerable; |
| | | circular = circular.circular; |
| | | } |
| | | // maintain two arrays for circular references, where corresponding parents |
| | | // and children have the same index |
| | | var allParents = []; |
| | | var allChildren = []; |
| | | |
| | | var useBuffer = typeof Buffer != 'undefined'; |
| | | |
| | | if (typeof circular == 'undefined') |
| | | circular = true; |
| | | |
| | | if (typeof depth == 'undefined') |
| | | depth = Infinity; |
| | | |
| | | // recurse this function so we don't reset allParents and allChildren |
| | | function _clone(parent, depth) { |
| | | // cloning null always returns null |
| | | if (parent === null) |
| | | return null; |
| | | |
| | | if (depth === 0) |
| | | return parent; |
| | | |
| | | var child; |
| | | var proto; |
| | | if (typeof parent != 'object') { |
| | | return parent; |
| | | } |
| | | |
| | | if (_instanceof(parent, nativeMap)) { |
| | | child = new nativeMap(); |
| | | } else if (_instanceof(parent, nativeSet)) { |
| | | child = new nativeSet(); |
| | | } else if (_instanceof(parent, nativePromise)) { |
| | | child = new nativePromise(function (resolve, reject) { |
| | | parent.then(function(value) { |
| | | resolve(_clone(value, depth - 1)); |
| | | }, function(err) { |
| | | reject(_clone(err, depth - 1)); |
| | | }); |
| | | }); |
| | | } else if (clone.__isArray(parent)) { |
| | | child = []; |
| | | } else if (clone.__isRegExp(parent)) { |
| | | child = new RegExp(parent.source, __getRegExpFlags(parent)); |
| | | if (parent.lastIndex) child.lastIndex = parent.lastIndex; |
| | | } else if (clone.__isDate(parent)) { |
| | | child = new Date(parent.getTime()); |
| | | } else if (useBuffer && Buffer.isBuffer(parent)) { |
| | | if (Buffer.from) { |
| | | // Node.js >= 5.10.0 |
| | | child = Buffer.from(parent); |
| | | } else { |
| | | // Older Node.js versions |
| | | child = new Buffer(parent.length); |
| | | parent.copy(child); |
| | | } |
| | | return child; |
| | | } else if (_instanceof(parent, Error)) { |
| | | child = Object.create(parent); |
| | | } else { |
| | | if (typeof prototype == 'undefined') { |
| | | proto = Object.getPrototypeOf(parent); |
| | | child = Object.create(proto); |
| | | } |
| | | else { |
| | | child = Object.create(prototype); |
| | | proto = prototype; |
| | | } |
| | | } |
| | | |
| | | if (circular) { |
| | | var index = allParents.indexOf(parent); |
| | | |
| | | if (index != -1) { |
| | | return allChildren[index]; |
| | | } |
| | | allParents.push(parent); |
| | | allChildren.push(child); |
| | | } |
| | | |
| | | if (_instanceof(parent, nativeMap)) { |
| | | parent.forEach(function(value, key) { |
| | | var keyChild = _clone(key, depth - 1); |
| | | var valueChild = _clone(value, depth - 1); |
| | | child.set(keyChild, valueChild); |
| | | }); |
| | | } |
| | | if (_instanceof(parent, nativeSet)) { |
| | | parent.forEach(function(value) { |
| | | var entryChild = _clone(value, depth - 1); |
| | | child.add(entryChild); |
| | | }); |
| | | } |
| | | |
| | | for (var i in parent) { |
| | | var attrs = Object.getOwnPropertyDescriptor(parent, i); |
| | | if (attrs) { |
| | | child[i] = _clone(parent[i], depth - 1); |
| | | } |
| | | |
| | | try { |
| | | var objProperty = Object.getOwnPropertyDescriptor(parent, i); |
| | | if (objProperty.set === 'undefined') { |
| | | // no setter defined. Skip cloning this property |
| | | continue; |
| | | } |
| | | child[i] = _clone(parent[i], depth - 1); |
| | | } catch(e){ |
| | | if (e instanceof TypeError) { |
| | | // when in strict mode, TypeError will be thrown if child[i] property only has a getter |
| | | // we can't do anything about this, other than inform the user that this property cannot be set. |
| | | continue |
| | | } else if (e instanceof ReferenceError) { |
| | | //this may happen in non strict mode |
| | | continue |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | if (Object.getOwnPropertySymbols) { |
| | | var symbols = Object.getOwnPropertySymbols(parent); |
| | | for (var i = 0; i < symbols.length; i++) { |
| | | // Don't need to worry about cloning a symbol because it is a primitive, |
| | | // like a number or string. |
| | | var symbol = symbols[i]; |
| | | var descriptor = Object.getOwnPropertyDescriptor(parent, symbol); |
| | | if (descriptor && !descriptor.enumerable && !includeNonEnumerable) { |
| | | continue; |
| | | } |
| | | child[symbol] = _clone(parent[symbol], depth - 1); |
| | | Object.defineProperty(child, symbol, descriptor); |
| | | } |
| | | } |
| | | |
| | | if (includeNonEnumerable) { |
| | | var allPropertyNames = Object.getOwnPropertyNames(parent); |
| | | for (var i = 0; i < allPropertyNames.length; i++) { |
| | | var propertyName = allPropertyNames[i]; |
| | | var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName); |
| | | if (descriptor && descriptor.enumerable) { |
| | | continue; |
| | | } |
| | | child[propertyName] = _clone(parent[propertyName], depth - 1); |
| | | Object.defineProperty(child, propertyName, descriptor); |
| | | } |
| | | } |
| | | |
| | | return child; |
| | | } |
| | | |
| | | return _clone(parent, depth); |
| | | } |
| | | |
| | | /** |
| | | * Simple flat clone using prototype, accepts only objects, usefull for property |
| | | * override on FLAT configuration object (no nested props). |
| | | * |
| | | * USE WITH CAUTION! This may not behave as you wish if you do not know how this |
| | | * works. |
| | | */ |
| | | clone.clonePrototype = function clonePrototype(parent) { |
| | | if (parent === null) |
| | | return null; |
| | | |
| | | var c = function () {}; |
| | | c.prototype = parent; |
| | | return new c(); |
| | | }; |
| | | |
| | | // private utility functions |
| | | |
| | | function __objToStr(o) { |
| | | return Object.prototype.toString.call(o); |
| | | } |
| | | clone.__objToStr = __objToStr; |
| | | |
| | | function __isDate(o) { |
| | | return typeof o === 'object' && __objToStr(o) === '[object Date]'; |
| | | } |
| | | clone.__isDate = __isDate; |
| | | |
| | | function __isArray(o) { |
| | | return typeof o === 'object' && __objToStr(o) === '[object Array]'; |
| | | } |
| | | clone.__isArray = __isArray; |
| | | |
| | | function __isRegExp(o) { |
| | | return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; |
| | | } |
| | | clone.__isRegExp = __isRegExp; |
| | | |
| | | function __getRegExpFlags(re) { |
| | | var flags = ''; |
| | | if (re.global) flags += 'g'; |
| | | if (re.ignoreCase) flags += 'i'; |
| | | if (re.multiline) flags += 'm'; |
| | | return flags; |
| | | } |
| | | clone.__getRegExpFlags = __getRegExpFlags; |
| | | |
| | | return clone; |
| | | })(); |
| | | |
| | | export default clone |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import Vue from 'vue' |
| | | import App from './App' |
| | | |
| | | Vue.config.productionTip = false |
| | | |
| | | App.mpType = 'app' |
| | | |
| | | // å¼å
¥å
¨å±uView |
| | | import uView from 'uview-ui' |
| | | Vue.use(uView); |
| | | // å¼å
¥å
¨å±TuniaoUI |
| | | import TuniaoUI from 'tuniao-ui' |
| | | Vue.use(TuniaoUI) |
| | | |
| | | const app = new Vue({ |
| | | ...App |
| | | }) |
| | | // httpæ¦æªå¨ï¼æ¤ä¸ºéè¦å å
¥çå
容ï¼å¦æä¸æ¯åå¨commonç®å½ï¼è¯·èªè¡ä¿®æ¹å¼å
¥è·¯å¾ |
| | | import httpInterceptor from '@/common/http.interceptor.js' |
| | | // è¿ééè¦å卿åï¼æ¯ä¸ºäºçVueåå»ºå¯¹è±¡å®æï¼å¼å
¥"app"对象(ä¹å³é¡µé¢ç"this"å®ä¾) |
| | | Vue.use(httpInterceptor, app) |
| | | app.$mount() |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="login__info tn-flex tn-flex-direction-column tn-flex-col-center tn-flex-row-center"> |
| | | <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="cacheName" placeholder-class="input-placeholder" @click="cacheshow=true" |
| | | placeholder="è¯·éæ©ç¼åæ¶ç¼å·" /> |
| | | <u-picker v-model="cacheshow" mode="selector" :range="selectorCache" range-key="cateName" |
| | | @confirm="cacheConfirm"></u-picker> |
| | | </view> |
| | | </view> |
| | | <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" :disabled="isOut" v-model="number" type="number" placeholder-class="input-placeholder" focus="true" |
| | | @input="numberInput" placeholder="请è¾å
¥æ°é" /> |
| | | </view> |
| | | </view> |
| | | <view class=""> |
| | | <u-radio-group v-model="value"> |
| | | <u-radio @change="radioChange" v-for="(item, index) in list" :key="index" :name="item.name" :disabled="item.disabled"> |
| | | {{item.name}} |
| | | </u-radio> |
| | | </u-radio-group> |
| | | </view> |
| | | <view class="login__info__item__button tn-cool-bg-color-7--reverse" @tap="submit()" hover-class="tn-hover" |
| | | :hover-stay-time="150">å¼å«AGV |
| | | </view> |
| | | <u-toast ref="uToast"></u-toast> |
| | | <u-modal v-model="show" :title-style="{color: 'red'}"> |
| | | <view class="slot-content"> |
| | | <rich-text :nodes="content"></rich-text> |
| | | </view> |
| | | </u-modal> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | number: '', |
| | | isOut:false, |
| | | show: false, |
| | | content: '', |
| | | list: [{ |
| | | name: '空æçå
¥åº', |
| | | disabled: false |
| | | }, |
| | | { |
| | | name: '空æçåºåº', |
| | | disabled: false |
| | | } |
| | | ], |
| | | // u-radio-groupçv-modelç»å®çå¼å¦æè®¾ç½®ä¸ºæä¸ªradioçnameï¼å°±ä¼è¢«é»è®¤éä¸ |
| | | value: '空æçå
¥åº', |
| | | show1: false, |
| | | cacheNo: '', |
| | | cacheName: '', |
| | | cacheshow: false, |
| | | selectorCache: [{ |
| | | cateName: '1å·ç¼åæ¶', |
| | | id: 1 |
| | | }, |
| | | { |
| | | cateName: '2å·ç¼åæ¶', |
| | | id: 2 |
| | | }, |
| | | { |
| | | cateName: '3å·ç¼åæ¶', |
| | | id: 3 |
| | | }, |
| | | { |
| | | cateName: '4å·ç¼åæ¶', |
| | | id: 4 |
| | | }, |
| | | { |
| | | cateName: '5å·ç¼åæ¶', |
| | | id: 5 |
| | | }, |
| | | { |
| | | cateName: '6å·ç¼åæ¶', |
| | | id: 6 |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | numberInput: function(e) { |
| | | this.number = e.detail.value; |
| | | |
| | | }, |
| | | //éä¸æä¸ªåéæ¡æ¶ï¼ç±radioæ¶è§¦å |
| | | radioChange(e) { |
| | | console.log(e); |
| | | if(e =="空æçåºåº"){ |
| | | this.number = 1, |
| | | this.isOut = true |
| | | } |
| | | else |
| | | { |
| | | this.number = "", |
| | | this.isOut = false |
| | | } |
| | | }, |
| | | cacheConfirm(e) { |
| | | let x = this.selectorCache[e]; |
| | | this.cacheName = x.cateName |
| | | this.cacheNo = x.id |
| | | }, |
| | | submit() { |
| | | let radio = '' |
| | | if (this.value === "空æçå
¥åº") { |
| | | radio = 1; |
| | | } else { |
| | | radio = 2; |
| | | } |
| | | if(this.number<=0 || this.number>5) |
| | | { |
| | | this.$t.message.toast('å
¥åºæ°éèå´ä¸º1-5') |
| | | return; |
| | | } |
| | | this.$u.post("/api/Towms/SendEpmtyTask", { |
| | | MainData: { |
| | | cacheNo: this.cacheNo, |
| | | creator: uni.getStorageSync('jo_user').userName, |
| | | radio: radio |
| | | } |
| | | }).then(res => { |
| | | this.barcode = '' |
| | | this.$t.message.toast(res.message); |
| | | }).catch(err => { |
| | | |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | // @import '@/static/css/templatePage/custom_nav_bar.scss'; |
| | | /* æ¬æµ® */ |
| | | .rocket-sussuspension { |
| | | animation: suspension 3s ease-in-out infinite; |
| | | } |
| | | |
| | | @keyframes suspension { |
| | | |
| | | 0%, |
| | | 100% { |
| | | transform: translate(0, 0); |
| | | } |
| | | |
| | | 50% { |
| | | transform: translate(-0.8rem, 1rem); |
| | | } |
| | | } |
| | | |
| | | .login { |
| | | position: relative; |
| | | height: 100%; |
| | | z-index: 1; |
| | | |
| | | /* èæ¯å¾ç start */ |
| | | &__bg { |
| | | z-index: -1; |
| | | position: fixed; |
| | | |
| | | &--top { |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | |
| | | .bg { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | |
| | | .rocket { |
| | | margin: 50rpx 28%; |
| | | width: 400rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | |
| | | &--bottom { |
| | | bottom: -10rpx; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | // height: 144px; |
| | | margin-bottom: env(safe-area-inset-bottom); |
| | | |
| | | image { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* èæ¯å¾ç end */ |
| | | |
| | | /* å
容 start */ |
| | | &__wrapper { |
| | | margin-top: 403rpx; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 忢 start */ |
| | | &__mode { |
| | | position: relative; |
| | | margin: 0 auto; |
| | | width: 476rpx; |
| | | height: 77rpx; |
| | | background-color: #FFFFFF; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | border-radius: 39rpx; |
| | | |
| | | &__item { |
| | | height: 77rpx; |
| | | width: 100%; |
| | | line-height: 77rpx; |
| | | text-align: center; |
| | | font-size: 31rpx; |
| | | color: #908f8f; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | z-index: 2; |
| | | transition: all 0.4s; |
| | | |
| | | &--active { |
| | | font-weight: bold; |
| | | color: #FFFFFF; |
| | | } |
| | | } |
| | | |
| | | &__slider { |
| | | position: absolute; |
| | | height: inherit; |
| | | width: calc(476rpx); |
| | | border-radius: inherit; |
| | | box-shadow: 0rpx 18rpx 72rpx 18rpx rgba(0, 195, 255, 0.1); |
| | | z-index: 1; |
| | | transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); |
| | | } |
| | | } |
| | | |
| | | /* 忢 end */ |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ start */ |
| | | &__info { |
| | | margin: 0 30rpx; |
| | | margin-top: 105rpx; |
| | | padding: 30rpx 51rpx; |
| | | padding-bottom: 0; |
| | | border-radius: 20rpx; |
| | | background-color: #ffff; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | |
| | | &__item { |
| | | |
| | | &__input { |
| | | margin-top: 59rpx; |
| | | width: 100%; |
| | | height: 100rpx; |
| | | border: 1rpx solid #E6E6E6; |
| | | border-radius: 39rpx; |
| | | |
| | | &__left-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-left: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__content { |
| | | width: 80%; |
| | | padding-left: 10rpx; |
| | | |
| | | &--verify-code { |
| | | width: 56%; |
| | | } |
| | | |
| | | input { |
| | | font-size: 48rpx; |
| | | // letter-spacing: 0.1em; |
| | | } |
| | | } |
| | | |
| | | &__right-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-right: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__right-verify-code { |
| | | width: 34%; |
| | | margin-right: 20rpx; |
| | | } |
| | | } |
| | | |
| | | &__button { |
| | | margin-top: 75rpx; |
| | | margin-bottom: 39rpx; |
| | | width: 100%; |
| | | height: 77rpx; |
| | | text-align: center; |
| | | font-size: 38rpx; |
| | | font-weight: bold; |
| | | line-height: 77rpx; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | border-radius: 39rpx; |
| | | box-shadow: 1rpx 10rpx 24rpx 0rpx rgba(60, 129, 254, 0.35); |
| | | } |
| | | |
| | | &__tips { |
| | | margin: 30rpx 0; |
| | | color: #AAAAAA; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ end */ |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ start */ |
| | | &__way { |
| | | margin: 0 auto; |
| | | margin-top: 110rpx; |
| | | |
| | | &__item { |
| | | &--icon { |
| | | width: 77rpx; |
| | | height: 77rpx; |
| | | font-size: 50rpx; |
| | | border-radius: 100rpx; |
| | | margin-bottom: 18rpx; |
| | | position: relative; |
| | | z-index: 1; |
| | | |
| | | &::after { |
| | | content: " "; |
| | | position: absolute; |
| | | z-index: -1; |
| | | width: 100%; |
| | | height: 100%; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-radius: inherit; |
| | | opacity: 1; |
| | | transform: scale(1, 1); |
| | | background-size: 100% 100%; |
| | | background-image: url(https://tnuiimage.tnkjapp.com/cool_bg_image/icon_bg5.png); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ end */ |
| | | /* å
容 end */ |
| | | |
| | | } |
| | | |
| | | /deep/.input-placeholder { |
| | | font-size: 24rpx; |
| | | color: #E6E6E6; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="login__info tn-flex tn-flex-direction-column tn-flex-col-center tn-flex-row-center"> |
| | | <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" :disabled="isfill" v-model="barcode" placeholder-class="input-placeholder" |
| | | focus="true" @input="barcodeInput" placeholder="è¯·æ«ææ¡ç " /> |
| | | |
| | | </view> |
| | | <button class="" size="mini" @click="clearSN" > æ¸
空</button> |
| | | </view> |
| | | <!-- <view class="login__info__item__button tn-cool-bg-color-7--reverse" @tap="resrt()" hover-class="tn-hover" |
| | | :hover-stay-time="150">éç½®æ¡ç </view> --> |
| | | <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="station" placeholder-class="input-placeholder" @click="show = true" |
| | | placeholder="è¯·éæ©ä¸æå£" /> |
| | | <u-picker v-model="show" mode="selector" :range="selectorObj" range-key="cateName" @confirm="confirm"> |
| | | </u-picker> |
| | | </view> |
| | | </view> |
| | | <view class="login__info__item__button tn-cool-bg-color-7--reverse" @tap="submit()" hover-class="tn-hover" |
| | | :hover-stay-time="150">éç¥AGV</view> |
| | | <u-toast ref="uToast"></u-toast> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | barcode: '', |
| | | isfill: false, |
| | | show: false, |
| | | station: '', |
| | | stationNo: '', |
| | | selectorObj: [{ |
| | | cateName: '1åå
1å·ä¸æå£', |
| | | id: "1" |
| | | }, |
| | | { |
| | | cateName: '1åå
2å·ä¸æå£', |
| | | id: "2" |
| | | }, |
| | | { |
| | | cateName: '1åå
3å·ä¸æå£', |
| | | id: "3" |
| | | }, |
| | | { |
| | | cateName: '2åå
2å·ä¸æå£', |
| | | id: "5" |
| | | }, |
| | | { |
| | | cateName: '2åå
3å·ä¸æå£', |
| | | id: "6" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | barcodeInput: function(e) { |
| | | if (e.detail.value == "") { |
| | | this.barcode = e.detail.value; |
| | | } else { |
| | | var len = this.barcode.split(',').length; |
| | | if (len <= 4) { |
| | | this.barcode = this.barcode + ','; |
| | | } else { |
| | | this.$t.message.toast('æ°éæå¤ä¸º5个'); |
| | | this.isfill=true; |
| | | return; |
| | | } |
| | | } |
| | | }, |
| | | confirm(e) { |
| | | console.log(e) |
| | | let x = this.selectorObj[e]; |
| | | this.station = x.cateName |
| | | this.stationNo = x.id |
| | | }, |
| | | clearSN:function(e){ |
| | | this.barcode=""; |
| | | this.isfill=false; |
| | | }, |
| | | submit() { |
| | | if (this.barcode == '') { |
| | | this.$t.message.toast('æ¡ç ä¸è½ä¸ºç©º') |
| | | return; |
| | | } |
| | | |
| | | this.$u.post("/api/ToWms/OutsourceInbound", { |
| | | MainData: { |
| | | dataSN: this.barcode, |
| | | stationNo: this.stationNo, |
| | | creator: uni.getStorageSync('jo_user').userName, |
| | | } |
| | | }).then(res => { |
| | | if (res.status) { |
| | | this.barcode = '', |
| | | this.station = '', |
| | | this.stationNo = '', |
| | | this.$t.message.toast('éç¥AGVæåï¼è¯·çå¾
AGVåè´§'); |
| | | } else { |
| | | this.$t.message.toast(res.message); |
| | | } |
| | | console.log(res); |
| | | }).catch(err => { |
| | | |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | // @import '@/static/css/templatePage/custom_nav_bar.scss'; |
| | | /* æ¬æµ® */ |
| | | .rocket-sussuspension { |
| | | animation: suspension 3s ease-in-out infinite; |
| | | } |
| | | |
| | | @keyframes suspension { |
| | | |
| | | 0%, |
| | | 100% { |
| | | transform: translate(0, 0); |
| | | } |
| | | |
| | | 50% { |
| | | transform: translate(-0.8rem, 1rem); |
| | | } |
| | | } |
| | | |
| | | .login { |
| | | position: relative; |
| | | height: 100%; |
| | | z-index: 1; |
| | | |
| | | /* èæ¯å¾ç start */ |
| | | &__bg { |
| | | z-index: -1; |
| | | position: fixed; |
| | | |
| | | &--top { |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | |
| | | .bg { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | |
| | | .rocket { |
| | | margin: 50rpx 28%; |
| | | width: 400rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | |
| | | &--bottom { |
| | | bottom: -10rpx; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | // height: 144px; |
| | | margin-bottom: env(safe-area-inset-bottom); |
| | | |
| | | image { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* èæ¯å¾ç end */ |
| | | |
| | | /* å
容 start */ |
| | | &__wrapper { |
| | | margin-top: 403rpx; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 忢 start */ |
| | | &__mode { |
| | | position: relative; |
| | | margin: 0 auto; |
| | | width: 476rpx; |
| | | height: 77rpx; |
| | | background-color: #FFFFFF; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | border-radius: 39rpx; |
| | | |
| | | &__item { |
| | | height: 77rpx; |
| | | width: 100%; |
| | | line-height: 77rpx; |
| | | text-align: center; |
| | | font-size: 31rpx; |
| | | color: #908f8f; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | z-index: 2; |
| | | transition: all 0.4s; |
| | | |
| | | &--active { |
| | | font-weight: bold; |
| | | color: #FFFFFF; |
| | | } |
| | | } |
| | | |
| | | &__slider { |
| | | position: absolute; |
| | | height: inherit; |
| | | width: calc(476rpx); |
| | | border-radius: inherit; |
| | | box-shadow: 0rpx 18rpx 72rpx 18rpx rgba(0, 195, 255, 0.1); |
| | | z-index: 1; |
| | | transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); |
| | | } |
| | | } |
| | | |
| | | /* 忢 end */ |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ start */ |
| | | &__info { |
| | | margin: 0 30rpx; |
| | | margin-top: 105rpx; |
| | | padding: 30rpx 51rpx; |
| | | padding-bottom: 0; |
| | | border-radius: 20rpx; |
| | | background-color: #ffff; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | |
| | | &__item { |
| | | |
| | | &__input { |
| | | margin-top: 59rpx; |
| | | width: 100%; |
| | | height: 100rpx; |
| | | border: 1rpx solid #E6E6E6; |
| | | border-radius: 39rpx; |
| | | |
| | | &__left-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-left: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__content { |
| | | width: 80%; |
| | | padding-left: 10rpx; |
| | | |
| | | &--verify-code { |
| | | width: 56%; |
| | | } |
| | | |
| | | input { |
| | | font-size: 48rpx; |
| | | // letter-spacing: 0.1em; |
| | | } |
| | | } |
| | | |
| | | &__right-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-right: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__right-verify-code { |
| | | width: 34%; |
| | | margin-right: 20rpx; |
| | | } |
| | | } |
| | | |
| | | &__button { |
| | | margin-top: 75rpx; |
| | | margin-bottom: 39rpx; |
| | | width: 100%; |
| | | height: 77rpx; |
| | | text-align: center; |
| | | font-size: 48rpx; |
| | | font-weight: bold; |
| | | line-height: 77rpx; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | border-radius: 39rpx; |
| | | box-shadow: 1rpx 10rpx 24rpx 0rpx rgba(60, 129, 254, 0.35); |
| | | } |
| | | |
| | | |
| | | &__tips { |
| | | margin: 30rpx 0; |
| | | color: #AAAAAA; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ end */ |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ start */ |
| | | &__way { |
| | | margin: 0 auto; |
| | | margin-top: 110rpx; |
| | | |
| | | &__item { |
| | | &--icon { |
| | | width: 77rpx; |
| | | height: 77rpx; |
| | | font-size: 50rpx; |
| | | border-radius: 100rpx; |
| | | margin-bottom: 18rpx; |
| | | position: relative; |
| | | z-index: 1; |
| | | |
| | | &::after { |
| | | content: " "; |
| | | position: absolute; |
| | | z-index: -1; |
| | | width: 100%; |
| | | height: 100%; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-radius: inherit; |
| | | opacity: 1; |
| | | transform: scale(1, 1); |
| | | background-size: 100% 100%; |
| | | background-image: url(https://tnuiimage.tnkjapp.com/cool_bg_image/icon_bg5.png); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ end */ |
| | | /* å
容 end */ |
| | | |
| | | } |
| | | |
| | | /deep/.input-placeholder { |
| | | font-size: 24rpx; |
| | | color: #E6E6E6; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="page"> |
| | | <view class="top"> |
| | | <view class="background"></view> |
| | | </view> |
| | | <view class="user-card"> |
| | | <view class="card"> |
| | | <view class="top"> |
| | | <view class="userImage"> |
| | | <!-- <open-data type="userAvatarUrl"></open-data> --> |
| | | <u-avatar :src="src" size="146"></u-avatar> |
| | | </view> |
| | | </view> |
| | | <view class="bottom" @click="Login"> |
| | | <view class="left"> |
| | | <view class="user-text"> |
| | | <!-- <open-data type="userNickName"></open-data> --> |
| | | <text style="text-align: center;">{{userNickName}}</text> |
| | | </view> |
| | | <!-- <view class="user-phone"> 171****4133 </view> --> |
| | | </view> |
| | | <view class="right flex-center"> |
| | | <u-icon class="icon" name="arrow-right"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="list-card"> |
| | | <!-- <view class="card"> |
| | | <view class="item item-bottom-solid"> |
| | | <view class="left flex-center"> |
| | | <image src="../../static/myIcon/qiu.png" mode="aspectFit"></image> |
| | | </view> |
| | | <view class="center"> |
| | | <text>åå çæ´»å¨</text> |
| | | </view> |
| | | <view class="right flex-center"> |
| | | <u-icon class="icon" name="arrow-right"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="item item-bottom-solid"> |
| | | <view class="left flex-center"> |
| | | <image src="../../static/myIcon/1.png" mode="aspectFit"></image> |
| | | </view> |
| | | <view class="center"> |
| | | <text>åå çæ´»å¨</text> |
| | | </view> |
| | | <view class="right flex-center"> |
| | | <u-icon class="icon" name="arrow-right"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="item"> |
| | | <view class="left flex-center"> |
| | | <image src="../../static/myIcon/2.png" mode="aspectFit"></image> |
| | | </view> |
| | | <view class="center"> |
| | | <text>åå çæ´»å¨</text> |
| | | </view> |
| | | <view class="right flex-center"> |
| | | <u-icon class="icon" name="arrow-right"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | <view class="quit flex-center"> |
| | | <view class="btn flex-center" @click="LastLogin"> |
| | | éåºç»å½ |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <style lang="scss" scoped> |
| | | .top { |
| | | height: 250rpx; |
| | | position: relative; |
| | | |
| | | .background { |
| | | background-color: #5199ff; |
| | | border-bottom-left-radius: 22px; |
| | | border-bottom-right-radius: 22px; |
| | | position: absolute; |
| | | height: 180rpx; |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | .icon { |
| | | color: #96a1ae; |
| | | font-size: 40rpx; |
| | | } |
| | | |
| | | .user-card { |
| | | height: 170rpx; |
| | | padding: 0 15px; |
| | | |
| | | .card { |
| | | position: relative; |
| | | bottom: 62px; |
| | | height: 250rpx; |
| | | background-color: white; |
| | | border-radius: 5px; |
| | | |
| | | .top { |
| | | height: 30%; |
| | | position: relative; |
| | | |
| | | .userImage { |
| | | position: absolute; |
| | | bottom: 24%; |
| | | left: 10%; |
| | | width: 150rpx; |
| | | height: 150rpx; |
| | | overflow: hidden; |
| | | border-radius: 50%; |
| | | border: 2px solid white; |
| | | } |
| | | } |
| | | |
| | | .bottom { |
| | | display: flex; |
| | | height: 70%; |
| | | |
| | | .left { |
| | | width: 80%; |
| | | height: 100%; |
| | | position: relative; |
| | | |
| | | .user-text { |
| | | width: 100%; |
| | | font-size: 1.6em; |
| | | padding-left: 80rpx; |
| | | height: 50%; |
| | | } |
| | | |
| | | .user-phone { |
| | | color: #96a1ae; |
| | | padding-left: 80rpx; |
| | | height: 50%; |
| | | width: 100%; |
| | | font-size: 0.9em; |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | width: 20%; |
| | | height: 50%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .list-card { |
| | | padding: 0 15px; |
| | | |
| | | .card { |
| | | border-radius: 5px; |
| | | position: relative; |
| | | background-color: white; |
| | | border-radius: 5px; |
| | | padding: 5px 30px; |
| | | |
| | | .item { |
| | | display: flex; |
| | | height: 120rpx; |
| | | |
| | | .left { |
| | | width: 15%; |
| | | |
| | | image { |
| | | width: 70rpx; |
| | | height: 70rpx; |
| | | } |
| | | } |
| | | |
| | | .center { |
| | | width: 65%; |
| | | display: flex; |
| | | justify-content: start; |
| | | align-items: center; |
| | | font-size: 1.1em; |
| | | } |
| | | |
| | | .right { |
| | | width: 20%; |
| | | justify-content: flex-end; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item-bottom-solid { |
| | | border-bottom: 1px solid #d4d6da; |
| | | } |
| | | |
| | | .quit { |
| | | height: 100rpx; |
| | | margin-top: 50px; |
| | | |
| | | .btn { |
| | | background-color: #4f99ff; |
| | | border-radius: 30px; |
| | | width: 80%; |
| | | color: white; |
| | | font-size: 1.2em; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .flex-center { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | </style> |
| | | |
| | | <script> |
| | | //import { } from "@/common/api/{$}.js"; |
| | | import httpInterceptor from '@/common/http.interceptor.js' |
| | | export default { |
| | | data() { |
| | | return { |
| | | src: "", |
| | | userNickName: '请ç»å½', |
| | | }; |
| | | }, |
| | | //çå¬é¡µé¢åå§åï¼å
¶åæ°å onLoad åæ°ï¼ä¸ºä¸ä¸ªé¡µé¢ä¼ éçæ°æ®ï¼åæ°ç±»å为 Objectï¼ç¨äºé¡µé¢ä¼ åï¼ï¼è§¦åæ¶æºæ©äº onLoad |
| | | onInit() {}, |
| | | //çå¬é¡µé¢å è½½ï¼å
¶åæ°ä¸ºä¸ä¸ªé¡µé¢ä¼ éçæ°æ®ï¼åæ°ç±»å为 Objectï¼ç¨äºé¡µé¢ä¼ åï¼ |
| | | onLoad() { |
| | | let isLogin = this.hasLogin(); |
| | | if (isLogin) { |
| | | let haslogin = uni.getStorageSync('jo_user') |
| | | this.userNickName = haslogin.userName; |
| | | this.src = httpInterceptor.baseUrl + "/" + haslogin.img; |
| | | } |
| | | }, |
| | | //çå¬é¡µé¢å次渲æå®æã注æå¦ææ¸²æé度快ï¼ä¼å¨é¡µé¢è¿å
¥å¨ç»å®æå触å |
| | | onReady() {}, |
| | | //çå¬é¡µé¢æ¾ç¤ºã页颿¯æ¬¡åºç°å¨å±å¹ä¸é½è§¦åï¼å
æ¬ä»ä¸çº§é¡µé¢ç¹è¿åé²åºå½åé¡µé¢ |
| | | beforeDestroy() {}, |
| | | //页颿»å¨å°åºé¨çäºä»¶ï¼ä¸æ¯scroll-viewæ»å°åºï¼ï¼å¸¸ç¨äºä¸æä¸ä¸é¡µæ°æ®ã |
| | | onReachBottom() {}, |
| | | onShareAppMessage(res) {}, |
| | | created() {}, |
| | | methods: { |
| | | hasLogin() { |
| | | let haslogin = uni.getStorageSync('jo_user') |
| | | if (haslogin == null || haslogin == "") { |
| | | return false |
| | | } else { |
| | | return true |
| | | } |
| | | }, |
| | | |
| | | LastLogin() { |
| | | uni.clearStorage(); |
| | | this.$router.go(0) |
| | | }, |
| | | |
| | | Login(){ |
| | | this.$u.route('/pages/login/login'); |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <u-card :title="title" > |
| | | <view class="" slot="body"> |
| | | <u-grid :col="3"> |
| | | <u-grid-item @tap="clickCoupon"> |
| | | <u-icon name="order" :size="46"></u-icon> |
| | | <view class="grid-text">å¤åç§»åº</view> |
| | | </u-grid-item> |
| | | <u-grid-item @tap="lock"> |
| | | <u-icon name="car-fill" :size="46"></u-icon> |
| | | <view class="grid-text">å¤åå
¥åº</view> |
| | | </u-grid-item> |
| | | <u-grid-item @tap="AGV"> |
| | | <u-icon name="car" :size="46"></u-icon> |
| | | <view class="grid-text">空ç</view> |
| | | </u-grid-item> |
| | | </u-grid> |
| | | </view> |
| | | </u-card> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | title: 'æä½åè½' |
| | | } |
| | | }, |
| | | onLoad() { |
| | | |
| | | }, |
| | | methods: { |
| | | clickCoupon(){ |
| | | if(this.hasLogin()){ |
| | | this.$u.route("pages/unpacking/unpacking") |
| | | }else{ |
| | | this.$t.message.loading('ç»å½å¤±æè¯·éæ°ç»å½') |
| | | setTimeout(()=>{ |
| | | this.$t.message.closeLoading() |
| | | this.$u.route({ |
| | | type:'reLaunch', |
| | | url:'pages/login/login' |
| | | }) |
| | | // this.$Router.replace({name:"tabbar"}) |
| | | },1300) |
| | | } |
| | | }, |
| | | lock(){ |
| | | console.log("lock") |
| | | if(this.hasLogin()){ |
| | | this.$u.route("pages/feeding/feeding") |
| | | }else{ |
| | | this.$t.message.loading('ç»å½å¤±æè¯·éæ°ç»å½') |
| | | setTimeout(()=>{ |
| | | |
| | | this.$t.message.closeLoading() |
| | | this.$u.route({ |
| | | type:'reLaunch', |
| | | url:'pages/login/login' |
| | | }) |
| | | // this.$Router.replace({name:"tabbar"}) |
| | | },1300) |
| | | } |
| | | }, |
| | | AGV(){ |
| | | console.log("AGV") |
| | | if(this.hasLogin()){ |
| | | this.$u.route("pages/AGV/AGV") |
| | | }else{ |
| | | this.$t.message.loading('ç»å½å¤±æè¯·éæ°ç»å½') |
| | | setTimeout(()=>{ |
| | | |
| | | this.$t.message.closeLoading() |
| | | this.$u.route({ |
| | | type:'reLaunch', |
| | | url:'pages/login/login' |
| | | }) |
| | | // this.$Router.replace({name:"tabbar"}) |
| | | },1300) |
| | | } |
| | | }, |
| | | |
| | | //夿æ¯å¦ç»å½ |
| | | hasLogin(){ |
| | | let haslogin= uni.getStorageSync('jo_user') |
| | | if(haslogin==null||haslogin==""){ |
| | | return false |
| | | } |
| | | else{ |
| | | return true |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .grid-text { |
| | | font-size: 28rpx; |
| | | margin-top: 4rpx; |
| | | color: $u-type-info; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="template-login"> |
| | | <!-- é¡¶é¨èªå®ä¹å¯¼èª --> |
| | | <!-- <tn-nav-bar fixed alpha customBack> |
| | | <view slot="back" class='tn-custom-nav-bar__back' |
| | | @click="goBack"> |
| | | <text class='icon tn-icon-left'></text> |
| | | <text class='icon tn-icon-home-capsule-fill'></text> |
| | | </view> |
| | | </tn-nav-bar> --> |
| | | |
| | | <view class="login"> |
| | | <!-- é¡¶é¨èæ¯å¾ç--> |
| | | <view class="login__bg login__bg--top"> |
| | | <image class="bg" src="/static/login_top2.jpg" mode="widthFix"></image> |
| | | </view> |
| | | <view class="login__bg login__bg--top"> |
| | | <image class="rocket rocket-sussuspension" src="/static/login_top3.png" mode="widthFix"></image> |
| | | </view> |
| | | |
| | | <view class="login__wrapper"> |
| | | <!-- ç»å½/注å忢 --> |
| | | <!-- <view class="login__mode tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-center"> |
| | | <view class="login__mode__item tn-flex-1" :class="[{'login__mode__item--active': currentModeIndex === 0}]" @tap.stop="modeSwitch(0)"> |
| | | ç»å½ |
| | | </view> |
| | | <view class="login__mode__item tn-flex-1" :class="[{'login__mode__item--active': currentModeIndex === 1}]" @tap.stop="modeSwitch(1)"> |
| | | 注å |
| | | </view> |
| | | |
| | | <view class="login__mode__slider tn-cool-bg-color-15--reverse" :style="[modeSliderStyle]"></view> |
| | | </view> --> |
| | | |
| | | <!-- è¾å
¥æ¡å
容--> |
| | | <view class="login__info tn-flex tn-flex-direction-column tn-flex-col-center tn-flex-row-center"> |
| | | <!-- ç»å½ --> |
| | | <block v-if="currentModeIndex === 0"> |
| | | <view class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__left-icon"> |
| | | <view class="tn-icon-my"></view> |
| | | </view> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="45" placeholder-class="input-placeholder" @input="userInput" placeholder="请è¾å
¥ç»å½ç¨æ·åç§°" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__left-icon"> |
| | | <view class="tn-icon-lock"></view> |
| | | </view> |
| | | <view class="login__info__item__input__content"> |
| | | <input :password="!showPassword" placeholder-class="input-placeholder" @input="passInput" placeholder="请è¾å
¥ç»å½å¯ç " /> |
| | | </view> |
| | | <view class="login__info__item__input__right-icon" @click="showPassword = !showPassword"> |
| | | <view :class="[showPassword ? 'tn-icon-eye' : 'tn-icon-eye-hide']"></view> |
| | | </view> |
| | | </view> |
| | | <view class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__left-icon"> |
| | | <view class="tn-icon-my"></view> |
| | | </view> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="45" placeholder-class="input-placeholder" @input="codeInput" placeholder="请è¾å
¥éªè¯ç " /> |
| | | </view> |
| | | <view class="login__info__item__input__right-icon u-border" style="width: 30%;" @click="getVierificationCode"> |
| | | <img v-show="codeImgSrc != ''" :src="codeImgSrc" /> |
| | | </view> |
| | | </view> |
| | | </block> |
| | | <!-- 注å --> |
| | | <view class="login__info__item__button tn-cool-bg-color-7--reverse" @click="currentModeIndex === 0 ? login() : registra()" hover-class="tn-hover" :hover-stay-time="150">{{ currentModeIndex === 0 ? 'ç»å½' : '注å'}}</view> |
| | | |
| | | <!-- <view v-if="currentModeIndex === 0" class="login__info__item__tips">å¿è®°å¯ç ?</view> --> |
| | | </view> |
| | | </view> |
| | | |
| | | <tn-tips ref="tips" position="top"></tn-tips> |
| | | <!-- åºé¨èæ¯å¾ç--> |
| | | <view class="login__bg login__bg--bottom"> |
| | | <image src="/static/login_bottom_bg.jpg" mode="widthFix"></image> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- éªè¯ç åè®¡æ¶ --> |
| | | <!-- <tn-verification-code |
| | | ref="code" |
| | | uniqueKey="login-demo-1" |
| | | :seconds="60" |
| | | @change="codeChange"> |
| | | </tn-verification-code> --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | var app = getApp(); |
| | | export default { |
| | | name: 'login-demo-1', |
| | | // mixins: [template_page_mixin], |
| | | data() { |
| | | return { |
| | | // å½åéä¸çæ¨¡å¼ |
| | | currentModeIndex: 0, |
| | | // 模å¼é䏿»å |
| | | modeSliderStyle: { |
| | | left: 0 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå¯ç |
| | | showPassword: false, |
| | | // åè®¡æ¶æç¤ºæå |
| | | tips: 'è·åéªè¯ç ', |
| | | email: '', |
| | | codeImgSrc: '', |
| | | pass: '', |
| | | code: '', |
| | | user: '', |
| | | isDetail: false |
| | | } |
| | | }, |
| | | watch: { |
| | | currentModeIndex(value) { |
| | | const sliderWidth = uni.upx2px(476 / 2) |
| | | this.modeSliderStyle.left = `${sliderWidth * value}px` |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | this.getVierificationCode() |
| | | if (options.id) { |
| | | this.isDetail = true |
| | | } |
| | | }, |
| | | methods: { |
| | | ///è·åéªè¯ç |
| | | getVierificationCode() { |
| | | this.$u.get('/api/User/getVierificationCode', {}).then(res=>{ |
| | | if (res.img != null) { |
| | | this.codeImgSrc = "data:image/png;base64," + res.img; |
| | | this.email = res.uuid; |
| | | } else { |
| | | this.$refs.uToast.show({ |
| | | title: 'è·åéªè¯ç å¤±è´¥è¯·éæ°è·å', |
| | | type: 'error', |
| | | }) |
| | | } |
| | | }) |
| | | // uni.request({ |
| | | // url:"http://192.168.0.101:8098/api/User/getVierificationCode", |
| | | // success: (res) => { |
| | | |
| | | // } |
| | | // }) |
| | | }, |
| | | login() { |
| | | if (this.pass == '') { |
| | | this.$t.message.toast('请è¾å
¥å¯ç ') |
| | | return; |
| | | } else if (this.user == '') { |
| | | this.$t.message.toast('请è¾å
¥ç¨æ·å') |
| | | return; |
| | | } else if (this.pass.length < 6) { |
| | | this.$t.message.toast('å¯ç åºå¤§äº6ä½') |
| | | return; |
| | | } else { |
| | | this.$t.message.loading('æ£å¨ç»å½') |
| | | let userInfo = this.userInfo; |
| | | let userifno = { |
| | | UUID: this.email, |
| | | passWord: this.pass, |
| | | userName: this.user, |
| | | verificationCode: this.code |
| | | } |
| | | this.$u.post('/api/User/login', { |
| | | UUID: this.email, |
| | | passWord: this.pass, |
| | | userName: this.user, |
| | | verificationCode: this.code |
| | | }).then(res => { |
| | | // this.$u.toast(res.message); |
| | | this.$t.message.toast(res.message) |
| | | this.$t.message.closeLoading() |
| | | uni.setStorage({ |
| | | key: 'jo_id_token', |
| | | data: res.data.token, |
| | | }); |
| | | uni.setStorage({ |
| | | key: 'jo_user', |
| | | data: res.data, |
| | | }); |
| | | uni.setStorage({ |
| | | key: 'jo_userImg', |
| | | data: res.data.img, |
| | | }); |
| | | setTimeout(()=>{ |
| | | this.$u.route({ |
| | | type:'reLaunch', |
| | | url:'pages/index/index' |
| | | }) |
| | | // this.$Router.replace({name:"tabbar"}) |
| | | },1300) |
| | | }); |
| | | |
| | | } |
| | | }, |
| | | codeInput: function(e) { |
| | | this.code = e.detail.value; |
| | | }, |
| | | passInput: function(e) { |
| | | this.pass = e.detail.value; |
| | | }, |
| | | userInput: function(e) { |
| | | this.user = e.detail.value; |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | // @import '@/static/css/templatePage/custom_nav_bar.scss'; |
| | | /* æ¬æµ® */ |
| | | .rocket-sussuspension{ |
| | | animation: suspension 3s ease-in-out infinite; |
| | | } |
| | | |
| | | @keyframes suspension { |
| | | 0%, 100% { |
| | | transform: translate(0 , 0); |
| | | } |
| | | 50% { |
| | | transform: translate(-0.8rem , 1rem); |
| | | } |
| | | } |
| | | |
| | | .login { |
| | | position: relative; |
| | | height: 100%; |
| | | z-index: 1; |
| | | |
| | | /* èæ¯å¾ç start */ |
| | | &__bg { |
| | | z-index: -1; |
| | | position: fixed; |
| | | |
| | | &--top { |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | |
| | | .bg { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | .rocket { |
| | | margin: 50rpx 28%; |
| | | width: 400rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | |
| | | &--bottom { |
| | | bottom: -10rpx; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | // height: 144px; |
| | | margin-bottom: env(safe-area-inset-bottom); |
| | | |
| | | image { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | } |
| | | /* èæ¯å¾ç end */ |
| | | |
| | | /* å
容 start */ |
| | | &__wrapper { |
| | | margin-top: 250rpx; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 忢 start */ |
| | | &__mode { |
| | | position: relative; |
| | | margin: 0 auto; |
| | | width: 476rpx; |
| | | height: 77rpx; |
| | | background-color: #FFFFFF; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | border-radius: 39rpx; |
| | | |
| | | &__item { |
| | | height: 77rpx; |
| | | width: 100%; |
| | | line-height: 77rpx; |
| | | text-align: center; |
| | | font-size: 31rpx; |
| | | color: #908f8f; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | z-index: 2; |
| | | transition: all 0.4s; |
| | | |
| | | &--active { |
| | | font-weight: bold; |
| | | color: #FFFFFF; |
| | | } |
| | | } |
| | | |
| | | &__slider { |
| | | position: absolute; |
| | | height: inherit; |
| | | width: calc(476rpx); |
| | | border-radius: inherit; |
| | | box-shadow: 0rpx 18rpx 72rpx 18rpx rgba(0, 195, 255, 0.1); |
| | | z-index: 1; |
| | | transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); |
| | | } |
| | | } |
| | | /* 忢 end */ |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ start */ |
| | | &__info { |
| | | margin: 0 30rpx; |
| | | margin-top: 105rpx; |
| | | padding: 30rpx 51rpx; |
| | | padding-bottom: 0; |
| | | border-radius: 20rpx; |
| | | background-color: #ffff; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | |
| | | &__item { |
| | | |
| | | &__input { |
| | | margin-top: 59rpx; |
| | | width: 100%; |
| | | height: 77rpx; |
| | | border: 1rpx solid #E6E6E6; |
| | | border-radius: 39rpx; |
| | | |
| | | &__left-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-left: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__content { |
| | | width: 80%; |
| | | padding-left: 10rpx; |
| | | |
| | | &--verify-code { |
| | | width: 56%; |
| | | } |
| | | |
| | | input { |
| | | font-size: 24rpx; |
| | | // letter-spacing: 0.1em; |
| | | } |
| | | } |
| | | |
| | | &__right-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-right: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__right-verify-code { |
| | | width: 34%; |
| | | margin-right: 20rpx; |
| | | } |
| | | } |
| | | |
| | | &__button { |
| | | margin-top: 75rpx; |
| | | margin-bottom: 39rpx; |
| | | width: 100%; |
| | | height: 77rpx; |
| | | text-align: center; |
| | | font-size: 31rpx; |
| | | font-weight: bold; |
| | | line-height: 77rpx; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | border-radius: 39rpx; |
| | | box-shadow: 1rpx 10rpx 24rpx 0rpx rgba(60, 129, 254, 0.35); |
| | | } |
| | | |
| | | &__tips { |
| | | margin: 30rpx 0; |
| | | color: #AAAAAA; |
| | | } |
| | | } |
| | | } |
| | | /* ç»å½æ³¨åä¿¡æ¯ end */ |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ start */ |
| | | &__way { |
| | | margin: 0 auto; |
| | | margin-top: 110rpx; |
| | | |
| | | &__item { |
| | | &--icon { |
| | | width: 77rpx; |
| | | height: 77rpx; |
| | | font-size: 50rpx; |
| | | border-radius: 100rpx; |
| | | margin-bottom: 18rpx; |
| | | position: relative; |
| | | z-index: 1; |
| | | |
| | | &::after { |
| | | content: " "; |
| | | position: absolute; |
| | | z-index: -1; |
| | | width: 100%; |
| | | height: 100%; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-radius: inherit; |
| | | opacity: 1; |
| | | transform: scale(1, 1); |
| | | background-size: 100% 100%; |
| | | background-image: url(https://tnuiimage.tnkjapp.com/cool_bg_image/icon_bg5.png); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* ç»å½æ¹å¼åæ¢ end */ |
| | | /* å
容 end */ |
| | | |
| | | } |
| | | |
| | | /deep/.input-placeholder { |
| | | font-size: 24rpx; |
| | | color: #E6E6E6; |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view> |
| | | <view class="login__info tn-flex tn-flex-direction-column tn-flex-col-center tn-flex-row-center"> |
| | | <!-- <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="jobID" focus="true" placeholder-class="input-placeholder" |
| | | @input="jobIDInput" placeholder="请è¾å
¥äº¤æ¥å·¥å" /> |
| | | </view> |
| | | </view> --> |
| | | <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="barcode" focus="true" placeholder-class="input-placeholder" |
| | | @input="barcodeInput" placeholder="è¯·æ«ææåºä¸ç车轮å·" /> |
| | | </view> |
| | | </view> |
| | | <!-- <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="cacheName" placeholder-class="input-placeholder" |
| | | @click="cacheshow=true" placeholder="è¯·éæ©ç¼åæ¶ç¼å·" /> |
| | | <u-picker v-model="cacheshow" mode="selector" :range="selectorCache" range-key="cateName" |
| | | @confirm="cacheConfirm"></u-picker> |
| | | </view> |
| | | </view> --> |
| | | <!-- <view |
| | | class="login__info__item__input tn-flex tn-flex-direction-row tn-flex-nowrap tn-flex-col-center tn-flex-row-left"> |
| | | <view class="login__info__item__input__content"> |
| | | <input maxlength="500" v-model="stationName" placeholder-class="input-placeholder" |
| | | @click="stationshow=true" placeholder="è¯·éæ©ä¸æå£" /> |
| | | <u-picker v-model="stationshow" mode="selector" :range="selectorStation" range-key="cateName" |
| | | @confirm="stationConfirm"></u-picker> |
| | | </view> |
| | | </view> --> |
| | | <view class="login__info__item__button tn-cool-bg-color-7--reverse" @tap="submitCheek()" |
| | | hover-class="tn-hover" :hover-stay-time="150">ä¿¡æ¯æ ¸å¯¹</view> |
| | | <view :class="istrue?'isnone':'isnonone'"> |
| | | <view class="login__info__item__button tn-cool-bg-color-7--reverse" @tap="submitTransfer()" |
| | | hover-class="tn-hover" :hover-stay-time="150" style="margin-top: 0px;">å
¥ç¼åæ¶</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | jobID: '', |
| | | barcode: '', |
| | | cacheNo: '', |
| | | cacheName: '', |
| | | stationNo: '', |
| | | stationName: '', |
| | | istrue: true, |
| | | cacheshow: false, |
| | | stationshow: false, |
| | | selectorCache: [{ |
| | | cateName: '1å·ç¼åæ¶', |
| | | id: 1 |
| | | }, |
| | | { |
| | | cateName: '2å·ç¼åæ¶', |
| | | id: 2 |
| | | }, |
| | | { |
| | | cateName: '3å·ç¼åæ¶', |
| | | id: 3 |
| | | }, |
| | | { |
| | | cateName: '4å·ç¼åæ¶', |
| | | id: 4 |
| | | }, |
| | | { |
| | | cateName: '5å·ç¼åæ¶', |
| | | id: 5 |
| | | }, |
| | | { |
| | | cateName: '6å·ç¼åæ¶', |
| | | id: 6 |
| | | } |
| | | ], |
| | | selectorStation: [{ |
| | | cateName: 'Båºæ£æææå£', |
| | | id: "DepThreeForZJYJ" |
| | | }, |
| | | { |
| | | cateName: 'Båºè´æææå£', |
| | | id: "DepThreeForFJYJ" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | ///å·¥åå· |
| | | jobIDInput: function(e) { |
| | | this.jobID = e.detail.value; |
| | | console.log(this.jobID); |
| | | }, |
| | | ///æ¡ç |
| | | barcodeInput: function(e) { |
| | | this.barcode = e.detail.value; |
| | | console.log(this.barcode); |
| | | console.log(uni.getStorageSync('jo_user')); |
| | | }, |
| | | //ç¼åæ¶ç¼å· |
| | | cacheConfirm(e) { |
| | | let x = this.selectorCache[e]; |
| | | this.cacheName = x.cateName |
| | | this.cacheNo = x.id |
| | | }, |
| | | //ä¸æå£ |
| | | stationConfirm(e) { |
| | | let x = this.selectorStation[e]; |
| | | this.stationName = x.cateName |
| | | this.stationNo = x.id |
| | | }, |
| | | //MESä¿¡æ¯æ ¡éª |
| | | submitCheek() { |
| | | if (this.barcode == '') { |
| | | this.$t.message.toast('æ¡ç ä¸è½ä¸ºç©º'); |
| | | return |
| | | } |
| | | // else if (this.stationNo == '') { |
| | | // this.$t.message.toast('䏿å£ä¸è½ä¸ºç©º'); |
| | | // return |
| | | // } |
| | | |
| | | // console.log(ip); |
| | | this.$u.post("api/ToWms/agvTransferList", { |
| | | MainData: { |
| | | sn: this.barcode, |
| | | jobID: this.jobID, |
| | | // cacheNo: this.cacheNo, |
| | | // address: this.stationNo, |
| | | creator: uni.getStorageSync('jo_user').userName, |
| | | //targetWorkshop:"1" |
| | | } |
| | | }).then(res => { |
| | | if (res.status) { |
| | | this.istrue = false; |
| | | this.$t.message.toast('æ ¡éªæå'); |
| | | } else { |
| | | this.istrue = true; |
| | | this.$t.message.toast(res.message); |
| | | } |
| | | }).catch(err => { |
| | | |
| | | }) |
| | | }, |
| | | //éè³ä¸æ¥¼ |
| | | submitTransfer() { |
| | | if (this.barcode == '') { |
| | | this.$t.message.toast('æ¡ç ä¸è½ä¸ºç©º'); |
| | | return |
| | | } else if (this.cacheNo == '') { |
| | | this.$t.message.toast('ç¼åæ¶ç¼å·ä¸è½ä¸ºç©º'); |
| | | return |
| | | } |
| | | this.stationNo = "DepThreeForZJYJ"; |
| | | this.$u.post("/api/ToWCS/SendFirstFloor", { |
| | | MainData: { |
| | | dataSN: this.barcode, |
| | | cacheNo: this.cacheNo, |
| | | address: this.stationNo, |
| | | creator: uni.getStorageSync('jo_user').userName |
| | | } |
| | | }).then(res => { |
| | | if (res.status) { |
| | | this.barcode = '', |
| | | this.cacheNo = '', |
| | | this.cacheName = '', |
| | | this.stationNo = '', |
| | | this.stationName = '', |
| | | this.istrue = true; |
| | | this.$t.message.toast('éè³ä¸æ¥¼æåï¼è¯·ææåæºä¸åæé®'); |
| | | } else { |
| | | this.$t.message.toast(res.message); |
| | | } |
| | | }).catch(err => { |
| | | |
| | | }) |
| | | }, |
| | | stop() { |
| | | // setInterval(function() { |
| | | // uni.hideKeyboard(); //éè软é®ç |
| | | // },5); |
| | | }, |
| | | |
| | | }, |
| | | onLoad() { |
| | | let _self = this; |
| | | _self.stop() |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .isnone { |
| | | display: none; |
| | | width: 100%; |
| | | } |
| | | |
| | | .isnonone { |
| | | width: 100%; |
| | | } |
| | | |
| | | // @import '@/static/css/templatePage/custom_nav_bar.scss'; |
| | | /* æ¬æµ® */ |
| | | .rocket-sussuspension { |
| | | animation: suspension 3s ease-in-out infinite; |
| | | } |
| | | |
| | | @keyframes suspension { |
| | | |
| | | 0%, |
| | | 100% { |
| | | transform: translate(0, 0); |
| | | } |
| | | |
| | | 50% { |
| | | transform: translate(-0.8rem, 1rem); |
| | | } |
| | | } |
| | | |
| | | .login { |
| | | position: relative; |
| | | height: 100%; |
| | | z-index: 1; |
| | | |
| | | /* èæ¯å¾ç start */ |
| | | &__bg { |
| | | z-index: -1; |
| | | position: fixed; |
| | | |
| | | &--top { |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | |
| | | .bg { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | |
| | | .rocket { |
| | | margin: 50rpx 28%; |
| | | width: 400rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | |
| | | &--bottom { |
| | | bottom: -10rpx; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | // height: 144px; |
| | | margin-bottom: env(safe-area-inset-bottom); |
| | | |
| | | image { |
| | | width: 750rpx; |
| | | will-change: transform; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* èæ¯å¾ç end */ |
| | | |
| | | /* å
容 start */ |
| | | &__wrapper { |
| | | margin-top: 403rpx; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 忢 start */ |
| | | &__mode { |
| | | position: relative; |
| | | margin: 0 auto; |
| | | width: 476rpx; |
| | | height: 77rpx; |
| | | background-color: #FFFFFF; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | border-radius: 39rpx; |
| | | |
| | | &__item { |
| | | height: 77rpx; |
| | | width: 100%; |
| | | line-height: 77rpx; |
| | | text-align: center; |
| | | font-size: 31rpx; |
| | | color: #908f8f; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | z-index: 2; |
| | | transition: all 0.4s; |
| | | |
| | | &--active { |
| | | font-weight: bold; |
| | | color: #FFFFFF; |
| | | } |
| | | } |
| | | |
| | | &__slider { |
| | | position: absolute; |
| | | height: inherit; |
| | | width: calc(476rpx); |
| | | border-radius: inherit; |
| | | box-shadow: 0rpx 18rpx 72rpx 18rpx rgba(0, 195, 255, 0.1); |
| | | z-index: 1; |
| | | transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); |
| | | } |
| | | } |
| | | |
| | | /* 忢 end */ |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ start */ |
| | | &__info { |
| | | margin: 0 30rpx; |
| | | margin-top: 105rpx; |
| | | padding: 30rpx 51rpx; |
| | | padding-bottom: 0; |
| | | border-radius: 20rpx; |
| | | background-color: #ffff; |
| | | box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1); |
| | | |
| | | &__item { |
| | | |
| | | &__input { |
| | | margin-top: 59rpx; |
| | | width: 100%; |
| | | height: 100rpx; |
| | | border: 1rpx solid #E6E6E6; |
| | | border-radius: 39rpx; |
| | | |
| | | &__left-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-left: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__content { |
| | | width: 80%; |
| | | padding-left: 10rpx; |
| | | |
| | | &--verify-code { |
| | | width: 56%; |
| | | } |
| | | |
| | | input { |
| | | font-size: 48rpx; |
| | | // letter-spacing: 0.1em; |
| | | } |
| | | } |
| | | |
| | | &__right-icon { |
| | | width: 10%; |
| | | font-size: 44rpx; |
| | | margin-right: 20rpx; |
| | | color: #AAAAAA; |
| | | } |
| | | |
| | | &__right-verify-code { |
| | | width: 34%; |
| | | margin-right: 20rpx; |
| | | } |
| | | } |
| | | |
| | | &__button { |
| | | margin-top: 75rpx; |
| | | margin-bottom: 39rpx; |
| | | width: 100%; |
| | | height: 77rpx; |
| | | text-align: center; |
| | | font-size: 48rpx; |
| | | font-weight: bold; |
| | | line-height: 77rpx; |
| | | letter-spacing: 1em; |
| | | text-indent: 1em; |
| | | border-radius: 39rpx; |
| | | box-shadow: 1rpx 10rpx 24rpx 0rpx rgba(60, 129, 254, 0.35); |
| | | } |
| | | |
| | | &__tips { |
| | | margin: 30rpx 0; |
| | | color: #AAAAAA; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ³¨åä¿¡æ¯ end */ |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ start */ |
| | | &__way { |
| | | margin: 0 auto; |
| | | margin-top: 110rpx; |
| | | |
| | | &__item { |
| | | &--icon { |
| | | width: 77rpx; |
| | | height: 77rpx; |
| | | font-size: 50rpx; |
| | | border-radius: 100rpx; |
| | | margin-bottom: 18rpx; |
| | | position: relative; |
| | | z-index: 1; |
| | | |
| | | &::after { |
| | | content: " "; |
| | | position: absolute; |
| | | z-index: -1; |
| | | width: 100%; |
| | | height: 100%; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-radius: inherit; |
| | | opacity: 1; |
| | | transform: scale(1, 1); |
| | | background-size: 100% 100%; |
| | | background-image: url(https://tnuiimage.tnkjapp.com/cool_bg_image/icon_bg5.png); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ç»å½æ¹å¼åæ¢ end */ |
| | | /* å
容 end */ |
| | | |
| | | } |
| | | |
| | | /deep/.input-placeholder { |
| | | font-size: 24rpx; |
| | | color: #E6E6E6; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="zh-CN"> |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| | | <link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico"> |
| | | <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> |
| | | <title> |
| | | <%= htmlWebpackPlugin.options.title %> |
| | | </title> |
| | | <script> |
| | | document.addEventListener('DOMContentLoaded', function() { |
| | | document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px' |
| | | }) |
| | | </script> |
| | | <link rel="stylesheet" href="<%= BASE_URL %>static/index.css" /> |
| | | </head> |
| | | <body> |
| | | <noscript> |
| | | <strong>æ¬ç«ç¹å¿
é¡»è¦å¼å¯JavaScriptæè½è¿è¡</strong> |
| | | </noscript> |
| | | <div id="app"></div> |
| | | </body> |
| | | </html> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | TuniaoUi for uniApp v1.0.0 | by å¾é¸ 2021-09-01 |
| | | ä»
ä¾å¼åï¼å¦ä½å®ç¨ææ¿åçæ³å¾è´£ä»»ä¸æ¦ä¸ä½è
æ å
³ |
| | | |
| | | *使ç¨TuniaoUiå¼åæ©å±ä¸æä»¶æ¶ï¼è¯·æ³¨æåºäºtuniaoåç¼ |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="value" class="tn-action-sheet-class tn-action-sheet"> |
| | | <tn-popup |
| | | v-model="value" |
| | | mode="bottom" |
| | | length="auto" |
| | | :popup="false" |
| | | :borderRadius="borderRadius" |
| | | :maskCloseable="maskCloseable" |
| | | :safeAreaInsetBottom="safeAreaInsetBottom" |
| | | :zIndex="elZIndex" |
| | | @close="close" |
| | | > |
| | | <!-- æç¤ºä¿¡æ¯ --> |
| | | <view |
| | | v-if="tips.text" |
| | | class="tn-action-sheet__tips tn-border-solid-bottom" |
| | | :style="[tipsStyle]" |
| | | > |
| | | {{tips.text}} |
| | | </view> |
| | | <!-- æé®å表 --> |
| | | <block v-for="(item, index) in list" :key="index"> |
| | | <view |
| | | class="tn-action-sheet__item tn-text-ellipsis" |
| | | :class="[ index < list.length - 1 ? 'tn-border-solid-bottom' : '']" |
| | | :style="[itemStyle(index)]" |
| | | hover-class="tn-hover-class" |
| | | :hover-stay-time="150" |
| | | @tap="itemClick(index)" |
| | | @touchmove.stop.prevent |
| | | > |
| | | <text>{{item.text}}</text> |
| | | <text v-if="item.subText" class="tn-action-sheet__item__subtext tn-text-ellipsis">{{item.subText}}</text> |
| | | </view> |
| | | </block> |
| | | |
| | | <!-- åæ¶æé® --> |
| | | <block v-if="cancelBtn"> |
| | | <view class="tn-action-sheet__cancel--gab"></view> |
| | | <view |
| | | class="tn-action-sheet__cancel tn-action-sheet__item" |
| | | hover-class="tn-hover-class" |
| | | :hover-stay-time="150" |
| | | @tap="close" |
| | | >{{cancelText}}</view> |
| | | </block> |
| | | |
| | | </tn-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-action-sheet', |
| | | props: { |
| | | // éè¿v-modelæ§å¶å¼¹åºåæ¶èµ· |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æé®æåæ°ç»ï¼å¯ä»¥èªå®ä¹é¢è²ååä½å¤§å° |
| | | // return [{ |
| | | // text: 'ç¡®å®', |
| | | // subText: 'è¿æ¯ä¸ä¸ªç¡®å®æé®', |
| | | // color: '', |
| | | // fontSize: '', |
| | | // disabled: true |
| | | // }] |
| | | list: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // é¡¶é¨æç¤ºæå |
| | | tips: { |
| | | type: Object, |
| | | default() { |
| | | return { |
| | | text: '', |
| | | color: '', |
| | | fontSize: 26 |
| | | } |
| | | } |
| | | }, |
| | | // å¼¹åºçé¡¶é¨åè§å¼ |
| | | borderRadius: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // ç¹å»é®ç½©å¯ä»¥å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // åºé¨åæ¶æé® |
| | | cancelBtn: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // åºé¨åæ¶æé®çæå |
| | | cancelText: { |
| | | type: String, |
| | | default: 'åæ¶' |
| | | }, |
| | | // å¼å¯åºé¨å®å
¨åºå |
| | | // å¨iPhoneXæºååºé¨æ·»å ä¸å®çå
è¾¹è· |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // z-indexå¼ |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | // é¡¶é¨æç¤ºæ ·å¼ |
| | | tipsStyle() { |
| | | let style = {} |
| | | if (this.tips.color) style.color = this.tips.color |
| | | if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx' |
| | | |
| | | return style |
| | | }, |
| | | // æä½é¡¹ç®çæ ·å¼ |
| | | itemStyle() { |
| | | return (index) => { |
| | | let style = {} |
| | | if (this.list[index].color) style.color = this.list[index].color |
| | | if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx' |
| | | |
| | | // é项被ç¦ç¨çæ ·å¼ |
| | | if (this.list[index].disabled) style.color = '#AAAAAA' |
| | | |
| | | return style |
| | | } |
| | | }, |
| | | elZIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.popup |
| | | } |
| | | }, |
| | | methods: { |
| | | // ç¹å»åæ¶æé® |
| | | close() { |
| | | // åéinputäºä»¶ï¼å¹¶ä¸ä¼ä½ç¨äºç¶ç»ä»¶ï¼èæ¯è¦è®¾ç½®ç»ä»¶å
é¨éè¿propsä¼ éçvalueåæ° |
| | | this.popupClose(); |
| | | this.$emit('close'); |
| | | }, |
| | | // å
³éå¼¹çª |
| | | popupClose() { |
| | | this.$emit('input', false) |
| | | }, |
| | | // ç¹å»å¯¹åºçitem |
| | | itemClick(index) { |
| | | // 妿æ¯ç¦ç¨é¡¹åä¸è¿è¡æä½ |
| | | if (this.list[index].disabled) return |
| | | this.$emit('click', index) |
| | | this.popupClose() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-action-sheet { |
| | | &__tips { |
| | | font-size: 26rpx; |
| | | text-align: center; |
| | | padding: 34rpx 0; |
| | | line-height: 1; |
| | | color: $tn-content-color; |
| | | } |
| | | |
| | | &__item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | padding: 34rpx 0; |
| | | |
| | | &__subtext { |
| | | font-size: 24rpx; |
| | | color: $tn-content-color; |
| | | margin-top: 20rpx; |
| | | } |
| | | } |
| | | |
| | | &__cancel { |
| | | color: $tn-font-color; |
| | | |
| | | &--gab { |
| | | height: 12rpx; |
| | | background-color: #eaeaec; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-avatar-group-class tn-avatar-group"> |
| | | <view v-for="(item, index) in lists" :key="index" class="tn-avatar-group__item" :style="[itemStyle(index)]"> |
| | | <tn-avatar |
| | | :src="item.src || ''" |
| | | :text="item.text || ''" |
| | | :icon="item.icon || ''" |
| | | :size="size" |
| | | :shape="shape" |
| | | :imgMode="imgMode" |
| | | :border="true" |
| | | backgroundColor="rgba(255, 255, 255, 0.4)" |
| | | :borderSize="4" |
| | | ></tn-avatar> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-avatar-group', |
| | | props: { |
| | | // 头åå表 |
| | | lists: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // 头åç±»å |
| | | // square 带åè§æ£æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: 'circle' |
| | | }, |
| | | // å¤§å° |
| | | // sm å°å¤´å lg 大头å xl å 大头å |
| | | // å¦æä¸ºå
¶ä»å认为æ¯ç´æ¥è®¾ç½®å¤§å° |
| | | size: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | // å½è®¾ç½®ä¸ºæ¾ç¤ºå¤´åä¿¡æ¯æ¶ï¼ |
| | | // å¾ççè£åªæ¨¡å¼ |
| | | imgMode: { |
| | | type: String, |
| | | default: 'aspectFill' |
| | | }, |
| | | // 头åä¹é´ç鮿¡æ¯ä¾ |
| | | // 0.4 代表 40% |
| | | gap: { |
| | | type: Number, |
| | | default: 0.4 |
| | | } |
| | | }, |
| | | computed: { |
| | | itemStyle() { |
| | | return (index) => { |
| | | let style = {} |
| | | if (this._checkSizeIsInline()) { |
| | | switch(this.size) { |
| | | case 'sm': |
| | | style.marginLeft = index != 0 ? `${-48 * this.gap}rpx` : '' |
| | | break |
| | | case 'lg': |
| | | style.marginLeft = index != 0 ? `${-96 * this.gap}rpx` : '' |
| | | break |
| | | case 'xl': |
| | | style.marginLeft = index != 0 ? `${-128 * this.gap}rpx` : '' |
| | | break |
| | | } |
| | | } else { |
| | | const size = Number(this.size.replace(/(px|rpx)/g, '')) || 64 |
| | | style.marginLeft = index != 0 ? `-${size * this.gap}rpx` : '' |
| | | } |
| | | return style |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // æ£æ¥æ¯å¦ä½¿ç¨å
ç½®ç大å°è¿è¡è®¾ç½® |
| | | _checkSizeIsInline() { |
| | | if (/(xs|sm|md|lg|xl|xxl)/.test(this.size)) return true |
| | | else return false |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-avatar-group { |
| | | display: flex; |
| | | flex-direction: row; |
| | | |
| | | &__item { |
| | | position: relative; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-avatar-class tn-avatar" |
| | | :class="[backgroundColorClass,avatarClass]" |
| | | :style="[avatarStyle]" |
| | | @tap="click" |
| | | > |
| | | <image |
| | | v-if="showImg" |
| | | class="tn-avatar__img" |
| | | :class="[imgClass]" |
| | | :src="src" |
| | | :mode="imgMode || 'aspectFill'" |
| | | @error="loadImageError" |
| | | ></image> |
| | | <view v-else class="tn-avatar__text" > |
| | | <view v-if="text">{{ text }}</view> |
| | | <view v-else :class="[`tn-icon-${icon}`]"></view> |
| | | </view> |
| | | |
| | | <!-- è§æ --> |
| | | <tn-badge |
| | | v-if="badge && (badgeIcon || badgeText)" |
| | | :radius="badgeSize" |
| | | :backgroundColor="badgeBgColor" |
| | | :fontColor="badgeColor" |
| | | :fontSize="badgeSize - 8" |
| | | :absolute="true" |
| | | :top="badgePosition[0]" |
| | | :right="badgePosition[1]" |
| | | > |
| | | <view v-if="badgeIcon && badgeText === ''"> |
| | | <view :class="[`tn-icon-${badgeIcon}`]"></view> |
| | | </view> |
| | | <view v-else> |
| | | {{ badgeText }} |
| | | </view> |
| | | </tn-badge> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [componentsColorMixin], |
| | | name: 'tn-avatar', |
| | | props: { |
| | | // åºå· |
| | | index: { |
| | | type: [Number, String], |
| | | default: 0 |
| | | }, |
| | | // 头åç±»å |
| | | // square 带åè§æ£æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: 'circle' |
| | | }, |
| | | // å¤§å° |
| | | // sm å°å¤´å lg 大头å xl å 大头å |
| | | // å¦æä¸ºå
¶ä»å认为æ¯ç´æ¥è®¾ç½®å¤§å° |
| | | size: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé´å½± |
| | | shadow: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¾¹æ¡ |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è¾¹æ¡é¢è² |
| | | borderColor: { |
| | | type: String, |
| | | default: 'rgba(0, 0, 0, 0.1)' |
| | | }, |
| | | // è¾¹æ¡å¤§å°, rpx |
| | | borderSize: { |
| | | type: Number, |
| | | default: 2 |
| | | }, |
| | | // 头åè·¯å¾ |
| | | src: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æå |
| | | text: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 徿 |
| | | icon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å½è®¾ç½®ä¸ºæ¾ç¤ºå¤´åä¿¡æ¯æ¶ï¼ |
| | | // å¾ççè£åªæ¨¡å¼ |
| | | imgMode: { |
| | | type: String, |
| | | default: 'aspectFill' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè§æ |
| | | badge: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 设置æ¾ç¤ºè§æ åï¼è§æ å¤§å° |
| | | badgeSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // è§æ èæ¯é¢è² |
| | | badgeBgColor: { |
| | | type: String, |
| | | default: '#AAAAAA' |
| | | }, |
| | | // è§æ åä½é¢è² |
| | | badgeColor: { |
| | | type: String, |
| | | default: '#FFFFFF' |
| | | }, |
| | | // è§æ 徿 |
| | | badgeIcon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // è§æ æåï¼ä¼å
级æ¯iconé« |
| | | badgeText: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // è§æ åæ |
| | | // [top, right] |
| | | badgePosition: { |
| | | type: Array, |
| | | default() { |
| | | return [0, 0] |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // å¾çæ¾ç¤ºæ¯å¦åçé误 |
| | | imgLoadError: false |
| | | } |
| | | }, |
| | | computed: { |
| | | showImg() { |
| | | // å¦æè®¾ç½®äºå¾çå°åï¼å为æ¾ç¤ºå¾çï¼å¦å为æ¾ç¤ºææ¬ |
| | | return this.text === '' && this.icon === '' |
| | | }, |
| | | avatarClass() { |
| | | let clazz = '' |
| | | clazz += ` tn-avatar--${this.shape}` |
| | | |
| | | if (this._checkSizeIsInline()) { |
| | | clazz += ` tn-avatar--${this.size}` |
| | | } |
| | | |
| | | if (this.shadow) { |
| | | clazz += ' tn-avatar--shadow' |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | avatarStyle() { |
| | | let style = {} |
| | | |
| | | if (this.backgroundColorStyle) { |
| | | style.background = this.backgroundColorStyle |
| | | } else if (this.shadow && this.showImg) { |
| | | style.backgroundImage = `url(${this.src})` |
| | | } |
| | | |
| | | if (this.border) { |
| | | style.border = `${this.borderSize}rpx solid ${this.borderColor}` |
| | | } |
| | | |
| | | if (!this._checkSizeIsInline()) { |
| | | style.width = this.size |
| | | style.height = this.size |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | imgClass() { |
| | | let clazz = '' |
| | | clazz += ` tn-avatar__img--${this.shape}` |
| | | |
| | | return clazz |
| | | } |
| | | }, |
| | | methods: { |
| | | // å è½½å¾ç失败 |
| | | loadImageError() { |
| | | this.imgLoadError = true |
| | | }, |
| | | // ç¹å»äºä»¶ |
| | | click() { |
| | | this.$emit("click", this.index) |
| | | }, |
| | | |
| | | // æ£æ¥æ¯å¦ä½¿ç¨å
ç½®ç大å°è¿è¡è®¾ç½® |
| | | _checkSizeIsInline() { |
| | | if (/^(xs|sm|md|lg|xl|xxl)$/.test(this.size)) return true |
| | | else return false |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-avatar { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | margin: 0; |
| | | padding: 0; |
| | | text-align: center; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background-color: $tn-font-holder-color; |
| | | // color: #FFFFFF; |
| | | white-space: nowrap; |
| | | position: relative; |
| | | width: 64rpx; |
| | | height: 64rpx; |
| | | z-index: 1; |
| | | |
| | | &--sm { |
| | | width: 48rpx; |
| | | height: 48rpx; |
| | | } |
| | | &--lg { |
| | | width: 96rpx; |
| | | height: 96rpx; |
| | | } |
| | | &--xl { |
| | | width: 128rpx; |
| | | height: 128rpx; |
| | | } |
| | | |
| | | &--square { |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | &--circle { |
| | | border-radius: 5000rpx; |
| | | } |
| | | |
| | | &--shadow { |
| | | position: relative; |
| | | |
| | | &::after { |
| | | content: " "; |
| | | display: block; |
| | | background: inherit; |
| | | filter: blur(10rpx); |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | top: 10rpx; |
| | | left: 10rpx; |
| | | z-index: -1; |
| | | opacity: 0.4; |
| | | transform-origin: 0 0; |
| | | border-radius: inherit; |
| | | transform: scale(1, 1); |
| | | } |
| | | } |
| | | |
| | | &__img { |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | &--square { |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | &--circle { |
| | | border-radius: 5000rpx; |
| | | } |
| | | } |
| | | |
| | | &__text { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-badge-class tn-badge" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | fontColorClass, |
| | | badgeClass |
| | | ]" |
| | | :style="[badgeStyle]" |
| | | @click="handleClick" |
| | | > |
| | | <slot v-if="!dot"></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [componentsColorMixin], |
| | | name: 'tn-badge', |
| | | props: { |
| | | // åºå· |
| | | index: { |
| | | type: [Number, String], |
| | | default: '0' |
| | | }, |
| | | // å¾½ç« çå¤§å° rpx |
| | | radius: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
è¾¹è· |
| | | padding: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å¤è¾¹è· |
| | | margin: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦ä¸ºä¸ä¸ªç¹ |
| | | dot: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦ä½¿ç¨ç»å¯¹å®ä½ |
| | | absolute: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // top |
| | | top: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // right |
| | | right: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // å±
ä¸ å¯¹é½å³ä¸è§ |
| | | translateCenter: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | computed: { |
| | | badgeClass() { |
| | | let clazz = '' |
| | | if (this.dot) { |
| | | clazz += ' tn-badge--dot' |
| | | } |
| | | if (this.absolute) { |
| | | clazz += ' tn-badge--absolute' |
| | | |
| | | if (this.translateCenter) { |
| | | clazz += ' tn-badge--center-position' |
| | | } |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | badgeStyle() { |
| | | let style = {} |
| | | |
| | | if (this.radius !== 0) { |
| | | style.width = this.radius + 'rpx' |
| | | style.height = this.radius + 'rpx' |
| | | style.lineHeight = this.radius + 'rpx' |
| | | |
| | | // style.borderRadius = (this.radius * 8) + 'rpx' |
| | | } |
| | | |
| | | if (this.padding) { |
| | | style.padding = this.padding |
| | | } |
| | | if (this.margin) { |
| | | style.margin = this.margin |
| | | } |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | if (this.fontSize) { |
| | | style.fontSize = this.fontSize + this.fontUnit |
| | | } |
| | | |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | |
| | | if (this.top) { |
| | | style.top = this.$t.string.getLengthUnitValue(this.top) |
| | | } |
| | | if (this.right) { |
| | | style.right = this.$t.string.getLengthUnitValue(this.right) |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çç¹å»äºä»¶ |
| | | handleClick() { |
| | | this.$emit('click', { |
| | | index: Number(this.index) |
| | | }) |
| | | this.$emit('tap', { |
| | | index: Number(this.index) |
| | | }) |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-badge { |
| | | width: auto; |
| | | height: auto; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 10; |
| | | font-size: 20rpx; |
| | | background-color: #FFFFFF; |
| | | // color: #FFFFFF; |
| | | border-radius: 100rpx; |
| | | padding: 4rpx 8rpx; |
| | | line-height: initial; |
| | | |
| | | &--dot { |
| | | width: 8rpx; |
| | | height: 8rpx; |
| | | border-radius: 50%; |
| | | padding: 0; |
| | | } |
| | | &--absolute { |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | } |
| | | &--center-position { |
| | | transform: translate(50%, -50%); |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <button |
| | | class="tn-btn-class tn-btn" |
| | | :class="[ |
| | | buttonClass, |
| | | backgroundColorClass, |
| | | fontColorClass |
| | | ]" |
| | | :style="[buttonStyle]" |
| | | hover-class="tn-hover" |
| | | :loading="loading" |
| | | :disabled="disabled" |
| | | :form-type="formType" |
| | | :open-type="openType" |
| | | @getuserinfo="handleGetUserInfo" |
| | | @getphonenumber="handleGetPhoneNumber" |
| | | @contact="handleContact" |
| | | @error="handleError" |
| | | @tap="handleClick" |
| | | > |
| | | <slot></slot> |
| | | </button> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [componentsColorMixin], |
| | | name: "tn-button", |
| | | // è§£å³å微信å°ç¨åºç§ï¼èªå®ä¹æé®æ æ³è§¦åbindsubmit |
| | | behaviors: ['wx://form-field-button'], |
| | | props: { |
| | | // æé®ç´¢å¼ï¼ç¨äºåºåå¤ä¸ªæé® |
| | | index: { |
| | | type: [Number, String], |
| | | default: 0 |
| | | }, |
| | | // æé®å½¢ç¶ default é»è®¤ round åè§ icon 徿 æé® |
| | | shape: { |
| | | type: String, |
| | | default: 'default' |
| | | }, |
| | | // æ¯å¦å é´å½± |
| | | shadow: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 宽度 rpxæ% |
| | | width: { |
| | | type: String, |
| | | default: 'auto' |
| | | }, |
| | | // é«åº¦ rpxæ% |
| | | height: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æé®ç尺寸 sm lg |
| | | size: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å使¯å¦å ç² |
| | | fontBold: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | padding: { |
| | | type: String, |
| | | default: '0 30rpx' |
| | | }, |
| | | // å¤è¾¹è· ä¸cssçmarginåæ°ç¨æ³ç¸å |
| | | margin: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦é空 |
| | | plain: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å½plain=trueæ¶ï¼æ¯å¦æ¾ç¤ºè¾¹æ¡ |
| | | border: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å½plain=trueæ¶ï¼æ¯å¦å ç²æ¾ç¤ºè¾¹æ¡ |
| | | borderBold: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå è½½å¾æ |
| | | loading: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 触åform表åçäºä»¶ç±»å |
| | | formType: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 弿¾è½å |
| | | openType: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦é»æ¢éå¤ç¹å»(é»è®¤é´éæ¯200ms) |
| | | blockRepeatClick: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // æ ¹æ®ä¸åç忰卿çæclass |
| | | buttonClass() { |
| | | let clazz = '' |
| | | // æé®å½¢ç¶ |
| | | switch (this.shape) { |
| | | case 'icon': |
| | | case 'round': |
| | | clazz += ' tn-round' |
| | | break |
| | | } |
| | | |
| | | // é´å½± |
| | | if (this.shadow) { |
| | | if (this.backgroundColorClass !== '' && this.backgroundColorClass.indexOf('tn-bg') != -1) { |
| | | const color = this.backgroundColor.slice(this.backgroundColor.lastIndexOf('-') + 1) |
| | | clazz += ` tn-shadow-${color}` |
| | | } else { |
| | | clazz += ' tn-shadow-blur' |
| | | } |
| | | } |
| | | |
| | | // åä½å ç² |
| | | if (this.fontBold) { |
| | | clazz += ' tn-text-bold' |
| | | } |
| | | |
| | | // 设置为é空并ä¸è®¾ç½®éç©ºä¾¿å¯æè¿è¡è®¾ç½® |
| | | if (this.plain) { |
| | | clazz += ' tn-btn--plain' |
| | | if (this.border) { |
| | | clazz += ' tn-border-solid' |
| | | if (this.borderBold) { |
| | | clazz += ' tn-bold-border' |
| | | } |
| | | if (this.backgroundColor !== '' && this.backgroundColor.includes('tn-bg')) { |
| | | const color = this.backgroundColor.slice(this.backgroundColor.lastIndexOf('-') + 1) |
| | | clazz += ` tn-border-${color}` |
| | | } |
| | | } |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | // æé®çæ ·å¼ |
| | | buttonStyle() { |
| | | let style = {} |
| | | switch(this.size) { |
| | | case 'sm': |
| | | style.padding = '0 20rpx' |
| | | style.fontSize = '22rpx' |
| | | style.height = this.height || '48rpx' |
| | | break |
| | | case 'lg': |
| | | style.padding = '0 40rpx' |
| | | style.fontSize = '32rpx' |
| | | style.height = this.height || '80rpx' |
| | | break |
| | | default : |
| | | style.padding = '0 30rpx' |
| | | style.fontSize = '28rpx' |
| | | style.height = this.height || '64rpx' |
| | | } |
| | | |
| | | // æ¯å¦æå¨è®¾ç½®äºå
è¾¹è· |
| | | if (this.padding) { |
| | | style.padding = this.padding |
| | | } |
| | | |
| | | // æ¯å¦æå¨è®¾ç½®å¤è¾¹è· |
| | | if (this.margin) { |
| | | style.margin = this.margin |
| | | } |
| | | |
| | | // æ¯å¦æå¨è®¾ç½®äºåä½å¤§å° |
| | | if (this.fontSize) { |
| | | style.fontSize = this.fontSize + this.fontUnit |
| | | } |
| | | style.width = this.shape === 'icon' ? style.height : this.width |
| | | style.padding = this.shape === 'icon' ? '0' : style.padding |
| | | |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | |
| | | if (!this.backgroundColorClass) { |
| | | if (this.plain) { |
| | | style.borderColor = this.backgroundColorStyle || '#080808' |
| | | } else { |
| | | style.backgroundColor = this.backgroundColorStyle || '#FFFFFF' |
| | | } |
| | | } |
| | | |
| | | // 设置é´å½± |
| | | if (this.shadow && !this.backgroundColorClass) { |
| | | if (this.backgroundColorStyle.indexOf('#') != -1) { |
| | | style.boxShadow = `6rpx 6rpx 8rpx ${(this.backgroundColorStyle || '#000000')}10` |
| | | } else if (this.backgroundColorStyle.indexOf('rgb') != -1 || this.backgroundColorStyle.indexOf('rgba') != -1 || !this.backgroundColorStyle) { |
| | | style.boxShadow = `6rpx 6rpx 8rpx ${(this.backgroundColorStyle || 'rgba(0, 0, 0, 0.1)')}` |
| | | } |
| | | |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | // 䏿¬¡ç¹å»çæ¶é´ |
| | | clickTime: 0, |
| | | // 两次ç¹å»é²æçé´éæ¶é´ |
| | | clickIntervalTime: 200 |
| | | } |
| | | }, |
| | | methods: { |
| | | // æé®ç¹å»äºä»¶ |
| | | handleClick() { |
| | | if (this.disabled) { |
| | | return |
| | | } |
| | | if (this.blockRepeatClick) { |
| | | const nowTime = new Date().getTime() |
| | | if (nowTime - this.clickTime <= this.clickIntervalTime) { |
| | | return |
| | | } |
| | | this.clickTime = nowTime |
| | | setTimeout(() => { |
| | | this.clickTime = 0 |
| | | }, this.clickIntervalTime) |
| | | } |
| | | this.$emit('click', { |
| | | index: Number(this.index) |
| | | }) |
| | | // å
¼å®¹tapäºä»¶ |
| | | this.$emit('tap', { |
| | | index: Number(this.index) |
| | | }) |
| | | }, |
| | | handleGetUserInfo({ detail = {} } = {}) { |
| | | this.$emit('getuserinfo', detail); |
| | | }, |
| | | handleContact({ detail = {} } = {}) { |
| | | this.$emit('contact', detail); |
| | | }, |
| | | handleGetPhoneNumber({ detail = {} } = {}) { |
| | | this.$emit('getphonenumber', detail); |
| | | }, |
| | | handleError({ detail = {} } = {}) { |
| | | this.$emit('error', detail); |
| | | }, |
| | | |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-btn { |
| | | position: relative; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-sizing: border-box; |
| | | line-height: 1; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | overflow: visible; |
| | | transform: translate(0rpx, 0rpx); |
| | | // background-color: $tn-mai |
| | | border-radius: 12rpx; |
| | | // color: $tn-font-color; |
| | | margin: 0; |
| | | |
| | | &--plain { |
| | | background-color: transparent !important; |
| | | background-image: none; |
| | | |
| | | &.tn-round { |
| | | border-radius: 1000rpx !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <tn-popup |
| | | v-model="value" |
| | | mode="bottom" |
| | | :popup="false" |
| | | length="auto" |
| | | :borderRadius="borderRadius" |
| | | :safeAreaInsetBottom="safeAreaInsetBottom" |
| | | :maskCloseable="maskCloseable" |
| | | :closeBtn="closeBtn" |
| | | :zIndex="elIndex" |
| | | @close="close" |
| | | > |
| | | <view class="tn-calendar-class tn-calendar"> |
| | | <!-- å¤´é¨ --> |
| | | <view class="tn-calendar__header"> |
| | | <view v-if="!$slots.tooltip || !$slots.$tooltip" class="tn-calendar__header__text"> |
| | | {{ toolTips }} |
| | | </view> |
| | | <view v-else> |
| | | <slot name="tooltip"></slot> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä½æç¤ºä¿¡æ¯ --> |
| | | <view class="tn-calendar__action"> |
| | | <view v-if="changeYear" class="tn-calendar__action__icon" :style="{backgroundColor: yearArrowColor}" @tap.stop="changeYearHandler(false)"> |
| | | <view><text class="tn-icon-left"></text></view> |
| | | </view> |
| | | <view v-if="changeMonth" class="tn-calendar__action__icon" :style="{backgroundColor: monthArrowColor}" @tap.stop="changeMonthHandler(false)"> |
| | | <view><text class="tn-icon-left"></text></view> |
| | | </view> |
| | | <view class="tn-calendar__action__text">{{ dateTitle }}</view> |
| | | <view v-if="changeMonth" class="tn-calendar__action__icon" :style="{backgroundColor: monthArrowColor}" @tap.stop="changeMonthHandler(true)"> |
| | | <view><text class="tn-icon-right"></text></view> |
| | | </view> |
| | | <view v-if="changeYear" class="tn-calendar__action__icon" :style="{backgroundColor: yearArrowColor}" @tap.stop="changeYearHandler(true)"> |
| | | <view><text class="tn-icon-right"></text></view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- ææä¸ææ è¯ --> |
| | | <view class="tn-calendar__week-day-zh"> |
| | | <view v-for="(item,index) in weekDayZh" :key="index" class="tn-calendar__week-day-zh__text">{{ item }}</view> |
| | | </view> |
| | | |
| | | <!-- æ¥åä¸»ä½ --> |
| | | <view class="tn-calendar__content"> |
| | | <!-- å置空ç½é¨å --> |
| | | <block v-for="(item, index) in weekdayArr" :key="index"> |
| | | <view class="tn-calendar__content__item"></view> |
| | | </block> |
| | | <view |
| | | v-for="(item, index) in daysArr" |
| | | :key="index" |
| | | class="tn-calendar__content__item" |
| | | :class="{ |
| | | 'tn-hover': disabledChoose(year, month, index + 1), |
| | | 'tn-calendar__content--start-date': (mode === 'range' && startDate == `${year}-${month}-${index+1}`) || mode === 'date', |
| | | 'tn-calendar__content--end-date': (mode === 'range' && endDate == `${year}-${month}-${index+1}`) || mode === 'date' |
| | | }" |
| | | :style="{ |
| | | backgroundColor: colorValue(index, 'bg') |
| | | }" |
| | | @tap.stop="dateClick(index)" |
| | | > |
| | | <view class="tn-calendar__content__item__text" :style="{color: colorValue(index, 'text')}"> |
| | | <view>{{ item.day }}</view> |
| | | </view> |
| | | <view class="tn-calendar__content__item__tips" :style="{color: item.color}"> |
| | | {{ item.bottomInfo }} |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="tn-calendar__content__month--bg">{{ month }}</view> |
| | | </view> |
| | | |
| | | <!-- åºé¨ --> |
| | | <view class="tn-calendar__bottom"> |
| | | <view class="tn-calendar__bottom__choose"> |
| | | <text>{{ mode === 'date' ? activeDate : startDate }}</text> |
| | | <text v-if="endDate">è³{{ endDate }}</text> |
| | | </view> |
| | | <view class="tn-calendar__bottom__btn" :style="{backgroundColor: btnColor}" @click="handleBtnClick(false)"> |
| | | <view class="tn-calendar__bottom__btn--text">ç¡®å®</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </tn-popup> |
| | | </template> |
| | | |
| | | <script> |
| | | import Calendar from '../../libs/utils/calendar.js' |
| | | |
| | | export default { |
| | | name: 'tn-calendar', |
| | | props: { |
| | | // ååç»å®æ§å¶ç»ä»¶å¼¹åºä¸æ¶èµ· |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¨¡å¼ |
| | | // date -> 忥æ range -> æ¥æèå´ |
| | | mode: { |
| | | type: String, |
| | | default: 'date' |
| | | }, |
| | | // æ¯å¦å
è®¸åæ¢å¹´ä»½ |
| | | changeYear: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦å
è®¸åæ¢æä»½ |
| | | changeMonth: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å¯åæ¢çæå¤§å¹´ä»½ |
| | | maxYear: { |
| | | type: [Number, String], |
| | | default: 2100 |
| | | }, |
| | | // å¯åæ¢çæå°å¹´ä»½ |
| | | minYear: { |
| | | type: [Number, String], |
| | | default: 1970 |
| | | }, |
| | | // æå°æ¥æ(ä¸å¨èå´è¢«ä¸å
è®¸éæ©) |
| | | minDate: { |
| | | type: String, |
| | | default: '1970-01-01' |
| | | }, |
| | | // æå¤§æ¥æï¼å¦æä¸ºç©ºåé»è®¤ä¸ºä»å¤© |
| | | maxDate: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 忢æä»½æé®çé¢è² |
| | | monthArrowColor: { |
| | | type: String, |
| | | default: '#AAAAAA' |
| | | }, |
| | | // 忢年份æé®çé¢è² |
| | | yearArrowColor: { |
| | | type: String, |
| | | default: '#C8C8C8' |
| | | }, |
| | | // é»è®¤åä½é¢è² |
| | | color: { |
| | | type: String, |
| | | default: '#080808' |
| | | }, |
| | | // éä¸|èµ·å§ç»ææ¥æèæ¯é¢è² |
| | | activeBgColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // éä¸|èµ·å§ç»ææ¥ææåé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#FFFFFF' |
| | | }, |
| | | // èå´æ¥æå
çèæ¯é¢è² |
| | | rangeBgColor: { |
| | | type: String, |
| | | default: '#E6E6E655' |
| | | }, |
| | | // èå´æ¥æå
çæåé¢è² |
| | | rangeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // èµ·å§æ¥ææ¾ç¤ºçæåï¼mode=rangeæ¶çæ |
| | | startText: { |
| | | type: String, |
| | | default: 'å¼å§' |
| | | }, |
| | | // ç»ææ¥ææ¾ç¤ºçæåï¼mode=rangeæ¶çæ |
| | | endText: { |
| | | type: String, |
| | | default: 'ç»æ' |
| | | }, |
| | | // æé®èæ¯é¢è² |
| | | btnColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // ååæåçé¢è² |
| | | lunarColor: { |
| | | type: String, |
| | | default: '#AAAAAA' |
| | | }, |
| | | // é䏿¥ææ¯å¦æé䏿æ |
| | | isActiveCurrent: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // åæ¢å¹´ææ¯å¦è§¦åäºä»¶ï¼mode=dateæ¶çæ |
| | | isChange: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºåå |
| | | showLunar: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é¡¶é¨æç¤ºæå |
| | | toolTips: { |
| | | type: String, |
| | | default: 'è¯·éæ©æ¥æ' |
| | | }, |
| | | // æ¾ç¤ºåè§çå¤§å° |
| | | borderRadius: { |
| | | type: Number, |
| | | default: 8 |
| | | }, |
| | | // æ¯å¦å¼å¯åºé¨å®å
¨åºéé
ï¼å¼å¯çè¯ï¼ä¼å¨iPhoneXæºååºé¨æ·»å ä¸å®çå
è¾¹è· |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¯ä»¥éè¿ç¹å»é®ç½©è¿è¡å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // zIndex |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå
³éæé® |
| | | closeBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | }, |
| | | computed: { |
| | | dateChange() { |
| | | return `${this.mode}-${this.minDate}-${this.maxDate}` |
| | | }, |
| | | elIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.popup |
| | | }, |
| | | colorValue() { |
| | | return (index, type) => { |
| | | let color = type === 'bg' ? '' : this.color |
| | | let day = index + 1 |
| | | let date = `${this.year}-${this.month}-${day}` |
| | | let timestamp = new Date(date.replace(/\-/g,'/')).getTime() |
| | | let start = this.startDate.replace(/\-/g,'/') |
| | | let end = this.endDate.replace(/\-/g,'/') |
| | | if ((this.mode === 'date' && this.isActiveCurrent && this.activeDate == date) || this.startDate == date || this.endDate == date) { |
| | | color = type === 'bg' ? this.activeBgColor : this.activeColor |
| | | } else if (this.endDate && timestamp > new Date(start).getTime() && timestamp < new Date(end).getTime()) { |
| | | color = type === 'bg' ? this.rangeBgColor : this.rangeColor |
| | | } |
| | | return color |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ææå ï¼1-7 |
| | | weekday: 1, |
| | | weekdayArr: [], |
| | | // ææå¯¹åºç䏿 |
| | | weekDayZh: ['æ¥','ä¸','äº','ä¸','å','äº','å
'], |
| | | // å½åææå¤å°å¤© |
| | | days: 0, |
| | | daysArr: [], |
| | | year: 2021, |
| | | month: 0, |
| | | day: 0, |
| | | startYear: 0, |
| | | startMonth: 0, |
| | | startDay: 0, |
| | | endYear: 0, |
| | | endMonth: 0, |
| | | endDay: 0, |
| | | today: '', |
| | | activeDate: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | min: null, |
| | | max: null, |
| | | // æ¥ææ é¢ |
| | | dateTitle: '', |
| | | // æ è®°æ¯å¦å·²ç»éæ©äºå¼å§æ¥æ |
| | | chooseStart: false |
| | | } |
| | | }, |
| | | watch: { |
| | | dateChange() { |
| | | this.init() |
| | | } |
| | | }, |
| | | created() { |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | // åå§å |
| | | init() { |
| | | let now = new Date() |
| | | this.year = now.getFullYear() |
| | | this.month = now.getMonth() + 1 |
| | | this.day = now.getDate() |
| | | this.today = `${this.year}-${this.month}-${this.day}` |
| | | this.activeDate = this.today |
| | | this.min = this.initDate(this.minDate) |
| | | this.max = this.initDate(this.maxDate || this.today) |
| | | this.startDate = '' |
| | | this.startYear = 0 |
| | | this.startMonth = 0 |
| | | this.startDay = 0 |
| | | this.endDate = '' |
| | | this.endYear = 0 |
| | | this.endMonth = 0 |
| | | this.endDay = 0 |
| | | this.chooseStart = false |
| | | this.changeData() |
| | | }, |
| | | // 忢æä»½ |
| | | changeMonthHandler(add) { |
| | | if (add) { |
| | | let month = this.month + 1 |
| | | let year = month > 12 ? this.year + 1 : this.year |
| | | if (!this.checkRange(year)) { |
| | | this.month = month > 12 ? 1 : month |
| | | this.year = year |
| | | this.changeData() |
| | | } |
| | | } else { |
| | | let month = this.month - 1 |
| | | let year = month < 1 ? this.year - 1 : this.year |
| | | if (!this.checkRange(year)) { |
| | | this.month = month < 1 ? 12 : month |
| | | this.year = year |
| | | this.changeData() |
| | | } |
| | | } |
| | | }, |
| | | // 忢年份 |
| | | changeYearHandler(add) { |
| | | let year = add ? this.year + 1 : this.year - 1 |
| | | if (!this.checkRange(year)) { |
| | | this.year = year |
| | | this.changeData() |
| | | } |
| | | }, |
| | | // æ¥æç¹å»äºä»¶ |
| | | dateClick(day) { |
| | | day += 1 |
| | | if (!this.disabledChoose(this.year, this.month, day)) { |
| | | this.day = day |
| | | let date = `${this.year}-${this.month}-${day}` |
| | | if (this.mode === 'date') { |
| | | this.activeDate = date |
| | | } else { |
| | | let startTimeCompare = new Date(date.replace(/\-/g,'/')).getTime() < new Date(this.startDate.replace(/\-/g,'/')).getTime() |
| | | if (!this.chooseStart || startTimeCompare) { |
| | | this.startDate = date |
| | | this.startYear = this.year |
| | | this.startMonth = this.month |
| | | this.startDay = this.day |
| | | this.endYear = 0 |
| | | this.endMonth = 0 |
| | | this.endDay = 0 |
| | | this.endDate = '' |
| | | this.activeDate = '' |
| | | this.chooseStart = true |
| | | } else { |
| | | this.endDate = date |
| | | this.endYear = this.year |
| | | this.endMonth = this.month |
| | | this.endDay = this.day |
| | | this.chooseStart = false |
| | | } |
| | | } |
| | | this.daysArr = this.handleDaysArr() |
| | | } |
| | | }, |
| | | // ä¿®æ¹æ¥ææ°æ® |
| | | changeData() { |
| | | this.days = this.getMonthDay(this.year, this.month) |
| | | this.daysArr = this.handleDaysArr() |
| | | this.weekday = this.getMonthFirstWeekDay(this.year, this.month) |
| | | this.weekdayArr = this.generateArray(1, this.weekday) |
| | | this.dateTitle = `${this.year}å¹´${this.month}æ` |
| | | if (this.isChange && this.mode === 'date') { |
| | | this.handleBtnClick(true) |
| | | } |
| | | }, |
| | | // å¤çæé®ç¹å» |
| | | handleBtnClick(show) { |
| | | if (!show) { |
| | | this.close() |
| | | } |
| | | if (this.mode === 'date') { |
| | | let arr = this.activeDate.split('-') |
| | | let year = this.isChange ? this.year : Number(arr[0]) |
| | | let month = this.isChange ? this.month : Number(arr[1]) |
| | | let day = this.isChange ? this.day : Number(arr[2]) |
| | | let days = this.getMonthDay(year, month) |
| | | let result = `${year}-${this.formatNumber(month)}-${this.formatNumber(day)}` |
| | | let weekText = this.getWeekText(result) |
| | | let isToday = false |
| | | if (`${year}-${month}-${day}` === this.today) { |
| | | isToday = true |
| | | } |
| | | this.$emit('change', { |
| | | year, |
| | | month, |
| | | day, |
| | | days, |
| | | week: weekText, |
| | | isToday, |
| | | date: result, |
| | | // æ¯å¦ä¸ºåæ¢å¹´ææä½ |
| | | switch: show |
| | | }) |
| | | } else { |
| | | if (!this.startDate || !this.endDate) return |
| | | |
| | | let startMonth = this.formatNumber(this.startMonth) |
| | | let startDay = this.formatNumber(this.startDay) |
| | | let startDate = `${this.startYear}-${startMonth}-${startDay}` |
| | | let startWeek = this.getWeekText(startDate) |
| | | |
| | | let endMonth = this.formatNumber(this.endMonth) |
| | | let endDay = this.formatNumber(this.endDay) |
| | | let endDate = `${this.endYear}-${endMonth}-${endDay}` |
| | | let endWeek = this.getWeekText(endDate) |
| | | |
| | | this.$emit('change', { |
| | | startYear: this.startYear, |
| | | startMonth: this.startMonth, |
| | | startDay: this.startDay, |
| | | startDate, |
| | | startWeek, |
| | | endYear: this.endYear, |
| | | endMonth: this.endMonth, |
| | | endDay: this.endDay, |
| | | endDate, |
| | | endWeek |
| | | }) |
| | | } |
| | | }, |
| | | // 夿æ¯å¦å
è®¸éæ© |
| | | disabledChoose(year, month, day) { |
| | | let flag = true |
| | | let date = `${year}/${month}/${day}` |
| | | let min = `${this.min.year}/${this.min.month}/${this.min.day}` |
| | | let max = `${this.max.year}/${this.max.month}/${this.max.day}` |
| | | let timestamp = new Date(date).getTime() |
| | | if (timestamp >= new Date(min).getTime() && timestamp <= new Date(max).getTime()) { |
| | | flag = false |
| | | } |
| | | return flag |
| | | }, |
| | | // æ£æ¥æ¯å¦å¨æ¥æèå´å
|
| | | checkRange(year) { |
| | | let overstep = false |
| | | if (year < this.minYear || year > this.maxYear) { |
| | | uni.showToast({ |
| | | title: 'æéæ¥æè¶
åºèå´', |
| | | icon: 'none' |
| | | }) |
| | | overstep = true |
| | | } |
| | | return overstep |
| | | }, |
| | | // å¤çæ¥æ |
| | | initDate(date) { |
| | | let fdate = date.split('-') |
| | | return { |
| | | year: Number(fdate[0] || 1970), |
| | | month: Number(fdate[1] || 1), |
| | | day: Number(fdate[2] || 1) |
| | | } |
| | | }, |
| | | // å¤çæ¥ææ°ç» |
| | | handleDaysArr() { |
| | | let days = this.generateArray(1, this.days) |
| | | let daysArr = days.map((item) => { |
| | | let bottomInfo = this.showLunar ? Calendar.solar2lunar(this.year, this.month, item).IDayCn : '' |
| | | let color = this.showLunar ? this.lunarColor : this.activeColor |
| | | if ( |
| | | (this.mode === 'date' && this.day == item) || |
| | | (this.mode === 'range' && (this.startDay == item || this.endDay == item)) |
| | | ) { |
| | | color = this.activeColor |
| | | } |
| | | if (this.mode === 'range') { |
| | | if (this.startDay == item && this.startDay != this.endDay) { |
| | | bottomInfo = this.startText |
| | | } |
| | | if (this.endDay == item) { |
| | | bottomInfo = this.endText |
| | | } |
| | | } |
| | | |
| | | return { |
| | | day: item, |
| | | color: color, |
| | | bottomInfo: bottomInfo |
| | | } |
| | | }) |
| | | return daysArr |
| | | }, |
| | | // è·åå¯¹åºææå¤å°å¤© |
| | | getMonthDay(year, month) { |
| | | return new Date(year, month, 0).getDate() |
| | | }, |
| | | // è·åå¯¹åºæç第ä¸å¤©æ¶ææå |
| | | getMonthFirstWeekDay(year, month) { |
| | | return new Date(`${year}/${month}/01 00:00:00`).getDay() |
| | | }, |
| | | // è·åå¯¹åºææçææ¬ |
| | | getWeekText(date) { |
| | | date = new Date(`${date.replace(/\-/g, '/')} 00:00:00`) |
| | | let week = date.getDay() |
| | | return 'ææ' + this.weekDayZh[week] |
| | | }, |
| | | // çææ¥æå¤©æ°æ°ç» |
| | | generateArray(start, end) { |
| | | return Array.from(new Array(end + 1).keys()).slice(start) |
| | | }, |
| | | // æ ¼å¼åæ°å |
| | | formatNumber(num) { |
| | | return num < 10 ? '0' + num : num + '' |
| | | }, |
| | | // å
³éçªå£ |
| | | close() { |
| | | this.$emit('input', false) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-calendar { |
| | | color: $tn-font-color; |
| | | |
| | | &__header { |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | font-size: 30rpx; |
| | | background-color: #FFFFFF; |
| | | color: $tn-main-color; |
| | | |
| | | &__text { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: 30rpx; |
| | | padding: 0 60rpx; |
| | | } |
| | | } |
| | | |
| | | &__action { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 40rpx 0 40rpx 0; |
| | | |
| | | &__icon { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin: 0 16rpx; |
| | | width: 32rpx; |
| | | height: 32rpx; |
| | | font-size: 20rpx; |
| | | // line-height: 32rpx; |
| | | border-radius: 50%; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | &__text { |
| | | padding: 0 16rpx; |
| | | color: $tn-font-color; |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | &__week-day-zh { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 12rpx 0; |
| | | overflow: hidden; |
| | | box-shadow: 16rpx 6rpx 8rpx 0 #E6E6E6; |
| | | margin-bottom: 2rpx; |
| | | |
| | | &__text { |
| | | flex: 1; |
| | | text-align: center; |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | width: 100%; |
| | | padding: 12rpx 0; |
| | | box-sizing: border-box; |
| | | background-color: #F7F7F7; |
| | | position: relative; |
| | | |
| | | &__item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 14.2857%; |
| | | padding: 12rpx 0; |
| | | margin: 6rpx 0; |
| | | overflow: hidden; |
| | | position: relative; |
| | | z-index: 2; |
| | | // box-shadow: inset 0rpx 0rpx 22rpx 4rpx rgba(255,255,255, 0.52); |
| | | |
| | | &__text { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 80rpx; |
| | | font-size: 32rpx; |
| | | position: relative; |
| | | } |
| | | |
| | | &__tips { |
| | | position: absolute; |
| | | width: 100%; |
| | | line-height: 24rpx; |
| | | left: 0; |
| | | bottom: 8rpx; |
| | | text-align: center; |
| | | z-index: 2; |
| | | transform-origin: center center; |
| | | transform: scale(0.8); |
| | | } |
| | | } |
| | | |
| | | &--start-date { |
| | | border-top-left-radius: 8rpx; |
| | | border-bottom-left-radius: 8rpx; |
| | | } |
| | | |
| | | &--end-date { |
| | | border-top-right-radius: 8rpx; |
| | | border-bottom-right-radius: 8rpx; |
| | | } |
| | | |
| | | &__month { |
| | | &--bg { |
| | | position: absolute; |
| | | font-size: 200rpx; |
| | | line-height: 200rpx; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | color: $tn-font-holder-color; |
| | | z-index: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__bottom { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | background-color: #F7F7F7; |
| | | padding: 0 40rpx 30rpx; |
| | | box-sizing: border-box; |
| | | font-size: 24rpx; |
| | | color: $tn-font-sub-color; |
| | | |
| | | &__choose { |
| | | height: 50rpx; |
| | | } |
| | | |
| | | &__btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | height: 60rpx; |
| | | border-radius: 40rpx; |
| | | color: #FFFFFF; |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-car-keyboard-class tn-car-keyboard" @touchmove.stop.prevent="() => {}"> |
| | | <view class="tn-car-keyboard__grids"> |
| | | |
| | | <view |
| | | v-for="(data, index) in inputCarNumber ? endKeyBoardList : areaList" |
| | | :key="index" |
| | | class="tn-car-keyboard__grids__item" |
| | | > |
| | | <view |
| | | v-for="(sub_data, sub_index) in data" |
| | | :key="sub_index" |
| | | class="tn-car-keyboard__grids__btn" |
| | | :class="{'tn-car-keyboard__grids__btn--disabled': sub_data === 'I'}" |
| | | :hover-class="sub_data !== 'I' ? 'tn-car-keyboard--hover' : ''" |
| | | :hover-stay-time="100" |
| | | @tap="click(index, sub_index)" |
| | | > |
| | | {{ sub_data }} |
| | | </view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-car-keyboard__back" |
| | | hover-class="tn-hover-class" |
| | | :hover-stay-time="150" |
| | | @touchstart.stop="backspaceClick" |
| | | @touchend="clearTimer" |
| | | > |
| | | <view class="tn-icon-left-arrow tn-car-keyboard__back__icon"></view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-car-keyboard__change" |
| | | hover-class="tn-car-keyboard--hover" |
| | | :hover-stay-time="150" |
| | | @tap="changeMode" |
| | | > |
| | | <text class="tn-car-keyboard__mode--zh" :class="[`tn-car-keyboard__mode--${!inputCarNumber ? 'active' : 'inactive'}`]">ä¸</text> |
| | | / |
| | | <text class="tn-car-keyboard__mode--en" :class="[`tn-car-keyboard__mode--${inputCarNumber ? 'active' : 'inactive'}`]">è±</text> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-car-keyboard', |
| | | props: { |
| | | // æ¯å¦æä¹±é®çé¡ºåº |
| | | randomEnabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 忢ä¸è±æè¾å
¥ |
| | | switchEnMode: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | areaList() { |
| | | let data = [ |
| | | '京', |
| | | '沪', |
| | | '粤', |
| | | 'æ´¥', |
| | | 'å', |
| | | '豫', |
| | | 'äº', |
| | | 'è¾½', |
| | | 'é»', |
| | | 'æ¹', |
| | | 'ç', |
| | | 'é²', |
| | | 'è', |
| | | 'æµ', |
| | | 'èµ£', |
| | | 'é', |
| | | 'æ¡', |
| | | 'ç', |
| | | 'æ', |
| | | 'é', |
| | | 'è', |
| | | 'å', |
| | | 'é½', |
| | | 'è´µ', |
| | | 'æ¸', |
| | | 'å·', |
| | | 'é', |
| | | 'ç¼', |
| | | 'å®', |
| | | 'è', |
| | | '港', |
| | | 'æ¾³', |
| | | 'æ°', |
| | | '使', |
| | | 'å¦', |
| | | '临', |
| | | 'è¦' |
| | | ] |
| | | // æä¹±é¡ºåº |
| | | if (this.randomEnabled) data = this.$t.array.random(data) |
| | | // åå²äºç»´æ°ç» |
| | | let showData = [] |
| | | showData[0] = data.slice(0, 10) |
| | | showData[1] = data.slice(10, 20) |
| | | showData[2] = data.slice(20, 30) |
| | | showData[3] = data.slice(30, 37) |
| | | return showData |
| | | }, |
| | | endKeyBoardList() { |
| | | let data = [ |
| | | 1, |
| | | 2, |
| | | 3, |
| | | 4, |
| | | 5, |
| | | 6, |
| | | 7, |
| | | 8, |
| | | 9, |
| | | 0, |
| | | 'Q', |
| | | 'W', |
| | | 'E', |
| | | 'R', |
| | | 'T', |
| | | 'Y', |
| | | 'U', |
| | | 'I', |
| | | 'O', |
| | | 'P', |
| | | 'A', |
| | | 'S', |
| | | 'D', |
| | | 'F', |
| | | 'G', |
| | | 'H', |
| | | 'J', |
| | | 'K', |
| | | 'L', |
| | | 'Z', |
| | | 'X', |
| | | 'C', |
| | | 'V', |
| | | 'B', |
| | | 'N', |
| | | 'M' |
| | | ] |
| | | // æä¹±é¡ºåº |
| | | if (this.randomEnabled) data = this.$t.array.random(data) |
| | | // åå²äºç»´æ°ç» |
| | | let showData = [] |
| | | showData[0] = data.slice(0, 10) |
| | | showData[1] = data.slice(10, 20) |
| | | showData[2] = data.slice(20, 29) |
| | | showData[3] = data.slice(29, 36) |
| | | return showData |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ è®°æ¯å¦è¾å
¥è½¦çå·ç |
| | | inputCarNumber: false, |
| | | // é¿æå¤æ¬¡å é¤äºä»¶çå¬ |
| | | longPressDeleteTimer: null |
| | | } |
| | | }, |
| | | watch:{ |
| | | switchEnMode: { |
| | | handler(value) { |
| | | if (value) { |
| | | this.inputCarNumber = true |
| | | } else { |
| | | this.inputCarNumber = false |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | // ç¹å»é®çæé® |
| | | click(i, j) { |
| | | let value = '' |
| | | // æ ¹æ®ä¸å模å¼è·åä¸åæ°ç»çå¼ |
| | | if (this.inputCarNumber) value = this.endKeyBoardList[i][j] |
| | | else value = this.areaList[i][j] |
| | | |
| | | // 车çéä¸å
å«I |
| | | if (value === 'I') return |
| | | |
| | | this.$emit('change', value) |
| | | }, |
| | | // ä¿®æ¹è¾å
¥æ¨¡å¼ |
| | | // 䏿/è±æ |
| | | changeMode() { |
| | | this.inputCarNumber = !this.inputCarNumber |
| | | }, |
| | | // ç¹å»éæ ¼ |
| | | backspaceClick() { |
| | | this.$emit('backspace') |
| | | this.clearTimer() |
| | | this.longPressDeleteTimer = setInterval(() => { |
| | | this.$emit('backspace') |
| | | }, 250) |
| | | }, |
| | | // æ¸
ç©ºå®æ¶å¨ |
| | | clearTimer() { |
| | | if (this.longPressDeleteTimer) { |
| | | clearInterval(this.longPressDeleteTimer) |
| | | this.longPressDeleteTimer = null |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-car-keyboard { |
| | | position: relative; |
| | | padding: 24rpx 0; |
| | | background-color: #E6E6E6; |
| | | |
| | | &__grids { |
| | | |
| | | &__item { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | &__btn { |
| | | display: inline-flex; |
| | | justify-content: center; |
| | | flex: 0 0 64rpx; |
| | | width: 62rpx; |
| | | height: 80rpx; |
| | | font-size: 38rpx; |
| | | line-height: 80rpx; |
| | | font-weight: 500; |
| | | text-decoration: none; |
| | | text-align: center; |
| | | background-color: #FFFFFF; |
| | | margin: 8rpx 5rpx; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 0rpx $tn-box-shadow-color; |
| | | |
| | | &--disabled { |
| | | opacity: 0.6; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__back { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | width: 96rpx; |
| | | height: 80rpx; |
| | | right: 22rpx; |
| | | bottom: 32rpx; |
| | | background-color: #E6E6E6; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 0rpx $tn-box-shadow-color; |
| | | } |
| | | |
| | | &__change { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | width: 96rpx; |
| | | height: 80rpx; |
| | | left: 22rpx; |
| | | bottom: 32rpx; |
| | | line-height: 1; |
| | | background-color: #FFFFFF; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 0rpx $tn-box-shadow-color; |
| | | } |
| | | |
| | | &__mode { |
| | | &--zh { |
| | | transform: translateY(-10rpx); |
| | | } |
| | | &--en { |
| | | transform: translateY(10rpx); |
| | | } |
| | | |
| | | &--active { |
| | | color: $tn-main-color; |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | &--inactive { |
| | | &.tn-car-keyboard__mode--zh { |
| | | transform: scale(0.85) translateY(-10rpx); |
| | | } |
| | | } |
| | | |
| | | &--inactive { |
| | | &.tn-car-keyboard__mode--en { |
| | | transform: scale(0.85) translateY(10rpx); |
| | | } |
| | | } |
| | | } |
| | | |
| | | &--hover { |
| | | background-color: #E6E6E6 !important; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-cascade-selection tn-cascade-selection-class"> |
| | | <scroll-view |
| | | class="selection__scroll-view" |
| | | :class="[{'tn-border-solid-bottom': headerLine}]" |
| | | :style="[scrollViewStyle]" |
| | | scroll-x |
| | | scroll-with-animation |
| | | :scroll-into-view="scrollViewId" |
| | | > |
| | | <view class="selection__header" :class="[backgroundColorClass]" :style="[headerStyle]"> |
| | | <view |
| | | v-for="(item, index) in selectedArr" |
| | | :key="index" |
| | | :id="`select__${index}`" |
| | | class="selection__header__item" |
| | | :class="[headerItemClass(index)]" |
| | | :style="[headerItemStyle(index)]" |
| | | @tap.stop="clickNav(index)" |
| | | > |
| | | {{ item.text }} |
| | | <view |
| | | v-if="index===currentTab && showActiveLine" |
| | | class="selection__header__line" |
| | | :style="{backgroundColor: activeLineColor}" |
| | | ></view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <swiper |
| | | class="selection__list" |
| | | :class="[backgroundColorClass]" |
| | | :style="[listStyle]" |
| | | :current="currentTab" |
| | | :duration="300" |
| | | @change="switchTab" |
| | | > |
| | | <swiper-item |
| | | v-for="(item, index) in selectedArr" |
| | | :key="index" |
| | | > |
| | | <scroll-view |
| | | class="selection__list__item" |
| | | :style="{height: selectionContainerHeight + 'rpx'}" |
| | | scroll-y |
| | | :scroll-into-view="item.scrollViewId" |
| | | > |
| | | <view class="selection__list__item--first"></view> |
| | | <view |
| | | v-for="(subItem, subIndex) in item.list" |
| | | :key="subIndex" |
| | | :id="`select__${subIndex}`" |
| | | class="selection__list__item__cell" |
| | | :style="[itemStyle]" |
| | | @tap="change(index, subIndex, subItem)" |
| | | > |
| | | <view |
| | | v-if="item.index === subIndex" |
| | | class="selection__list__item__icon tn-icon-success" |
| | | :style="[itemIconStyle]" |
| | | ></view> |
| | | <image |
| | | v-if="subItem.src" |
| | | class="selection__list__item__image" |
| | | :style="[itemImageStyle]" |
| | | :src="subItem.src" |
| | | ></image> |
| | | <view |
| | | class="selection__list__item__title" |
| | | :class="[{'tn-text-bold': item.index === subIndex && itemActiveBold}]" |
| | | :style="[itemTitleStyle(index, subIndex)]" |
| | | > |
| | | {{ subItem.text }} |
| | | </view> |
| | | <view |
| | | v-if="subItem.subText" |
| | | class="selection__list__item__title--sub" |
| | | :style="[itemSubTitleStyle]" |
| | | > |
| | | {{ subItem.subText }} |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </swiper-item> |
| | | </swiper> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-cascade-selection', |
| | | mixins: [ componentsColorMixin ], |
| | | props: { |
| | | // 妿ä¸ä¸çº§æ¯è¯·æ±è¿åï¼å为第ä¸çº§æ°æ®ï¼å¦åä¸ºæææ°æ® |
| | | /* { |
| | | text: '', // æ é¢ |
| | | subText: '', // åæ é¢ |
| | | src: '', // å¾çå°å |
| | | value: 0, // éä¸çå¼ |
| | | children: [ |
| | | { |
| | | text: '', |
| | | subText: '', |
| | | value: 0, |
| | | children: [] |
| | | } |
| | | ] |
| | | } */ |
| | | list: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // é»è®¤éä¸å¼ |
| | | // ['value1','value2','value3'] |
| | | defaultValue: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // åéæ°æ®éè¿è¯·æ±æ¥è·å |
| | | request: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // request为trueæ¶çæ, è·åå°çåéæ°æ® |
| | | receiveData: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // æ¾ç¤ºheaderåºé¨ç»çº¿ |
| | | headerLine: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // headerèæ¯é¢è² |
| | | headerBgColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 顶鍿 ç¾æ é«åº¦,åä½rpx |
| | | tabsHeight: { |
| | | type: Number, |
| | | default: 88 |
| | | }, |
| | | // é»è®¤æ¾ç¤ºæå |
| | | text: { |
| | | type: String, |
| | | default: 'è¯·éæ©' |
| | | }, |
| | | // éä¸çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // éä¸åå ç² |
| | | activeBold: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é䏿¾ç¤ºåºé¨çº¿æ¡ |
| | | showActiveLine: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 线æ¡é¢è² |
| | | activeLineColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // icon大å°,åä½rpx |
| | | activeIconSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // iconé¢è² |
| | | activeIconColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // itemå¾ç宽度, åä½rpx |
| | | itemImgWidth: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // itemå¾çé«åº¦, åä½rpx |
| | | itemImgHeight: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // itemå¾çåè§ |
| | | itemImgRadius: { |
| | | type: String, |
| | | default: '50%' |
| | | }, |
| | | // item texté¢è² |
| | | itemTextColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // item textéä¸é¢è² |
| | | itemActiveTextColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // item textéä¸å ç² |
| | | itemActiveBold: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // item textæå大å°, åä½rpx |
| | | itemTextSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // item subTexté¢è² |
| | | itemSubTextColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // item subTextåä½å¤§å°, åä½rpx |
| | | itemSubTextSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // itemæ ·å¼ |
| | | itemStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // selectioné项容å¨é«åº¦, åä½rpx |
| | | selectionContainerHeight: { |
| | | type: Number, |
| | | default: 300 |
| | | } |
| | | }, |
| | | computed: { |
| | | scrollViewStyle() { |
| | | let style = {} |
| | | if (this.headerBgColor) { |
| | | style.backgroundColor = this.headerBgColor |
| | | } |
| | | return style |
| | | }, |
| | | headerStyle() { |
| | | let style = {} |
| | | style.height = `${this.tabsHeight}rpx` |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | return style |
| | | }, |
| | | headerItemClass() { |
| | | return (index) => { |
| | | let clazz = '' |
| | | if (index !== this.currentTab) { |
| | | clazz += ` ${this.fontColorClass}` |
| | | } else { |
| | | if (this.activeBold) { |
| | | clazz += ' tn-text-bold' |
| | | } |
| | | } |
| | | return clazz |
| | | } |
| | | }, |
| | | headerItemStyle() { |
| | | return (index) => { |
| | | let style = {} |
| | | style.color = index === this.currentTab ? this.activeColor : (this.fontColorStyle ? this.fontColorStyle : '') |
| | | if (this.fontSizeStyle) { |
| | | style.fontSize = this.fontSizeStyle |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | listStyle() { |
| | | let style = {} |
| | | style.height = `${this.selectionContainerHeight}rpx` |
| | | if (this.backgroundColorStyle) { |
| | | style.color = this.backgroundColorStyle |
| | | } |
| | | return style |
| | | }, |
| | | itemIconStyle() { |
| | | let style = {} |
| | | if (this.activeIconColor) { |
| | | style.color = this.activeIconColor |
| | | } |
| | | if (this.activeIconSize) { |
| | | style.fontSize = this.activeIconSize + 'rpx' |
| | | } |
| | | return style |
| | | }, |
| | | itemImageStyle() { |
| | | let style = {} |
| | | if (this.itemImgWidth) { |
| | | style.width = this.itemImgWidth + 'rpx' |
| | | } |
| | | if (this.itemImgHeight) { |
| | | style.height = this.itemImgHeight + 'rpx' |
| | | } |
| | | if (this.itemImgRadius) { |
| | | style.borderRadius = this.itemImgRadius |
| | | } |
| | | return style |
| | | }, |
| | | itemTitleStyle() { |
| | | return (index, subIndex) => { |
| | | let style = {} |
| | | if (index === subIndex) { |
| | | if (this.itemActiveTextColor) { |
| | | style.color = this.itemActiveTextColor |
| | | } |
| | | } else { |
| | | if (this.itemTextColor) { |
| | | style.color = this.itemTextColor |
| | | } |
| | | } |
| | | if (this.itemTextSize) { |
| | | style.fontSize = this.itemTextSize + 'rpx' |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | itemSubTitleStyle() { |
| | | let style = {} |
| | | if (this.itemSubTextColor) { |
| | | style.color = this.itemSubTextColor |
| | | } |
| | | if (this.itemSubTextSize) { |
| | | style.fontSize = this.itemSubTextSize + 'rpx' |
| | | } |
| | | return {} |
| | | } |
| | | }, |
| | | watch: { |
| | | list(val) { |
| | | this.initData(val, -1) |
| | | }, |
| | | defaultValue(val) { |
| | | this.setDefaultValue(val) |
| | | }, |
| | | receiveData(val) { |
| | | this.addSubData(val, this.currentTab) |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | // å½åéä¸çåé |
| | | currentTab: 0, |
| | | // tabsæ scrollViewæ»å¨çä½ç½® |
| | | scrollViewId: 'select__0', |
| | | // é项æ°ç» |
| | | selectedArr: [] |
| | | } |
| | | }, |
| | | created() { |
| | | this.setDefaultValue(this.defaultValue) |
| | | }, |
| | | methods: { |
| | | // åå§åæ°æ® |
| | | initData(data, index) { |
| | | if (!data || data.length === 0) return |
| | | if (this.request) { |
| | | // 第ä¸çº§æ°æ® |
| | | this.addSubData(data, index) |
| | | } else { |
| | | this.addSubData(this.getItemList(index, -1), index) |
| | | } |
| | | }, |
| | | // éç½®æ°æ® |
| | | reset() { |
| | | this.initData(this.list, -1) |
| | | }, |
| | | // æ»å¨åæ¢ |
| | | switchTab(e) { |
| | | this.currentTab = e.detail.current |
| | | this.checkSelectPosition() |
| | | }, |
| | | // ç¹å»æ é¢åæ¢ |
| | | clickNav(index) { |
| | | if (this.currentTab !== index) { |
| | | this.currentTab = index |
| | | } |
| | | }, |
| | | // åè¡¨æ°æ®åçæ¹å |
| | | change(index, subIndex, subItem) { |
| | | let item = this.selectedArr[index] |
| | | if (item.index === subIndex) return |
| | | item.index = subIndex |
| | | item.text = subItem.text |
| | | item.subText = subItem.subText || '' |
| | | item.value = subItem.value |
| | | item.src = subItem.src || '' |
| | | this.$emit('change', { |
| | | index: index, |
| | | subIndex: subIndex, |
| | | ...subItem |
| | | }) |
| | | |
| | | // 妿䏿¯å¼æ¥å è½½ï¼åååºå¯¹åºçæ°æ® |
| | | if (!this.request) { |
| | | let data = this.getItemList(index, subIndex) |
| | | this.addSubData(data, index) |
| | | } |
| | | }, |
| | | // 设置é»è®¤çæ°æ® |
| | | setDefaultValue(val) { |
| | | let defaultValues = val || [] |
| | | if (defaultValues.length > 0) { |
| | | this.selectedArr = this.getItemListWithValues(JSON.parse(JSON.stringify(this.list)), defaultValues) |
| | | if (!this.selectedArr) return |
| | | this.currentTab = this.selectedArr.length - 1 |
| | | this.$nextTick(() => { |
| | | this.checkSelectPosition() |
| | | }) |
| | | // defaultItemList.map((item) => { |
| | | // item.scrollViewId = `select__${item.index}` |
| | | // }) |
| | | // this.selectedArr = defaultItemList |
| | | // this.currentTab = defaultItemList.length - 1 |
| | | // this.$nextTick(() => { |
| | | // this.checkSelectPosition() |
| | | // }) |
| | | } else { |
| | | this.initData(this.list, -1) |
| | | } |
| | | }, |
| | | // è·å对åºé项çitemæ°æ® |
| | | getItemList(index, subIndex) { |
| | | let list = [] |
| | | let arr = JSON.parse(JSON.stringify(this.list)) |
| | | // åå§åæ°æ® |
| | | if (index === -1) { |
| | | list = this.removeChildren(arr) |
| | | } else { |
| | | // å¤æç¬¬ä¸é¡¹æ¯å¦å·²ç»éæ© |
| | | let value = this.selectedArr[0].index |
| | | value = value === -1 ? subIndex : value |
| | | list = arr[value].children || [] |
| | | if (index > 0) { |
| | | for (let i = 1; i < index + 1; i++) { |
| | | // è·åå½åæ°æ®éä¸çåºå· |
| | | let val = index === i ? subIndex : this.selectedArr[i].index |
| | | list = list[val].children || [] |
| | | if (list.length === 0) break |
| | | } |
| | | } |
| | | list = this.removeChildren(list) |
| | | } |
| | | return list |
| | | }, |
| | | // æ ¹æ®æ°ç»ä¸çå¼è·å对åºçitemæ°æ® |
| | | getItemListWithValues(data, values) { |
| | | const defaultValues = JSON.parse(JSON.stringify(values)) |
| | | if (!defaultValues || defaultValues.length === 0) return |
| | | // ååºç¬¬ä¸ä¸ªå¼æå¯¹åºçitem |
| | | const itemIndex = data.findIndex((item) => { |
| | | return item.value === defaultValues[0] |
| | | }) |
| | | if (itemIndex === -1) return |
| | | const item = data[itemIndex] |
| | | item.index = itemIndex |
| | | item.scrollViewId = `select__${itemIndex}` |
| | | item.list = this.removeChildren(JSON.parse(JSON.stringify(data))) |
| | | // 夿æ¯å¦åªæ1ä¸ªå¼ |
| | | if (defaultValues.length === 1 || (!item.hasOwnProperty('children') || item.children.length === 0)) { |
| | | return this.removeChildren([item]) |
| | | } else { |
| | | let selectItemList = [] |
| | | const children = item.children |
| | | selectItemList.push(item) |
| | | // ç§»é¤å·²ç»è·åçå¼ |
| | | defaultValues.splice(0, 1) |
| | | const childrenValue = this.getItemListWithValues(children, defaultValues) |
| | | selectItemList = selectItemList.concat(childrenValue) |
| | | |
| | | return this.removeChildren(selectItemList) |
| | | } |
| | | }, |
| | | // å é¤åå
ç´ |
| | | removeChildren(data) { |
| | | let list = data.map((item) => { |
| | | if (item.hasOwnProperty('children')) { |
| | | delete item['children'] |
| | | } |
| | | return item |
| | | }) |
| | | return list |
| | | }, |
| | | // æ°å¢åéæ°æ®æ¶å¤ç |
| | | addSubData(data, index) { |
| | | // 夿æ¯å¦å·²ç»å®æéæ©æ°æ®æè
为åå§åæ°æ® |
| | | if (!data || data.length === 0) { |
| | | if (index == -1) return |
| | | // 宿鿩 |
| | | let arr = this.selectedArr |
| | | // 妿å½åéä¸é¡¹çåºå·æ¯å·²éæ°æ®çé¿åº¦å°ï¼å表示å½åéæ°éæ©äºæ°æ® |
| | | if (index < arr.length - 1) { |
| | | let newArr = arr.slice(0, index + 1) |
| | | this.selectedArr = newArr |
| | | } |
| | | let result = JSON.parse(JSON.stringify(this.selectedArr)) |
| | | let lastItem = result[result.length - 1] || {} |
| | | let text = '' |
| | | result.map(item => { |
| | | text += item.text |
| | | delete item['list'] |
| | | delete item['scrollViewId'] |
| | | return item |
| | | }) |
| | | this.$emit('complete', { |
| | | result: result, |
| | | value: lastItem.value, |
| | | text: text, |
| | | subText: lastItem.subText, |
| | | src: lastItem.src |
| | | }) |
| | | } else { |
| | | // éç½®æ°æ® |
| | | let item = [{ |
| | | text: this.text, |
| | | subText: '', |
| | | value: '', |
| | | src: '', |
| | | index: -1, |
| | | scrollViewId: 'select__0', |
| | | list: data |
| | | }] |
| | | // åå§åæ°æ® |
| | | if (index === -1) { |
| | | this.selectedArr = item |
| | | } else { |
| | | // æ¼æ¥æ°æ§æ°æ®å¹¶ä¸å¤ææ¯å¦ä¸ºéæ°éæ©äºæ°æ®ï¼å¦æä¸ºéæ°éæ©äºæ°æ®åéç½®ä¹åçéé¡¹æ°æ®ï¼ |
| | | let retainArr = this.selectedArr.slice(0, index + 1) |
| | | this.selectedArr = retainArr.concat(item) |
| | | } |
| | | this.$nextTick(() => { |
| | | this.currentTab = this.selectedArr.length - 1 |
| | | }) |
| | | } |
| | | }, |
| | | // æ£æ¥å½åéä¸é¡¹ï¼å¹¶å°é项设置ä½ç½®ä¿¡æ¯ |
| | | checkSelectPosition() { |
| | | let item = this.selectedArr[this.currentTab] |
| | | item.scrollViewId = 'select__0' |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | // 设置å½åæ°æ®æ»å¨å°çä½ç½® |
| | | let val = item.index < 2 ? 0 : Number(item.index - 2) |
| | | item.scrollViewId = `select__${val}` |
| | | }, 10) |
| | | }) |
| | | |
| | | // 设置é项æ»å¨å°æå¨çä½ç½® |
| | | if (this.currentTab > 1) { |
| | | this.scrollViewId = `select__${this.currentTab - 1}` |
| | | } else { |
| | | this.scrollViewId = `select__0` |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-cascade-selection { |
| | | width: 100%; |
| | | } |
| | | |
| | | .selection { |
| | | &__scroll-view { |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &__header { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | position: relative; |
| | | |
| | | &__item { |
| | | max-width: 240rpx; |
| | | padding: 15rpx 30rpx; |
| | | flex-shrink: 0; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | position: relative; |
| | | } |
| | | |
| | | &__line { |
| | | width: 60rpx; |
| | | height: 6rpx; |
| | | border-radius: 4rpx; |
| | | position: absolute; |
| | | bottom: 0; |
| | | right: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | } |
| | | } |
| | | |
| | | &__list { |
| | | background-color: #FFFFFF; |
| | | &__item { |
| | | &--first { |
| | | width: 100%; |
| | | height: 20rpx; |
| | | } |
| | | |
| | | &__cell { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx 30rpx; |
| | | } |
| | | |
| | | &__icon { |
| | | margin-right: 12rpx; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | &__image { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | margin-right: 12rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | &__title { |
| | | word-break: break-all; |
| | | color: #333333; |
| | | font-size: 28rpx; |
| | | |
| | | &--sub { |
| | | margin-left: 20rpx; |
| | | word-break: break-all; |
| | | color: $tn-font-sub-color; |
| | | font-size: 24rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-checkbox-group-class tn-checkbox-group"> |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Emitter from '../../libs/utils/emitter.js' |
| | | |
| | | export default { |
| | | mixins: [ Emitter ], |
| | | name: 'tn-checkbox-group', |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // å¯ä»¥éä¸å¤å°ä¸ªcheckbox |
| | | max: { |
| | | type: Number, |
| | | default: 999 |
| | | }, |
| | | // 表åæäº¤æ¶çæ è¯ç¬¦ |
| | | name: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ç¦ç¨éæ© |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¦ç¨ç¹å»æ ç¾è¿è¡éæ© |
| | | disabledLabel: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // éæ©æ¡çå½¢ç¶ square æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: 'square' |
| | | }, |
| | | // é䏿¶çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // ç»ä»¶å¤§å° |
| | | size: { |
| | | type: Number, |
| | | default: 34 |
| | | }, |
| | | // æ¯ä¸ªcheckboxå ç宽度 |
| | | width: { |
| | | type: String, |
| | | default: 'auto' |
| | | }, |
| | | // æ¯å¦æ¢è¡ |
| | | wrap: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 徿 å¤§å° |
| | | iconSize: { |
| | | type: Number, |
| | | default: 20 |
| | | } |
| | | }, |
| | | computed: { |
| | | // è¿écomputedçåéï¼é½æ¯åç»ä»¶tn-checkboxéè¦ç¨å°çï¼ç±äºå¤´æ¡å°ç¨åºçå
¼å®¹æ§å·®å¼ï¼åç»ä»¶æ æ³å®æ¶çå¬ç¶ç»ä»¶åæ°çåå |
| | | // æä»¥éè¦æå¨éç¥åç»ä»¶ï¼è¿éè¿åä¸ä¸ªparentDataåéï¼ä¾watchçå¬ï¼å¨å
¶ä¸å»éç¥æ¯ä¸ä¸ªåç»ä»¶éæ°ä»ç¶ç»ä»¶(tn-checkbox-group) |
| | | // æåç¶ç»ä»¶æ°çåååçåæ° |
| | | parentData() { |
| | | return [this.value, this.disabled, this.disabledLabel, this.shape, this.activeColor, this.size, this.width, this.wrap, this.iconSize] |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | watch: { |
| | | // å½ç¶ç»ä»¶ä¸çåç»ä»¶éè¦å
±äº«çåæ°åçäºååï¼æå¨éç¥åç»ä»¶ |
| | | parentData() { |
| | | if (this.children.length) { |
| | | this.children.map(child => { |
| | | // 夿åç»ä»¶(tn-checkbox)妿æupdateParentDataæ¹æ³çè¯ï¼åç»ä»¶éæ°ä»ç¶ç»ä»¶æåäºææ°çå¼ |
| | | typeof(child.updateParentData) === 'function' && child.updateParentData() |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | this.children = [] |
| | | }, |
| | | methods: { |
| | | initValue(values) { |
| | | this.$emit('input', values) |
| | | }, |
| | | // 触åäºä»¶ |
| | | emitEvent() { |
| | | let values = [] |
| | | this.children.map(child => { |
| | | if (child.checkValue) values.push(child.name) |
| | | }) |
| | | this.$emit('change', values) |
| | | this.$emit('input', values) |
| | | // ååºäºä»¶ï¼ç¨äºå¨è¡¨åç»ä»¶ä¸åµå
¥checkboxçæ
åµï¼è¿è¡éªè¯ |
| | | // ç±äºå¤´æ¡å°ç¨åºæ§è¡è¿éï¼æ
éè¦ç¨å 忝«ç§çå»¶æ¶ |
| | | setTimeout(() => { |
| | | // å°å½åçå¼åéå° tn-form-item è¿è¡æ ¡éª |
| | | this.dispatch('tn-form-item', 'on-form-change', values) |
| | | }, 60) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-checkbox-group { |
| | | /* #ifndef MP || APP-NVUE */ |
| | | display: inline-flex; |
| | | flex-wrap: wrap; |
| | | /* #endif */ |
| | | &::after { |
| | | content: " "; |
| | | display: table; |
| | | clear: both; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-checkbox-class tn-checkbox" :style="[checkboxStyle]"> |
| | | <view |
| | | class="tn-checkbox__icon-wrap" |
| | | :class="[iconClass]" |
| | | :style="[iconStyle]" |
| | | @tap="toggle" |
| | | > |
| | | <view class="tn-checkbox__icon-wrap__icon" :class="[`tn-icon-${iconName}`]"></view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-checkbox__label" |
| | | :class="[labelClass]" |
| | | :style="{ |
| | | fontSize: labelSize ? labelSize + 'rpx' : '' |
| | | }" |
| | | @tap="onClickLabel" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-checkbox', |
| | | props: { |
| | | // checkboxåç§° |
| | | name: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // æ¯å¦ä¸ºéä¸ç¶æ |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¦ç¨éæ© |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¦ç¨ç¹å»æ ç¾è¿è¡éæ© |
| | | disabledLabel: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // éæ©æ¡çå½¢ç¶ square æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // é䏿¶çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ç»ä»¶å¤§å° |
| | | size: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // 徿 åç§° |
| | | iconName: { |
| | | type: String, |
| | | default: 'success' |
| | | }, |
| | | // 徿 å¤§å° |
| | | iconSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // labelçåä½å¤§å° |
| | | labelSize: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | // æ¯å¦ç¦ç¨éä¸ï¼ç¶ç»ä»¶çç¦ç¨ä¼è¦çå½åçç¦ç¨ç¶æ |
| | | isDisabled() { |
| | | return this.disabled ? this.disabled : (this.parent ? this.parentData.disabled : false) |
| | | }, |
| | | // æ¯å¦ç¦ç¨ç¹å»labeléä¸ï¼ç¶ç»ä»¶çç¦ç¨ä¼è¦çå½åçç¦ç¨ç¶æ |
| | | isDisabledLabel() { |
| | | return this.disabledLabel ? this.disabledLabel : (this.parent ? this.parentData.disabledLabel : false) |
| | | }, |
| | | // 尺寸 |
| | | checkboxSize() { |
| | | return this.size ? this.size : (this.parent ? this.parentData.size : 34) |
| | | }, |
| | | // æ¿æ´»æ¶çé¢è² |
| | | elAvtiveColor() { |
| | | return this.activeColor ? this.activeColor : (this.parent ? this.parentData.activeColor : '#01BEFF') |
| | | }, |
| | | // å½¢ç¶ |
| | | elShape() { |
| | | return this.shape ? this.shape : (this.parent ? this.parentData.shape : 'square') |
| | | }, |
| | | iconClass() { |
| | | let clazz = '' |
| | | clazz += (' tn-checkbox__icon-wrap--' + this.elShape) |
| | | |
| | | if (this.checkValue) clazz += ' tn-checkbox__icon-wrap--checked' |
| | | if (this.isDisabled) clazz += ' tn-checkbox__icon-wrap--disabled' |
| | | if (this.value && this.isDisabled) clazz += ' tn-checkbox__icon-wrap--disabled--checked' |
| | | |
| | | return clazz |
| | | }, |
| | | iconStyle() { |
| | | let style = {} |
| | | // 夿æ¯å¦ç¨æ·æå¨ç¦ç¨åä¼ éçå¼ |
| | | if (this.elAvtiveColor && this.checkValue && !this.isDisabled) { |
| | | style.borderColor = this.elAvtiveColor |
| | | style.backgroundColor = this.elAvtiveColor |
| | | } |
| | | |
| | | // checkboxå
é¨çå¾é徿 ï¼å¦æéä¸ç¶æï¼ä¸ºç½è²ï¼å¦å为éæè²å³å¯ |
| | | style.color = this.checkValue ? '#FFFFFF' : 'transparent' |
| | | |
| | | style.width = this.checkboxSize + 'rpx' |
| | | style.height = style.width |
| | | |
| | | style.fontSize = (this.iconSize ? this.iconSize : (this.parent ? this.parentData.iconSize : 20)) + 'rpx' |
| | | |
| | | return style |
| | | }, |
| | | checkboxStyle() { |
| | | let style = {} |
| | | if (this.parent && this.parentData.width) { |
| | | // #ifdef MP |
| | | // åå®¶å°ç¨åºå 为å®ä»¬ç¹æ®çç¼è¯ç»æï¼ä½¿ç¨floatå¸å± |
| | | style.float = 'left'; |
| | | // #endif |
| | | // #ifndef MP |
| | | // H5åAPP使ç¨flexå¸å± |
| | | style.flex = `0 0 ${this.parentData.width}`; |
| | | // #endif |
| | | } |
| | | if(this.parent && this.parentData.wrap) { |
| | | style.width = '100%'; |
| | | // #ifndef MP |
| | | // H5åAPP使ç¨flexå¸å±ï¼å°å®½åº¦è®¾ç½®100%ï¼å³å¯èªå¨æ¢è¡ |
| | | style.flex = '0 0 100%'; |
| | | // #endif |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | labelClass() { |
| | | let clazz = '' |
| | | if (this.isDisabled) { |
| | | clazz += ' tn-checkbox__label--disabled' |
| | | } |
| | | return clazz |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // å½åcheckboxçvalueå¼ |
| | | checkValue: false, |
| | | parentData: { |
| | | value: null, |
| | | max: null, |
| | | disabled: null, |
| | | disabledLabel: null, |
| | | shape: null, |
| | | activeColor: null, |
| | | size: null, |
| | | width: null, |
| | | wrap: null, |
| | | iconSize: null |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | this.checkValue = val |
| | | } |
| | | }, |
| | | created() { |
| | | // æ¯ä»å®å°ç¨åºä¸æ¯æprovide/injectï¼æä»¥ä½¿ç¨è¿ä¸ªæ¹æ³è·åæ´ä¸ªç¶ç»ä»¶ï¼å¨createdå®ä¹ï¼é¿å
循ç¯åºç¨ |
| | | // this.parent = this.$t.$parent.call(this, 'tn-checkbox-group') |
| | | // // 妿åå¨u-checkbox-groupï¼å°æ¬ç»ä»¶çthiså¡è¿ç¶ç»ä»¶çchildrenä¸ |
| | | // this.parent && this.parent.children.push(this) |
| | | // // åå§åç¶ç»ä»¶çvalueå¼ |
| | | // this.parent && this.parent.emitEvent() |
| | | this.updateParentData() |
| | | this.parent && this.parent.children.push(this) |
| | | }, |
| | | methods: { |
| | | updateCheckValue() { |
| | | // æ´æ°å½åcheckboxçéä¸ç¶æ |
| | | this.checkValue = (this.parent && this.parentData.value.includes(this.name)) || this.value === true |
| | | if (this.parent) { |
| | | if (this.value && !this.parentData.value.includes(this.name)) { |
| | | this.parentData.value.push(this.name) |
| | | this.parent.initValue(this.parentData.value) |
| | | } |
| | | } |
| | | }, |
| | | updateParentData() { |
| | | this.getParentData('tn-checkbox-group') |
| | | this.updateCheckValue() |
| | | }, |
| | | onClickLabel() { |
| | | if (!this.isDisabled && !this.isDisabledLabel) { |
| | | this.setValue() |
| | | } |
| | | }, |
| | | toggle() { |
| | | if (!this.isDisabled) { |
| | | this.setValue() |
| | | } |
| | | }, |
| | | emitEvent() { |
| | | this.$emit('change', { |
| | | name: this.name, |
| | | value: !this.checkValue |
| | | }) |
| | | if (this.parent) { |
| | | this.checkValue = !this.checkValue |
| | | // æ§è¡ç¶ç»ä»¶tn-checkbox-groupçäºä»¶æ¹æ³ |
| | | // çå¾
ä¸ä¸ä¸ªå¨æåæ§è¡ï¼å 为this.$emit('input')ä½ç¨äºç¶ç»ä»¶ï¼ååé¦å°åç»ä»¶å
é¨ï¼éè¦æ¶é´ |
| | | setTimeout(() => { |
| | | if(this.parent.emitEvent) this.parent.emitEvent(); |
| | | }, 80) |
| | | } |
| | | }, |
| | | // 设置inputçå¼ï¼éè¿v-modalç»å®ç»ä»¶çå¼ |
| | | setValue() { |
| | | // 夿æ¯å¦ä¸ºå¯éé¡¹ç» |
| | | if (this.parent) { |
| | | // åè½¬ç¶æ |
| | | if (this.checkValue === true) { |
| | | this.emitEvent() |
| | | // this.$emit('input', !this.checkValue) |
| | | } else { |
| | | // è¶
åºæå¤§å¯é项ï¼å¼¹åºæç¤º |
| | | if (this.parentData.value.length >= this.parentData.max) { |
| | | return this.$t.message.toast(`æå¤å¯é${this.parent.max}项`) |
| | | } |
| | | // å¦æåæ¥ä¸ºæªéä¸ç¶æï¼éè¦éä¸çæ°éå°äºç¶ç»ä»¶ä¸è®¾ç½®çmaxå¼ï¼æå¯ä»¥éä¸ |
| | | this.emitEvent(); |
| | | // this.$emit('input', !this.checkValue); |
| | | } |
| | | } else { |
| | | // åªæä¸ä¸ªå¯é项 |
| | | this.emitEvent() |
| | | this.$emit('input', !this.checkValue) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-checkbox { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | overflow: hidden; |
| | | user-select: none; |
| | | line-height: 1.8; |
| | | |
| | | &__icon-wrap { |
| | | color: $tn-font-color; |
| | | flex: none; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-sizing: border-box; |
| | | width: 42rpx; |
| | | height: 42rpx; |
| | | color: transparent; |
| | | text-align: center; |
| | | transition-property: color, border-color, background-color; |
| | | border: 1px solid $tn-font-sub-color; |
| | | transition-duration: 0.2s; |
| | | |
| | | /* #ifdef MP-TOUTIAO */ |
| | | // 头æ¡å°ç¨åºå
¼å®¹æ§é®é¢ï¼éè¦è®¾ç½®è¡é«ä¸º0ï¼å¦å徿 åä¸ |
| | | &__icon { |
| | | line-height: 0; |
| | | } |
| | | /* #endif */ |
| | | |
| | | &--circle { |
| | | border-radius: 100%; |
| | | } |
| | | |
| | | &--square { |
| | | border-radius: 6rpx; |
| | | } |
| | | |
| | | &--checked { |
| | | color: #FFFFFF; |
| | | background-color: $tn-main-color; |
| | | border-color: $tn-main-color; |
| | | } |
| | | |
| | | &--disabled { |
| | | background-color: $tn-font-holder-color; |
| | | border-color: $tn-font-sub-color; |
| | | } |
| | | |
| | | &--disabled--checked { |
| | | color: $tn-font-sub-color !important; |
| | | } |
| | | } |
| | | |
| | | &__label { |
| | | word-wrap: break-word; |
| | | margin-left: 10rpx; |
| | | margin-right: 24rpx; |
| | | color: $tn-font-color; |
| | | font-size: 30rpx; |
| | | |
| | | &--disabled { |
| | | color: $tn-font-sub-color; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-circle-progress-class tn-circle-progress" |
| | | :style="{ |
| | | width: widthPx + 'px', |
| | | height: widthPx + 'px' |
| | | }" |
| | | > |
| | | <!-- æ¯ä»å®å°ç¨åºä¸æ¯æcanvas-id屿§ï¼å¿
é¡»ç¨id屿§ --> |
| | | <!-- é»è®¤åç¯ --> |
| | | <canvas |
| | | class="tn-circle-progress__canvas-bg" |
| | | :canvas-id="elBgId" |
| | | :id="elBgId" |
| | | :style="{ |
| | | width: widthPx + 'px', |
| | | height: widthPx + 'px' |
| | | }" |
| | | ></canvas> |
| | | <!-- è¿åº¦åç¯ --> |
| | | <canvas |
| | | class="tn-circle-progress__canvas" |
| | | :canvas-id="elId" |
| | | :id="elId" |
| | | :style="{ |
| | | width: widthPx + 'px', |
| | | height: widthPx + 'px' |
| | | }" |
| | | ></canvas> |
| | | <view class="tn-circle-progress__content"> |
| | | <slot v-if="$slots.default || $slots.$default"></slot> |
| | | <view v-else-if="showPercent" class="tn-circle-progress__content__percent">{{ percent + '%' }}</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-circle-progress', |
| | | props: { |
| | | // è¿åº¦ï¼ç¾åæ¯ï¼ |
| | | percent: { |
| | | type: Number, |
| | | default: 0, |
| | | validator: val => { |
| | | return val >= 0 && val <= 100 |
| | | } |
| | | }, |
| | | // åç¯çº¿å®½ |
| | | borderWidth: { |
| | | type: Number, |
| | | default: 14 |
| | | }, |
| | | // æ´ä½åç宽度 |
| | | width: { |
| | | type: Number, |
| | | default: 200 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºæ¡çº¹ |
| | | striped: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¡çº¹æ¯å¦è¿å¨ |
| | | stripedActive: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¿æ´»é¨åé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // éæ¿æ´»é¨åé¢è² |
| | | inactiveColor: { |
| | | type: String, |
| | | default: '#f0f0f0' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¿åº¦æ¡å
é¨ç¾åæ¯å¼ |
| | | showPercent: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // åç¯æ§è¡å¨ç»çæ¶é´ï¼ms |
| | | duration: { |
| | | type: Number, |
| | | default: 1500 |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 微信å°ç¨åºä¸ä¸è½ä½¿ç¨this.$t.uuid()å½¢å¼å¨æçæidå¼ï¼å¦å伿¥é |
| | | // #ifdef MP-WEIXIN |
| | | elBgId: 'tCircleProgressBgId', |
| | | elId: 'tCircleProgressElId', |
| | | // #endif |
| | | // #ifndef MP-WEIXIN |
| | | elBgId: this.$t.uuid(), |
| | | elId: this.$t.uuid(), |
| | | // #endif |
| | | // æ´»å¨åä¸ä¸æ |
| | | progressContext: null, |
| | | // è½¬æ¢æpx为åä½çèæ¯å®½åº¦ |
| | | widthPx: uni.upx2px(this.width || 200), |
| | | // è½¬æ¢æpx为åä½çåç¯å®½åº¦ |
| | | borderWidthPx: uni.upx2px(this.borderWidth || 14), |
| | | // canvasç»åçèµ·å§è§åº¦ï¼é»è®¤ä¸º-90度ï¼é¡ºæ¶é |
| | | startAngle: -90 * Math.PI / 180, |
| | | // å¨æä¿®æ¹è¿åº¦å¼çæ¶åï¼ä¿åè¿åº¦å¼çååååå¼ |
| | | newPercent: 0, |
| | | oldPercent: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | percent(newVal, oldVal = 0) { |
| | | if (newVal > 100) newVal = 100 |
| | | if (oldVal < 0) oldVal = 0 |
| | | |
| | | this.newPercent = newVal |
| | | this.oldPercent = oldVal |
| | | setTimeout(() => { |
| | | // æ 论æ¯ç¾åæ¯å¼å¢å è¿æ¯åå°ï¼éè¦æä½è¿æ¯åæ¥çæ§çç¾åæ¯å¼ |
| | | // å°æ¤å¼åå°æè
æ°å¢å°æ°çç¾åæ¯å¼ |
| | | this.drawCircleByProgress(oldVal) |
| | | }, 50) |
| | | } |
| | | }, |
| | | created() { |
| | | // èµå¼ï¼ç¨äºå è½½å第ä¸ä¸ªç»åä½¿ç¨ |
| | | this.newPercent = this.percent; |
| | | this.oldPercent = 0; |
| | | }, |
| | | mounted() { |
| | | setTimeout(() => { |
| | | this.drawProgressBg() |
| | | this.drawCircleByProgress(this.oldPercent) |
| | | }, 50) |
| | | }, |
| | | methods: { |
| | | // ç»å¶è¿åº¦æ¡èæ¯ |
| | | drawProgressBg() { |
| | | let ctx = uni.createCanvasContext(this.elBgId, this) |
| | | // 设置线宽 |
| | | ctx.setLineWidth(this.borderWidthPx) |
| | | // 设置é¢è² |
| | | ctx.setStrokeStyle(this.inactiveColor) |
| | | ctx.beginPath() |
| | | let radius = this.widthPx / 2 |
| | | ctx.arc(radius, radius, radius - this.borderWidthPx, 0, 360 * Math.PI / 180, false) |
| | | ctx.stroke() |
| | | ctx.draw() |
| | | }, |
| | | // ç»å¶åå¼§çè¿åº¦ |
| | | drawCircleByProgress(progress) { |
| | | // 妿已ç»åå¨åæ¿æ¥ä½¿ç¨ |
| | | let ctx = this.progressContext |
| | | if (!ctx) { |
| | | ctx =uni.createCanvasContext(this.elId, this) |
| | | this.progressContext = ctx |
| | | } |
| | | ctx.setLineCap('round') |
| | | // 设置线æ¡å®½åº¦åé¢è² |
| | | ctx.setLineWidth(this.borderWidthPx) |
| | | ctx.setStrokeStyle(this.activeColor) |
| | | // å°æ»è¿æ¸¡æ¶é´é¤ä»¥100ï¼å¾åºæ¯ä¿®æ¹ç¾åä¹ä¸è¿åº¦æéçæ¶é´ |
| | | let preSecondTime = Math.floor(this.duration / 100) |
| | | // ç»æè§ç计ç®ä¾æ®ä¸ºï¼å°2Ïå为100份ï¼ä¹ä»¥å½åçè¿åº¦å¼ï¼å¾åºç»æ¢ç¹ç弧度å¼ï¼å èµ·å§è§ï¼ä¸ºæ´ä¸ªåä»é»è®¤ç |
| | | let endAngle = ((360 * Math.PI / 180) / 100) * progress + this.startAngle |
| | | let radius = this.widthPx / 2 |
| | | ctx.beginPath() |
| | | ctx.arc(radius, radius, radius - this.borderWidthPx, this.startAngle, endAngle, false) |
| | | ctx.stroke() |
| | | ctx.draw() |
| | | |
| | | // 妿忴忰å¼å¤§äºæ§å¼ï¼æå³çå¢å¤§äºç¾åæ¯ |
| | | if (this.newPercent > this.oldPercent) { |
| | | // æ¯æ¬¡éå¢ç¾åä¹ä¸ |
| | | progress++ |
| | | // 妿æ°å¢åçå¼ï¼å¤§äºéè¦è®¾ç½®çå¼ç¾åæ¯å¼ï¼åæ¢ç»§ç»å¢å |
| | | if (progress > this.newPercent) return |
| | | } else { |
| | | progress-- |
| | | if (progress < this.newPercent) return |
| | | } |
| | | setTimeout(() => { |
| | | // 宿¶å¨ï¼æ¯æ¬¡æä½é´é为timeå¼ï¼ä¸ºäºè®©è¿åº¦æ¡æå¨ç»ææ |
| | | this.drawCircleByProgress(progress) |
| | | }, preSecondTime) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-circle-progress { |
| | | position: relative; |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | background-color: transparent; |
| | | |
| | | &__canvas { |
| | | position: absolute; |
| | | |
| | | &-bg { |
| | | position: absolute; |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | &__percent { |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-collapse-item-class tn-collapse-item" :style="[itemStyle]"> |
| | | <!-- å¤´é¨ --> |
| | | <view |
| | | class="tn-collapse-item__head" |
| | | :style="[headStyle]" |
| | | :hover-stay-time="200" |
| | | :hover-class="hoverClass" |
| | | @tap.stop="headClick" |
| | | > |
| | | <block v-if="!$slots['title-all'] || !$slots['$title-all']"> |
| | | <view |
| | | v-if="!$slots.title || !$slots.$title" |
| | | class="tn-collapse-item__head__title tn-text-ellipsis" |
| | | :style="[ |
| | | { textAlign: align ? align : 'left'}, |
| | | isShow && activeStyle && !arrow ? activeStyle : '' |
| | | ]" |
| | | >{{ title }}</view> |
| | | <view v-else> |
| | | <slot name="title"></slot> |
| | | </view> |
| | | <view class="tn-collapse-item__head__icon__wrap"> |
| | | <view |
| | | v-if="arrow" |
| | | class="tn-icon-down tn-collapse-item__head__icon__arrow" |
| | | :class="{'tn-collapse-item__head__icon__arrow--active': isShow}" |
| | | :style="[arrowIconStyle]" |
| | | ></view> |
| | | </view> |
| | | </block> |
| | | <view v-else> |
| | | <slot name="title-all"></slot> |
| | | </view> |
| | | </view> |
| | | <!-- å
容 --> |
| | | <view |
| | | class="tn-collapse-item__body" |
| | | :style="[{ |
| | | height: isShow ? height + 'px' : '0' |
| | | }]" |
| | | > |
| | | <view class="tn-collapse-item__body__content" :id="elId" :style="[bodyStyle]"> |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-collapse-item', |
| | | props: { |
| | | // å±å¼ |
| | | open: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¯ä¸æ è¯ |
| | | name: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ é¢ |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ é¢å¯¹é½æ¹å¼ |
| | | align: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // ç¹å»ä¸æ¶èµ· |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ´»å¨æ¶æ ·å¼ |
| | | activeStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ è¯ |
| | | index: { |
| | | type: [Number, String], |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | arrowIconStyle() { |
| | | let style = {} |
| | | if (this.arrowColor) { |
| | | style.color = this.arrowColor |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isShow: false, |
| | | elId: this.$t.uuid(), |
| | | // bodyé«åº¦ |
| | | height: 0, |
| | | // 头鍿 ·å¼ |
| | | headStyle: {}, |
| | | // 䏻使 ·å¼ |
| | | bodyStyle: {}, |
| | | // itemæ ·å¼ |
| | | itemStyle: {}, |
| | | // æ¾ç¤ºå³è¾¹ç®å¤´ |
| | | arrow: true, |
| | | // ç®å¤´é¢è² |
| | | arrowColor: '', |
| | | // ç¹å»å¤´é¨æ¶çæææ ·å¼ |
| | | hoverClass: '' |
| | | } |
| | | }, |
| | | watch: { |
| | | open(value) { |
| | | this.isShow = value |
| | | } |
| | | }, |
| | | created() { |
| | | this.parent = false |
| | | this.isShow = this.open |
| | | }, |
| | | mounted() { |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | // 弿¥è·åå
容æè
ä¿®æ¹äºå
容æ¶éæ°è·åå
容çä¿¡æ¯ |
| | | init() { |
| | | this.parent = this.$t.$parent.call(this, 'tn-collapse') |
| | | if (this.parent) { |
| | | this.nameSync = this.name ? this.name : this.parent.childrens.length |
| | | // ä¸åå¨ææ·»å 对åºå®ä¾ |
| | | !this.parent.childrens.includes(this) && this.parent.childrens.push(this) |
| | | this.headStyle = this.parent.headStyle |
| | | this.bodyStyle = this.parent.bodyStyle |
| | | this.itemStyle = this.parent.itemStyle |
| | | this.arrow = this.parent.arrow |
| | | this.arrowColor = this.parent.arrowColor |
| | | this.hoverClass = this.parent.hoverClass |
| | | } |
| | | this.$nextTick(() => { |
| | | this.queryRect() |
| | | }) |
| | | }, |
| | | // ç¹å»å¤´é¨ |
| | | headClick() { |
| | | if (this.disabled) return |
| | | if (this.parent && this.parent.accordion) { |
| | | this.parent.childrens.map(child => { |
| | | // å¦ææ¯æé£ç´æ¨¡å¼ï¼å°å
¶ä»çitemå
³é |
| | | if (this !== child) { |
| | | child.isShow = false |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.isShow = !this.isShow |
| | | // 触åä¿®æ¹äºä»¶ |
| | | this.$emit('change', { |
| | | index: this.index, |
| | | show: this.isShow |
| | | }) |
| | | // åªæå¨æå¼æ¶æè§¦åç¶å
ç´ çchange |
| | | if (this.isShow) this.parent && this.parent.onChange() |
| | | this.$forceUpdate() |
| | | }, |
| | | // æ¥è¯¢å
容é«åº¦ |
| | | queryRect() { |
| | | this._tGetRect('#'+this.elId).then(res => { |
| | | this.height = res.height |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-collapse-item { |
| | | |
| | | &__head { |
| | | position: relative; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | color: $tn-font-color; |
| | | font-size: 30rpx; |
| | | line-height: 1; |
| | | padding: 24rpx 0; |
| | | padding-left: 24rpx; |
| | | text-align: left; |
| | | background-color: #FFFFFF; |
| | | |
| | | &__title { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &__icon { |
| | | &__arrow { |
| | | transition: all 0.3s; |
| | | margin-right: 20rpx; |
| | | margin-left: 14rpx; |
| | | font-size: inherit; |
| | | |
| | | &--active { |
| | | transform: rotate(180deg); |
| | | transform-origin: center center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__body { |
| | | transition: all 0.3s; |
| | | overflow: hidden; |
| | | |
| | | &__content { |
| | | overflow: hidden; |
| | | font-size: 28rpx; |
| | | color: $tn-font-color; |
| | | text-align: left; |
| | | background-color: #FFFFFF; |
| | | padding-left: 24rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-collapse-class tn-collapse"> |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-collapse', |
| | | props: { |
| | | // æ¯å¦ä¸ºæé£ç´ |
| | | accordion: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 头鍿 ·å¼ |
| | | headStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // 䏻颿 ·å¼ |
| | | bodyStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¯ä¸ä¸ªitemçæ ·å¼ |
| | | itemStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¾ç¤ºç®å¤´ |
| | | arrow: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ç®å¤´é¢è² |
| | | arrowColor: { |
| | | type: String, |
| | | default: '#AAAAAA' |
| | | }, |
| | | // ç¹å»æ 颿 æ¶çæåæ ·å¼ |
| | | hoverClass: { |
| | | type: String, |
| | | default: 'tn-hover' |
| | | } |
| | | }, |
| | | computed: { |
| | | parentData() { |
| | | return [this.headStyle, this.bodyStyle, this.itemStyle, this.arrow, this.arrowColor, this.hoverClass] |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | watch: { |
| | | parentData() { |
| | | // 妿ç¶ç»ä»¶çåæ°åçååéæ°åå§ååç»ä»¶çä¿¡æ¯ |
| | | if (this.childrens.length > 0) { |
| | | this.init() |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | this.childrens = [] |
| | | }, |
| | | methods: { |
| | | // éæ°åå§åå
鍿æåå
ç´ è®¡ç®é«åº¦ï¼å¼æ¥è·åæ°æ®æ¶éæ°æ¸²æ |
| | | init() { |
| | | this.childrens.forEach((child, index) => { |
| | | child.init() |
| | | }) |
| | | }, |
| | | // collapseItem被ç¹å»æ¶ç±collapseItemè°ç¨ç¶ç»ä»¶ |
| | | onChange() { |
| | | let activeItem = [] |
| | | this.childrens.forEach((child, index) => { |
| | | if (child.isShow) { |
| | | activeItem.push(child.nameSync) |
| | | } |
| | | }) |
| | | // å¦ææ¶æé£ç´æ¨¡å¼ï¼åªæä¸ä¸ªå¹é
ç»æï¼å³activeItemé¿åº¦ä¸º1 |
| | | if (this.accordion) activeItem = activeItem.join(',') |
| | | this.$emit('change', activeItem) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <text |
| | | class="tn-color-icon-class tn-color-icon" |
| | | :class="[ |
| | | 'tn-color-icon-' + name |
| | | ]" |
| | | :style="{ |
| | | fontSize: size + unit, |
| | | margin: margin |
| | | }" |
| | | @tap="handleClick" |
| | | ></text> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-color-icon', |
| | | props: { |
| | | // ç´¢å¼ |
| | | index: { |
| | | type: [Number, String], |
| | | default: '0' |
| | | }, |
| | | // 徿 åç§° |
| | | name: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 徿 å¤§å° |
| | | size: { |
| | | type: Number, |
| | | default:32 |
| | | }, |
| | | // 大å°åä½ |
| | | unit: { |
| | | type: String, |
| | | default: 'px' |
| | | }, |
| | | // å¤è¾¹è· |
| | | margin: { |
| | | type: String, |
| | | default: '0' |
| | | } |
| | | }, |
| | | computed: { |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çç¹å»äºä»¶ |
| | | handleClick() { |
| | | this.$emit("click", { |
| | | index: Number(this.index) |
| | | }) |
| | | this.$emit("tap", { |
| | | index: Number(this.index) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | @charset "UTF-8"; |
| | | |
| | | @font-face { |
| | | font-family: "tuniaoColorFont"; /* Project id 2445412 */ |
| | | /* Color fonts */ |
| | | src: url('iconfont.woff2?t=1632654518618') format('woff2'); |
| | | } |
| | | |
| | | .tn-color-icon { |
| | | font-family: "tuniaoColorFont" !important; |
| | | font-size: 16px; |
| | | font-style: normal; |
| | | -webkit-font-smoothing: antialiased; |
| | | -moz-osx-font-smoothing: grayscale; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | } |
| | | |
| | | .tn-color-icon-logo-github:before { |
| | | content: "\e601"; |
| | | } |
| | | |
| | | .tn-color-icon-logo-qq:before { |
| | | content: "\e602"; |
| | | } |
| | | |
| | | .tn-color-icon-logo-weixin:before { |
| | | content: "\e603"; |
| | | } |
| | | |
| | | .tn-color-icon-logo-alipay:before { |
| | | content: "\e604"; |
| | | } |
| | | |
| | | .tn-color-icon-logo-weibo:before { |
| | | content: "\e605"; |
| | | } |
| | | |
| | | .tn-color-icon-logo-dingtalk:before { |
| | | content: "\e606"; |
| | | } |
| | | |
| | | .tn-color-icon-safe:before { |
| | | content: "\e607"; |
| | | } |
| | | |
| | | .tn-color-icon-wifi:before { |
| | | content: "\e608"; |
| | | } |
| | | |
| | | .tn-color-icon-help:before { |
| | | content: "\e609"; |
| | | } |
| | | |
| | | .tn-color-icon-tag:before { |
| | | content: "\e60a"; |
| | | } |
| | | |
| | | .tn-color-icon-play:before { |
| | | content: "\e60b"; |
| | | } |
| | | |
| | | .tn-color-icon-stopwatch:before { |
| | | content: "\e60c"; |
| | | } |
| | | |
| | | .tn-color-icon-home:before { |
| | | content: "\e60d"; |
| | | } |
| | | |
| | | .tn-color-icon-map:before { |
| | | content: "\e60e"; |
| | | } |
| | | |
| | | .tn-color-icon-book:before { |
| | | content: "\e60f"; |
| | | } |
| | | |
| | | .tn-color-icon-qrcode:before { |
| | | content: "\e610"; |
| | | } |
| | | |
| | | .tn-color-icon-discover:before { |
| | | content: "\e611"; |
| | | } |
| | | |
| | | .tn-color-icon-visitor:before { |
| | | content: "\e612"; |
| | | } |
| | | |
| | | .tn-color-icon-menu:before { |
| | | content: "\e613"; |
| | | } |
| | | |
| | | .tn-color-icon-renew:before { |
| | | content: "\e614"; |
| | | } |
| | | |
| | | .tn-color-icon-business:before { |
| | | content: "\e615"; |
| | | } |
| | | |
| | | .tn-color-icon-telephone:before { |
| | | content: "\e616"; |
| | | } |
| | | |
| | | .tn-color-icon-medicine:before { |
| | | content: "\e617"; |
| | | } |
| | | |
| | | .tn-color-icon-chicken:before { |
| | | content: "\e618"; |
| | | } |
| | | |
| | | .tn-color-icon-clock:before { |
| | | content: "\e619"; |
| | | } |
| | | |
| | | .tn-color-icon-download:before { |
| | | content: "\e61a"; |
| | | } |
| | | |
| | | .tn-color-icon-lamp:before { |
| | | content: "\e61b"; |
| | | } |
| | | |
| | | .tn-color-icon-hourglass:before { |
| | | content: "\e61c"; |
| | | } |
| | | |
| | | .tn-color-icon-calendar:before { |
| | | content: "\e61d"; |
| | | } |
| | | |
| | | .tn-color-icon-bluetooth:before { |
| | | content: "\e61e"; |
| | | } |
| | | |
| | | .tn-color-icon-fish:before { |
| | | content: "\e61f"; |
| | | } |
| | | |
| | | .tn-color-icon-seal:before { |
| | | content: "\e620"; |
| | | } |
| | | |
| | | .tn-color-icon-remind:before { |
| | | content: "\e621"; |
| | | } |
| | | |
| | | .tn-color-icon-music:before { |
| | | content: "\e622"; |
| | | } |
| | | |
| | | .tn-color-icon-email:before { |
| | | content: "\e623"; |
| | | } |
| | | |
| | | .tn-color-icon-medal:before { |
| | | content: "\e624"; |
| | | } |
| | | |
| | | .tn-color-icon-image:before { |
| | | content: "\e625"; |
| | | } |
| | | |
| | | .tn-color-icon-network:before { |
| | | content: "\e626"; |
| | | } |
| | | |
| | | .tn-color-icon-wallet:before { |
| | | content: "\e627"; |
| | | } |
| | | |
| | | .tn-color-icon-program:before { |
| | | content: "\e628"; |
| | | } |
| | | |
| | | .tn-color-icon-shrimp:before { |
| | | content: "\e629"; |
| | | } |
| | | |
| | | .tn-color-icon-collect:before { |
| | | content: "\e62a"; |
| | | } |
| | | |
| | | .tn-color-icon-screw:before { |
| | | content: "\e62b"; |
| | | } |
| | | |
| | | .tn-color-icon-set:before { |
| | | content: "\e62c"; |
| | | } |
| | | |
| | | .tn-color-icon-userfavorite:before { |
| | | content: "\e62d"; |
| | | } |
| | | |
| | | .tn-color-icon-useradd:before { |
| | | content: "\e62e"; |
| | | } |
| | | |
| | | .tn-color-icon-honor:before { |
| | | content: "\e62f"; |
| | | } |
| | | |
| | | .tn-color-icon-shop:before { |
| | | content: "\e630"; |
| | | } |
| | | |
| | | .tn-color-icon-usercard:before { |
| | | content: "\e631"; |
| | | } |
| | | |
| | | .tn-color-icon-school:before { |
| | | content: "\e632"; |
| | | } |
| | | |
| | | .tn-color-icon-user:before { |
| | | content: "\e633"; |
| | | } |
| | | |
| | | .tn-color-icon-internet:before { |
| | | content: "\e634"; |
| | | } |
| | | |
| | | .tn-color-icon-time:before { |
| | | content: "\e635"; |
| | | } |
| | | |
| | | .tn-color-icon-topic:before { |
| | | content: "\e636"; |
| | | } |
| | | |
| | | .tn-color-icon-phone:before { |
| | | content: "\e637"; |
| | | } |
| | | |
| | | .tn-color-icon-usertable:before { |
| | | content: "\e638"; |
| | | } |
| | | |
| | | .tn-color-icon-userset:before { |
| | | content: "\e639"; |
| | | } |
| | | |
| | | .tn-color-icon-game:before { |
| | | content: "\e63a"; |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-column-notice-class tn-column-notice" |
| | | :class="[backgroundColorClass]" |
| | | :style="[noticeStyle]" |
| | | > |
| | | <!-- 左徿 --> |
| | | <view class="tn-column-notice__icon"> |
| | | <view |
| | | v-if="leftIcon" |
| | | class="tn-column-notice__icon--left" |
| | | :class="[`tn-icon-${leftIconName}`,fontColorClass]" |
| | | :style="[fontStyle('leftIcon')]" |
| | | @tap="clickLeftIcon"></view> |
| | | </view> |
| | | |
| | | <!-- æ»å¨æ¾ç¤ºå
容 --> |
| | | <swiper class="tn-column-notice__swiper" :style="[swiperStyle]" :vertical="vertical" circular :autoplay="autoplay && playStatus === 'play'" :interval="duration" @change="change"> |
| | | <swiper-item v-for="(item, index) in list" :key="index" class="tn-column-notice__swiper--item"> |
| | | <view |
| | | class="tn-column-notice__swiper--content tn-text-ellipsis" |
| | | :class="[fontColorClass]" |
| | | :style="[fontStyle()]" |
| | | @tap="click(index)" |
| | | >{{ item }}</view> |
| | | </swiper-item> |
| | | </swiper> |
| | | |
| | | <!-- å³å¾æ --> |
| | | <view class="tn-column-notice__icon"> |
| | | <view |
| | | v-if="rightIcon" |
| | | class="tn-column-notice__icon--right" |
| | | :class="[`tn-icon-${rightIconName}`,fontColorClass]" |
| | | :style="[fontStyle('rightIcon')]" |
| | | @tap="clickRightIcon"></view> |
| | | <view |
| | | v-if="closeBtn" |
| | | class="tn-column-notice__icon--right" |
| | | :class="[`tn-icon-close`,fontColorClass]" |
| | | :style="[fontStyle('close')]" |
| | | @tap="close"></view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-column-notice', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // æ¾ç¤ºçå
容 |
| | | list: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // æ¯å¦æ¾ç¤º |
| | | show: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ææ¾ç¶æ |
| | | // play -> ææ¾ paused -> æå |
| | | playStatus: { |
| | | type: String, |
| | | default: 'play' |
| | | }, |
| | | // æ»å¨æ¹å |
| | | // horizontal -> æ°´å¹³æ»å¨ vertical -> åç´æ»å¨ |
| | | mode: { |
| | | type: String, |
| | | default: 'horizontal' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå·¦è¾¹å¾æ |
| | | leftIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å·¦è¾¹å¾æ çåç§° |
| | | leftIconName: { |
| | | type: String, |
| | | default: 'sound' |
| | | }, |
| | | // å·¦è¾¹å¾æ çå¤§å° |
| | | leftIconSize: { |
| | | type: Number, |
| | | default: 34 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå³è¾¹ç徿 |
| | | rightIcon: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å³è¾¹å¾æ çåç§° |
| | | rightIconName: { |
| | | type: String, |
| | | default: 'right' |
| | | }, |
| | | // å³è¾¹å¾æ çå¤§å° |
| | | rightIconSize: { |
| | | type: Number, |
| | | default: 26 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå
³éæé® |
| | | closeBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // åè§ |
| | | radius: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
è¾¹è· |
| | | padding: { |
| | | type: String, |
| | | default: '18rpx 24rpx' |
| | | }, |
| | | // èªå¨ææ¾ |
| | | autoplay: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ»å¨å¨æ |
| | | duration: { |
| | | type: Number, |
| | | default: 2000 |
| | | } |
| | | }, |
| | | computed: { |
| | | fontStyle() { |
| | | return (type) => { |
| | | let style = {} |
| | | style.color = this.fontColorStyle ? this.fontColorStyle : '' |
| | | style.fontSize = this.fontSizeStyle ? this.fontSizeStyle : '' |
| | | if (type === 'leftIcon' && this.leftIconSize) { |
| | | style.fontSize = this.leftIconSize + 'rpx' |
| | | } |
| | | if (type === 'rightIcon' && this.rightIconSize) { |
| | | style.fontSize = this.rightIconSize + 'rpx' |
| | | } |
| | | if (type === 'close') { |
| | | style.fontSize = '24rpx' |
| | | } |
| | | |
| | | return style |
| | | } |
| | | }, |
| | | noticeStyle() { |
| | | let style = {} |
| | | style.backgroundColor = this.backgroundColorStyle ? this.backgroundColorStyle : 'transparent' |
| | | if (this.padding) style.padding = this.padding |
| | | return style |
| | | }, |
| | | swiperStyle() { |
| | | let style = {} |
| | | style.height = this.fontSize ? this.fontSize + 6 + this.fontUnit : '32rpx' |
| | | style.lineHeight = style.height |
| | | |
| | | return style |
| | | }, |
| | | // æ è®°æ¯å¦ä¸ºåç´ |
| | | vertical() { |
| | | if (this.mode === 'horizontal') return false |
| | | else return true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | watch: { |
| | | |
| | | }, |
| | | methods: { |
| | | // ç¹å»äºéç¥æ |
| | | click(index) { |
| | | this.$emit('click', index) |
| | | }, |
| | | // ç¹å»äºå
³éæé® |
| | | close() { |
| | | this.$emit('close') |
| | | }, |
| | | // ç¹å»äºå·¦è¾¹å¾æ |
| | | clickLeftIcon() { |
| | | this.$emit('clickLeft') |
| | | }, |
| | | // ç¹å»äºå³è¾¹å¾æ |
| | | clickRightIcon() { |
| | | this.$emit('clickRight') |
| | | }, |
| | | // åæ¢æ¶æ¯æ¶é´ |
| | | change(event) { |
| | | let index = event.detail.current |
| | | if (index === this.list.length - 1) { |
| | | this.$emit('end') |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-column-notice { |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-wrap: nowrap; |
| | | overflow: hidden; |
| | | |
| | | &__swiper { |
| | | height: auto; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | margin-left: 12rpx; |
| | | |
| | | &--item { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &--content { |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | |
| | | &__icon { |
| | | &--left { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | &--right { |
| | | margin-left: 12rpx; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-countdown-class tn-countdown"> |
| | | <view |
| | | v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '00'))" |
| | | class="tn-countdown__item" |
| | | :class="[backgroundColorClass]" |
| | | :style="[itemStyle]" |
| | | > |
| | | <view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]"> |
| | | {{ d }} |
| | | </view> |
| | | </view> |
| | | <view |
| | | v-if="showHours && (hideZeroDay || (!hideZeroDay && d != '00'))" |
| | | class="tn-countdown__separator" |
| | | :style="{ |
| | | fontSize: separatorSize + 'rpx', |
| | | color: separatorColor, |
| | | paddingBottom: separator === 'en' ? '4rpx' : 0 |
| | | }" |
| | | > |
| | | {{ separator === 'en' ? ':' : '天'}} |
| | | </view> |
| | | |
| | | <view |
| | | v-if="showHours" |
| | | class="tn-countdown__item" |
| | | :class="[backgroundColorClass]" |
| | | :style="[itemStyle]" |
| | | > |
| | | <view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]"> |
| | | {{ h }} |
| | | </view> |
| | | </view> |
| | | <view |
| | | v-if="showMinutes" |
| | | class="tn-countdown__separator" |
| | | :style="{ |
| | | fontSize: separatorSize + 'rpx', |
| | | color: separatorColor, |
| | | paddingBottom: separator === 'en' ? '4rpx' : 0 |
| | | }" |
| | | > |
| | | {{ separator === 'en' ? ':' : 'æ¶'}} |
| | | </view> |
| | | |
| | | <view |
| | | v-if="showMinutes" |
| | | class="tn-countdown__item" |
| | | :class="[backgroundColorClass]" |
| | | :style="[itemStyle]" |
| | | > |
| | | <view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]"> |
| | | {{ m }} |
| | | </view> |
| | | </view> |
| | | <view |
| | | v-if="showSeconds" |
| | | class="tn-countdown__separator" |
| | | :style="{ |
| | | fontSize: separatorSize + 'rpx', |
| | | color: separatorColor, |
| | | paddingBottom: separator === 'en' ? '4rpx' : 0 |
| | | }" |
| | | > |
| | | {{ separator === 'en' ? ':' : 'å'}} |
| | | </view> |
| | | |
| | | <view |
| | | v-if="showSeconds" |
| | | class="tn-countdown__item" |
| | | :class="[backgroundColorClass]" |
| | | :style="[itemStyle]" |
| | | > |
| | | <view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]"> |
| | | {{ s }} |
| | | </view> |
| | | </view> |
| | | <view |
| | | v-if="showSeconds && separator === 'cn'" |
| | | class="tn-countdown__separator" |
| | | :style="{ |
| | | fontSize: separatorSize + 'rpx', |
| | | color: separatorColor, |
| | | paddingBottom: separator === 'en' ? '4rpx' : 0 |
| | | }" |
| | | > |
| | | ç§ |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-count-down', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // åè®¡æ¶æ¶é´ï¼ç§ä½ä¸ºåä½ |
| | | timestamp: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¯å¦èªå¨å¼å§ |
| | | autoplay: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ°åæ¡é«åº¦ |
| | | height: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | }, |
| | | // åé符类å |
| | | // en -> 使ç¨è±æçåå· cn -> 使ç¨ä¸æè¿è¡åå² |
| | | separator: { |
| | | type: String, |
| | | default: 'en' |
| | | }, |
| | | // åå²ç¬¦å¤§å° |
| | | separatorSize: { |
| | | type: Number, |
| | | default: 30 |
| | | }, |
| | | // åé符é¢è² |
| | | separatorColor: { |
| | | type: String, |
| | | default: '#080808' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¾¹æ¡ |
| | | showBorder: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è¾¹æ¡é¢è² |
| | | borderColor: { |
| | | type: String, |
| | | default: '#080808' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºç§ |
| | | showSeconds: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå |
| | | showMinutes: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºæ¶ |
| | | showHours: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå¤© |
| | | showDays: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 妿å½å¤©çé¨å为0æ¶ï¼æ¯å¦éè䏿¾ç¤º |
| | | hideZeroDay: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // å计æ¶itemçæ ·å¼ |
| | | itemStyle() { |
| | | let style = {} |
| | | if (this.height) { |
| | | style.height = this.$t.string.getLengthUnitValue(this.height) |
| | | style.width = style.height |
| | | } |
| | | if (this.showBorder) { |
| | | style.borderStyle = 'solid' |
| | | style.borderColor = this.borderColor |
| | | style.borderWidth = '1rpx' |
| | | } |
| | | style.backgroundColor = this.backgroundColorStyle || '#FFFFFF' |
| | | return style |
| | | }, |
| | | // åè®¡æ¶æ°åæ ·å¼ |
| | | letterStyle() { |
| | | let style = {} |
| | | style.fontSize = this.fontSizeStyle || '30rpx' |
| | | style.color = this.fontColorStyle || '#080808' |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | d: '00', |
| | | h: '00', |
| | | m: '00', |
| | | s: '00', |
| | | // 宿¶å¨ |
| | | timer: null, |
| | | // è®°å½å计è¿ç¨ä¸ååçç§æ° |
| | | seconds: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | // ç嬿¶é´æ³åå |
| | | timestamp(value) { |
| | | this.clearTimer() |
| | | this.start() |
| | | } |
| | | }, |
| | | mounted() { |
| | | // 妿æ¶èªå¨å计æ¶ï¼å è½½å®æå¼å§è®¡æ¶ |
| | | this.autoplay && this.timestamp && this.start() |
| | | }, |
| | | beforeDestroy() { |
| | | this.clearTimer() |
| | | }, |
| | | methods: { |
| | | // å¼å§åè®¡æ¶ |
| | | start() { |
| | | // é¿å
å¯è½åºç°çå计æ¶éå æ
åµ |
| | | this.clearTimer() |
| | | if (this.timestamp <= 0) return |
| | | this.seconds = Number(this.timestamp) |
| | | this.formatTime(this.seconds) |
| | | this.timer = setInterval(() => { |
| | | this.seconds-- |
| | | // ååºchangeäºä»¶ |
| | | this.$emit('change', this.seconds) |
| | | if (this.seconds < 0) { |
| | | return this.end() |
| | | } |
| | | this.formatTime(this.seconds) |
| | | }, 1000) |
| | | }, |
| | | // æ ¼å¼åæ¶é´ |
| | | formatTime(seconds) { |
| | | // å°äºçäº0çè¯ï¼ç»æåè®¡æ¶ |
| | | seconds <= 0 && this.end() |
| | | let [day, hour, minute, second] = [0, 0, 0, 0] |
| | | day = Math.floor(seconds / (60 * 60 * 24)) |
| | | // 妿䏿¾ç¤ºå¤©ï¼åå°å¤©å¯¹åºçå°æ¶è®¡å
¥å°å°æ¶ä¸ |
| | | // å
æå½åçhour计ç®åºæ¥ä¾ååç§ä½¿ç¨ |
| | | hour = Math.floor(seconds / (60 * 60)) - (day * 24) |
| | | let showHour = null |
| | | if (this.showDays) { |
| | | showHour = hour |
| | | } else { |
| | | // å°å¤©æ°å¯¹åºçå°æ¶å å
¥å°æ¶ä¸è¿è¡æ¾ç¤º |
| | | showHour = Math.floor(seconds / (60 * 60)) |
| | | } |
| | | minute = Math.floor(seconds / 60) - (hour * 60) - (day * 24 * 60) |
| | | second = Math.floor(seconds) - (minute * 60) - (hour * 60 * 60) - (day * 24 * 60 * 60) |
| | | // 妿å°äº0å¨åé¢è¿è¡è¡¥0æä½ |
| | | showHour = this.$t.number.formatNumberAddZero(showHour) |
| | | minute = this.$t.number.formatNumberAddZero(minute) |
| | | second = this.$t.number.formatNumberAddZero(second) |
| | | day = this.$t.number.formatNumberAddZero(day) |
| | | |
| | | this.d = day |
| | | this.h = showHour |
| | | this.m = minute |
| | | this.s = second |
| | | }, |
| | | // å计æ¶ç»æ |
| | | end() { |
| | | this.clearTimer() |
| | | this.$emit('end') |
| | | }, |
| | | // æ¸
é¤åè®¡æ¶ |
| | | clearTimer() { |
| | | if (this.timer !== null) { |
| | | clearInterval(this.timer) |
| | | this.timer = null |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-countdown { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | |
| | | &__item { |
| | | box-sizing: content-box; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 2rpx; |
| | | border-radius: 6rpx; |
| | | white-space: nowrap; |
| | | transform: translateZ(0); |
| | | |
| | | &__time { |
| | | margin: 0; |
| | | padding: 0; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | &__separator { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 0 5rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-count-scroll-class tn-count-scroll"> |
| | | <view |
| | | v-for="(item, index) in columns" |
| | | :key="index" |
| | | class="tn-count-scroll__box" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: heightPxValue + 'px' |
| | | }" |
| | | > |
| | | <view |
| | | class="tn-count-scroll__column" |
| | | :style="{ |
| | | transform: `translate3d(0, -${keys[index] * heightPxValue}px, 0)`, |
| | | transitionDuration: `${duration}s` |
| | | }" |
| | | > |
| | | <view |
| | | v-for="(value, value_index) in item" |
| | | :key="value_index" |
| | | class="tn-count-scroll__column__item" |
| | | :class="[fontColorClass]" |
| | | :style="{ |
| | | height: heightPxValue + 'px', |
| | | lineHeight: heightPxValue + 'px', |
| | | fontSize: fontSizeStyle || '32rpx', |
| | | fontWeight: bold ? 'bold': 'normal', |
| | | color: fontColorStyle || '#080808' |
| | | }" |
| | | > |
| | | {{ value }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-count-scroll', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | value: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // è¡é« |
| | | height: { |
| | | type: Number, |
| | | default: 32 |
| | | }, |
| | | // å个åç宽度 |
| | | width: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | }, |
| | | // æ¯å¦å ç² |
| | | bold: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æç»æ¶é´ |
| | | duration: { |
| | | type: Number, |
| | | default: 1.2 |
| | | }, |
| | | // ååä½åå²ç¬¦ |
| | | decimalSeparator: { |
| | | type: String, |
| | | default: '.' |
| | | }, |
| | | // ååä½åå²ç¬¦ |
| | | thousandthsSeparator: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | heightPxValue() { |
| | | return uni.upx2px(this.height || 0) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ¯åçæ°æ® |
| | | columns: [], |
| | | // æ¯å对åºå¼æå¨çæ»å¨ä½ç½® |
| | | keys: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | this.initColumn(val) |
| | | } |
| | | }, |
| | | created() { |
| | | // 为äºè¾¾å°ä¸è¿å
¥å°±ææ»å¨ææï¼å»¶è¿æ§è¡åå§å |
| | | this.initColumn() |
| | | setTimeout(() => { |
| | | this.initColumn(this.value) |
| | | }, 20) |
| | | }, |
| | | methods: { |
| | | // åå§åæ¯ä¸åçæ°æ® |
| | | initColumn(val) { |
| | | val = val + '' |
| | | let digit = val.length, |
| | | columnArray = [], |
| | | rows = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; |
| | | for (let i = 0; i < digit; i++) { |
| | | if (val[i] === this.decimalSeparator || val[i] === this.thousandthsSeparator) { |
| | | columnArray.push(val[i]) |
| | | } else { |
| | | columnArray.push(rows) |
| | | } |
| | | } |
| | | this.columns = columnArray |
| | | this.roll(val) |
| | | }, |
| | | // æ»å¨å¤ç |
| | | roll(value) { |
| | | let valueArray = value.toString().split(''), |
| | | lengths = this.columns.length, |
| | | indexs = []; |
| | | |
| | | while (valueArray.length) { |
| | | let figure = valueArray.pop() |
| | | if (figure === this.decimalSeparator || figure === this.thousandthsSeparator) { |
| | | indexs.unshift(0) |
| | | } else { |
| | | indexs.unshift(Number(figure)) |
| | | } |
| | | } |
| | | while(indexs.length < lengths) { |
| | | indexs.unshift(0) |
| | | } |
| | | this.keys = indexs |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-count-scroll { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | |
| | | &__box { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &__column { |
| | | transform: translate3d(0, 0, 0); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-direction: column; |
| | | transition-timing-function: cubic-bezier(0, 1, 0, 1); |
| | | |
| | | &__item { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-count-num-class tn-count-num" |
| | | :class="[fontColorClass]" |
| | | :style="{ |
| | | fontSize: fontSizeStyle || '50rpx', |
| | | fontWeight: bold ? 'bold' : 'normal', |
| | | color: fontColorStyle || '#080808' |
| | | }" |
| | | > |
| | | {{ displayValue }} |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-count-to', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // å¼å§çæ°å¼ï¼é»è®¤ä¸º0 |
| | | startVal: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // ç»æç®æ æ°å¼ |
| | | endVal: { |
| | | type: Number, |
| | | default: 0, |
| | | required: true |
| | | }, |
| | | // æ¯å¦èªå¨å¼å§ |
| | | autoplay: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ»å¨å°ç®æ å¼çæç»æ¶é´ï¼åä½ä¸ºæ¯«ç§ |
| | | duration: { |
| | | type: Number, |
| | | default: 2000 |
| | | }, |
| | | // æ¯å¦å¨å³å°ç»æçæ¶å使ç¨ç¼æ
¢æ»å¨çææ |
| | | useEasing: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¾ç¤ºçå°æ°ä½æ° |
| | | decimals: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // åè¿å¶çåå²ç¬¦ |
| | | decimalSeparator: { |
| | | type: String, |
| | | default: '.' |
| | | }, |
| | | // ååä½çåé符 |
| | | // 类似éé¢çåå²(ï¿¥23,321.05ä¸ç",") |
| | | thousandthsSeparator: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå ç²åä½ |
| | | bold: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | countDown() { |
| | | return this.startVal > this.endVal |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | localStartVal: this.startVal, |
| | | localDuration: this.duration, |
| | | // æ¾ç¤ºçæ°å¼ |
| | | displayValue: this.formatNumber(this.startVal), |
| | | // æå°çæ°å¼ |
| | | printValue: null, |
| | | // æ¯å¦æå |
| | | paused: false, |
| | | // å¼å§æ¶é´æ³ |
| | | startTime: null, |
| | | // åçæ¶é´æ³ |
| | | remainingTime: null, |
| | | // å½åæ¶é´æ³ |
| | | timestamp: null, |
| | | // ä¸ä¸æ¬¡çæ¶é´æ³ |
| | | lastTime: 0, |
| | | rAF: null |
| | | } |
| | | }, |
| | | watch: { |
| | | startVal() { |
| | | this.autoplay && this.start() |
| | | }, |
| | | endVal() { |
| | | this.autoplay && this.start() |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.autoplay && this.start() |
| | | }, |
| | | methods: { |
| | | // å¼å§æ»å¨ |
| | | start() { |
| | | this.localStartVal = this.startVal |
| | | this.startTime = null |
| | | this.localDuration = this.duration |
| | | this.paused = false |
| | | this.rAF = this.requestAnimationFrame(this.count) |
| | | }, |
| | | // éæ°å¼å§ |
| | | reStart() { |
| | | if (this.paused) { |
| | | this.resume() |
| | | this.paused = false |
| | | } else { |
| | | this.stop() |
| | | this.paused = true |
| | | } |
| | | }, |
| | | // 忢 |
| | | stop() { |
| | | this.cancelAnimationFrame(this.rAF) |
| | | }, |
| | | // æ¢å¤ |
| | | resume() { |
| | | this.startTime = null |
| | | this.localDuration = this.remainingTime |
| | | this.localStartVal = this.printValue |
| | | this.requestAnimationFrame(this.count) |
| | | }, |
| | | // éç½® |
| | | reset() { |
| | | this.startTime = null |
| | | this.cnacelAnimationFrame(this.rAF) |
| | | this.displayValue = this.formatNumber(this.startVal) |
| | | }, |
| | | // 鿝ç»ä»¶ |
| | | destroyed() { |
| | | this.cancelAnimationFrame(this.rAF) |
| | | }, |
| | | // ç´¯å æ¶é´ |
| | | count(timestamp) { |
| | | if (!this.startTime) this.startTime = timestamp |
| | | this.timestamp = timestamp |
| | | const progress = timestamp - this.startTime |
| | | this.remainingTime = this.localDuration - progress |
| | | if (this.useEasing) { |
| | | if (this.countDown) { |
| | | this.printValue = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration) |
| | | } { |
| | | this.printValue = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration) |
| | | } |
| | | } else { |
| | | if (this.countDown) { |
| | | this.printValue = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration) |
| | | } else { |
| | | this.printValue = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration) |
| | | } |
| | | } |
| | | if (this.countDown) { |
| | | this.printValue = this.printValue < this.endVal ? this.endVal : this.printValue |
| | | } else { |
| | | this.printValue = this.printValue > this.endVal ? this.endVal : this.printValue |
| | | } |
| | | |
| | | this.displayValue = this.formatNumber(this.printValue) |
| | | if (progress < this.localDuration) { |
| | | this.rAF = this.requestAnimationFrame(this.count) |
| | | } else { |
| | | this.$emit('end') |
| | | } |
| | | }, |
| | | // ç¼å¨æ¶é´è®¡ç® |
| | | easingFn(t, b, c, d) { |
| | | return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b |
| | | }, |
| | | // 请æ±å¸§å¨ç» |
| | | requestAnimationFrame(cb) { |
| | | const currentTime = new Date().getTime() |
| | | // 为äºä½¿setTimteoutçå°½å¯è½çæ¥è¿æ¯ç§60å¸§çææ |
| | | const timeToCall = Math.max(0, 16 - (currentTime - this.lastTime)) |
| | | const timerId = setTimeout(() => { |
| | | cb && cb(currentTime + timeToCall) |
| | | }, timeToCall) |
| | | this.lastTime = currentTime + timeToCall |
| | | return timerId |
| | | }, |
| | | // æ¸
é¤å¸§å¨ç» |
| | | clearAnimationFrame(timerId) { |
| | | clearTimeout(timerId) |
| | | }, |
| | | // æ ¼å¼åæ°å¼ |
| | | formatNumber(number) { |
| | | const reg = /(\d+)(\d{3})/ |
| | | number = Number(number) |
| | | number = number.toFixed(Number(this.decimals)) |
| | | number += '' |
| | | const numberArray = number.split('.') |
| | | let num1 = numberArray[0] |
| | | const num2 = numberArray.length > 1 ? this.decimalSeparator + numberArray[1] : '' |
| | | |
| | | if (this.thousandthsSeparator && !this.isNumber(this.thousandthsSeparator)) { |
| | | while(reg.test(num1)) { |
| | | num1 = num1.replace(reg, '$1' + this.thousandthsSeparator + '$2') |
| | | } |
| | | } |
| | | return num1 + num2 |
| | | }, |
| | | // 夿æ¯å¦ä¸ºæ°å |
| | | isNumber(val) { |
| | | return !isNaN(parseFloat(val)) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-count-num { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | text-align: center; |
| | | line-height: 1; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | var cropper = { |
| | | // ç»å¸xè½´èµ·ç¹ |
| | | cutX: 0, |
| | | // ç»å¸yè½´èµ·ç¹ |
| | | cutY: 0, |
| | | // 触æ¸ç¹ä¿¡æ¯(ææä¸å¾çä¸å¿ç¹çç¸å¯¹ä½ç½®) |
| | | touchRelactive: [{ |
| | | x: 0, |
| | | y: 0 |
| | | }], |
| | | // åæè§¦æ¸æ¶æè¾¹çé¿åº¦ |
| | | hypotenuseLength:0, |
| | | // æ¯å¦ç»æè§¦æ¸ |
| | | touchEndFlag: false, |
| | | // ç»å¸å®½é« |
| | | canvasWidth: 0, |
| | | canvasHeight: 0, |
| | | // å¾çå®½é« |
| | | imgWidth: 0, |
| | | imgHeight: 0, |
| | | // å¾çç¼©æ¾æ¯ä¾ |
| | | scale: 1, |
| | | // å¾çæè½¬è§åº¦ |
| | | angle: 0, |
| | | // å¾çä¸è¾¹è· |
| | | imgTop: 0, |
| | | // å¾çå·¦è¾¹è· |
| | | imgLeft: 0, |
| | | // çªå£å®½é« |
| | | windowWidth: 0, |
| | | windowHeight: 0, |
| | | init: true |
| | | } |
| | | |
| | | function bool(str) { |
| | | return str === 'true' || str === true |
| | | } |
| | | |
| | | function propsChange(prop, oldProp, ownerInstance, instance) { |
| | | if (prop && prop !== 'null') { |
| | | var params = prop.split(',') |
| | | var type = +params[0] |
| | | var dataset = instance.getDataset() |
| | | if (cropper.init || type == 4) { |
| | | cropper.canvasWidth = +dataset.width |
| | | cropper.canvasHeight = +dataset.height |
| | | cropper.imgTop = +dataset.windowheight / 2 |
| | | cropper.imgLeft = +dataset.windowwidth / 2 |
| | | cropper.imgWidth = +dataset.imgwidth |
| | | cropper.imgHeight = +dataset.imgheight |
| | | cropper.windowHeight = +dataset.windowheight |
| | | cropper.windowWidth = +dataset.windowwidth |
| | | cropper.init = false |
| | | } else if (type == 2 || type == 3) { |
| | | cropper.imgWidth = +dataset.imgwidth |
| | | cropper.imgHeight = +dataset.imgheight |
| | | } |
| | | cropper.angle = +dataset.angle |
| | | if (type == 3) { |
| | | imgTransform(ownerInstance) |
| | | } |
| | | switch(type) { |
| | | case 1: |
| | | setCutCenter(ownerInstance) |
| | | // 设置è£åªæ¡å¤§å° |
| | | computeCutSize(ownerInstance) |
| | | // æ£æ¥è£åªæ¡æ¯å¦å¨èå´å
|
| | | cutDetectionPosition(ownerInstance) |
| | | break |
| | | case 2: |
| | | setCutCenter(ownerInstance) |
| | | break |
| | | case 3: |
| | | imgMarginDetectionScale(ownerInstance) |
| | | break |
| | | case 4: |
| | | imageReset(ownerInstance) |
| | | break |
| | | case 5: |
| | | setCutCenter(ownerInstance) |
| | | break |
| | | default: |
| | | break |
| | | } |
| | | } |
| | | } |
| | | |
| | | function touchStart(event, ownerInstance) { |
| | | var touch = event.touches || event.changedTouches |
| | | cropper.touchEndFlag = false |
| | | if (touch.length === 1) { |
| | | cropper.touchRelactive[0] = { |
| | | x: touch[0].pageX - cropper.imgLeft, |
| | | y: touch[0].pageY - cropper.imgTop |
| | | } |
| | | } else { |
| | | var width = Math.abs(touch[0].pageX - touch[1].pageX) |
| | | var height = Math.abs(touch[0].pageY - touch[1].pageY) |
| | | cropper.touchRelactive = [{ |
| | | x: touch[0].pageX - cropper.imgLeft, |
| | | y: touch[0].pageY - cropper.imgTop |
| | | },{ |
| | | x: touch[1].pageX - cropper.imgLeft, |
| | | y: touch[1].pageY - cropper.imgTop |
| | | }] |
| | | cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) |
| | | } |
| | | } |
| | | |
| | | function touchMove(event, ownerInstance) { |
| | | var touch = event.touches || event.changedTouches |
| | | if (cropper.touchEndFlag) return |
| | | moveDuring(ownerInstance) |
| | | if (event.touches.length === 1) { |
| | | var left = touch[0].pageX - cropper.touchRelactive[0].x, |
| | | top = touch[0].pageY - cropper.touchRelactive[0].y; |
| | | cropper.imgLeft = left |
| | | cropper.imgTop = top |
| | | imgTransform(ownerInstance) |
| | | imgMarginDetectionPosition(ownerInstance) |
| | | } else { |
| | | var dataset = event.instance.getDataset() |
| | | var minScale = +dataset.minscale |
| | | var maxScale = +dataset.maxscale |
| | | var width = Math.abs(touch[0].pageX - touch[1].pageX), |
| | | height = Math.abs(touch[0].pageY - touch[1].pageY), |
| | | hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)), |
| | | scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength), |
| | | current_deg = 0; |
| | | scale = scale <= minScale ? minScale : scale |
| | | scale = scale >= maxScale ? maxScale : scale |
| | | cropper.scale = scale |
| | | imgMarginDetectionScale(ownerInstance, true) |
| | | var touchRelative = [{ |
| | | x: touch[0].pageX - cropper.imgLeft, |
| | | y: touch[0].pageY - cropper.imgTop |
| | | }, { |
| | | x: touch[1].pageX - cropper.imgLeft, |
| | | y: touch[1].pageY - cropper.imgTop |
| | | }] |
| | | cropper.touchRelactive = touchRelative |
| | | cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) |
| | | // æ´æ°è§å¾ |
| | | cropper.angle = cropper.angle + current_deg |
| | | imgTransform(ownerInstance) |
| | | } |
| | | } |
| | | |
| | | function touchEnd(event, ownerInstance) { |
| | | cropper.touchEndFlag = true |
| | | moveStop(ownerInstance) |
| | | updateData(ownerInstance) |
| | | } |
| | | |
| | | function moveDuring(ownerInstance) { |
| | | if (!ownerInstance) return |
| | | ownerInstance.callMethod('moveDuring') |
| | | } |
| | | |
| | | function moveStop(ownerInstance) { |
| | | if (!ownerInstance) return |
| | | ownerInstance.callMethod('moveStop') |
| | | } |
| | | |
| | | function setCutCenter(ownerInstance) { |
| | | var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5 |
| | | var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5 |
| | | |
| | | cropper.imgTop = cropper.imgTop - cropper.cutY + cutY |
| | | cropper.cutY = cutY |
| | | cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX |
| | | cropper.cutX = cutX |
| | | cutDetectionPosition(ownerInstance) |
| | | imgTransform(ownerInstance) |
| | | updateData(ownerInstance) |
| | | } |
| | | |
| | | // æ£æµåªè£æ¡ä½ç½®æ¯å¦å¨å
许çèå´å
ï¼å±å¹å
ï¼ |
| | | function cutDetectionPosition(ownerInstance) { |
| | | var windowHeight = cropper.windowHeight, |
| | | windowWidth = cropper.windowWidth; |
| | | |
| | | // æ£æµä¸è¾¹è·æ¯å¦å¨èå´å
|
| | | var cutDetectionPositionTop = function() { |
| | | if (cropper.cutY < 0) { |
| | | cropper.cutY = 0 |
| | | } |
| | | if (cropper.cutY > windowHeight - cropper.canvasHeight) { |
| | | cropper.cutY = windowHeight - cropper.canvasHeight |
| | | } |
| | | } |
| | | |
| | | // æ£æµå·¦è¾¹è·æ¯å¦å¨èå´å
|
| | | var cutDetectionPositionLeft = function() { |
| | | if (cropper.cutX < 0) { |
| | | cropper.cutX = 0 |
| | | } |
| | | if (cropper.cutX > windowWidth - cropper.canvasWidth) { |
| | | cropper.cutX = windowWidth - cropper.canvasWidth |
| | | } |
| | | } |
| | | |
| | | // è£åªæ¡åæ å¤çï¼å¦æåªåä¸ä¸ªåæ°åå¦ä¸ä¸ªé»è®¤ä¸º0ï¼é½ä¸åé»è®¤ä¸ºå±
ä¸ï¼ |
| | | if (cropper.cutX === null && cropper.cutY === null) { |
| | | var cutX = (windowWidth - cropper.canvasWidth) * 0.5, |
| | | cutY = (windowHeight - cropper.canvasHeight) * 0.5; |
| | | cropper.cutX = cutX |
| | | cropper.cutY = cutY |
| | | } else if (cropper.cutX !== null && cropper.cutX !== null) { |
| | | cutDetectionPositionTop() |
| | | cutDetectionPositionLeft() |
| | | } else if (cropper.cutX !== null && cropper.cutY === null) { |
| | | cutDetectionPositionLeft() |
| | | cropper.cutY = (windowHeight - cropper.canvasHeight) / 2 |
| | | } else if (cropper.cutX === null && cropper.cutY !== null) { |
| | | cutDetectionPositionTop() |
| | | cropper.cutX = (windowWidth - cropper.canvasWidth) / 2 |
| | | } |
| | | } |
| | | |
| | | // å¾çè¾¹ç¼æ£æµ-ç¼©æ¾ |
| | | function imgMarginDetectionScale(ownerInstance, delay) { |
| | | var scale = cropper.scale, |
| | | imgWidth = cropper.imgWidth, |
| | | imgHeight = cropper.imgHeight; |
| | | if ((cropper.angle / 90) % 2) { |
| | | imgWidth = cropper.imgHeight |
| | | imgHeight = cropper.imgWidth |
| | | } |
| | | if (imgWidth * scale < cropper.canvasWidth) { |
| | | scale = cropper.canvasWidth / imgWidth |
| | | } |
| | | if (imgHeight * scale < cropper.canvasHeight) { |
| | | scale = Math.max(scale, cropper.canvasHeight / imgHeight) |
| | | } |
| | | imgMarginDetectionPosition(ownerInstance, scale, delay) |
| | | } |
| | | |
| | | // å¾çè¾¹ç¼æ£æµ-ä½ç½® |
| | | function imgMarginDetectionPosition(ownerInstance, scale, delay) { |
| | | var left = cropper.imgLeft, |
| | | top = cropper.imgTop, |
| | | imgWidth = cropper.imgWidth, |
| | | imgHeight = cropper.imgHeight; |
| | | scale = scale || cropper.scale |
| | | if ((cropper.angle / 90) % 2) { |
| | | imgWidth = cropper.imgHeight |
| | | imgHeight = cropper.imgWidth |
| | | } |
| | | |
| | | left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2 |
| | | left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 |
| | | top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2 |
| | | top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 |
| | | |
| | | cropper.imgLeft = left |
| | | cropper.imgTop = top |
| | | cropper.scale = scale |
| | | if (!delay || delay === 'null') { |
| | | imgTransform(ownerInstance) |
| | | } |
| | | } |
| | | |
| | | // æ¹åæªåå¼å¤§å° |
| | | function computeCutSize(ownerInstance) { |
| | | if (cropper.canvasWidth > cropper.windowWidth) { |
| | | cropper.canvasWidth = cropper.windowWidth |
| | | } else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) { |
| | | cropper.cutX = cropper.windowWidth - cropper.cutX |
| | | } |
| | | if (cropper.canvasHeight > cropper.windowHeight) { |
| | | cropper.canvasHeight = cropper.windowHeight |
| | | } else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) { |
| | | cropper.cutY = cropper.windowHeight - cropper.cutY |
| | | } |
| | | } |
| | | |
| | | // å¾çå¨ç» |
| | | function imgTransform(ownerInstance) { |
| | | var image = ownerInstance.selectComponent('.tn-cropper__image') |
| | | if (!image) return |
| | | var x = cropper.imgLeft - cropper.imgWidth / 2, |
| | | y = cropper.imgTop - cropper.imgHeight / 2; |
| | | image.setStyle({ |
| | | 'transform': 'translate3d('+ x + 'px,' + y + 'px,0) scale(' + cropper.scale +') rotate(' + cropper.angle + 'deg)' |
| | | }) |
| | | } |
| | | |
| | | // å¾çéç½® |
| | | function imageReset(ownerInstance) { |
| | | cropper.scale = 1 |
| | | cropper.angle = 0 |
| | | imgTransform(ownerInstance) |
| | | } |
| | | |
| | | // é«åº¦åå |
| | | function canvasHeight(ownerInstance) { |
| | | if (!ownerInstance) return |
| | | computeCutSize(ownerInstance) |
| | | } |
| | | |
| | | // 宽度åå |
| | | function canvasWidth(ownerInstance) { |
| | | if (!ownerInstance) return |
| | | computeCutSize(ownerInstance) |
| | | } |
| | | |
| | | // æ´æ°æ°æ® |
| | | function updateData(ownerInstance) { |
| | | if (!ownerInstance) return |
| | | ownerInstance.callMethod('change', { |
| | | cutX: cropper.cutX, |
| | | cutY: cropper.cutY, |
| | | imgWidth: cropper.imgWidth, |
| | | imgHeight: cropper.imgHeight, |
| | | scale: cropper.scale, |
| | | angle: cropper.angle, |
| | | imgTop: cropper.imgTop, |
| | | imgLeft: cropper.imgLeft |
| | | }) |
| | | } |
| | | |
| | | module.exports = { |
| | | touchStart: touchStart, |
| | | touchMove: touchMove, |
| | | touchEnd: touchEnd, |
| | | propsChange: propsChange |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-cropper-class tn-cropper" @touchmove.stop.prevent="stop"> |
| | | <image |
| | | v-if="imageUrl" |
| | | :src="imageUrl" |
| | | class="tn-cropper__image" |
| | | :style="{ |
| | | width: (imgWidth ? imgWidth : width) + 'px', |
| | | height: (imgHeight ? imgHeight : height) + 'px', |
| | | transitionDuration: (animation ? 0.3 : 0) + 's' |
| | | }" |
| | | mode="widthFix" |
| | | :data-minScale="minScale" |
| | | :data-maxScale="maxScale" |
| | | @load="imageLoad" |
| | | @error="imageLoad" |
| | | @touchstart="wxs.touchStart" |
| | | @touchmove="wxs.touchMove" |
| | | @touchend="wxs.touchEnd" |
| | | ></image> |
| | | |
| | | <view |
| | | class="tn-cropper__wrapper" |
| | | :style="{ |
| | | width: width + 'px', |
| | | height: height + 'px', |
| | | borderRadius: isRound ? '50%' : '0' |
| | | }" |
| | | > |
| | | <view |
| | | class="tn-cropper__border" |
| | | :style="{ |
| | | border: borderStyle, |
| | | borderRadius: isRound ? '50%' : '0', |
| | | }" |
| | | :prop="props" |
| | | :change:prop="wxs.propsChange" |
| | | :data-width="width" |
| | | :data-height="height" |
| | | :data-windowHeight="systemInfo.windowHeight || 600" |
| | | :data-windowWidth="systemInfo.windowWidth || 400" |
| | | :data-imgTop="imgTop" |
| | | :data-imgWidth="imgWidth" |
| | | :data-imgHeight="imgHeight" |
| | | :data-angle="angle" |
| | | ></view> |
| | | </view> |
| | | |
| | | <canvas |
| | | class="tn-cropper__canvas" |
| | | :style="{ |
| | | width: width * scaleRatio + 'px', |
| | | height: height * scaleRatio + 'px' |
| | | }" |
| | | :canvas-id="CANVAS_ID" |
| | | :id="CANVAS_ID" |
| | | :disable-scroll="true" |
| | | ></canvas> |
| | | |
| | | <view |
| | | v-if="!custom" |
| | | class="tn-cropper__tabbar" |
| | | > |
| | | <view class="tn-cropper__tabbar__btn tn-cropper__tabber__cancel" @tap.stop="back">åæ¶</view> |
| | | <view class="tn-cropper__tabbar__rotate" :class="[`tn-icon-${rotateIcon}`]" @tap.stop="setAngle"></view> |
| | | <view class="tn-cropper__tabbar__btn tn-cropper__tabber__confirm" @tap.stop="getCutImage">宿</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script src="./index.wxs" lang="wxs" module="wxs"></script> |
| | | <script> |
| | | export default { |
| | | name: 'tn-cropper', |
| | | props: { |
| | | // å¾çè·¯å¾ |
| | | imageUrl: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // è£åªæ¡é«åº¦ px |
| | | height: { |
| | | type: Number, |
| | | default: 280 |
| | | }, |
| | | // è£åªæ¡ç宽度 px |
| | | width: { |
| | | type: Number, |
| | | default: 280 |
| | | }, |
| | | // æ¯å¦ä¸ºåå½¢è£åªæ¡ |
| | | isRound: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è£åªæ¡è¾¹æ¡æ ·å¼ |
| | | borderStyle: { |
| | | type: String, |
| | | default: '1rpx solid #FFF' |
| | | }, |
| | | // çæçå¾ç尺寸ç¸å¯¹äºè£åªæ¡çæ¯ä¾ |
| | | scaleRatio: { |
| | | type: Number, |
| | | default: 1 |
| | | }, |
| | | // è£åªåçå¾çè´¨é |
| | | // åå¼èå´ä¸ºï¼(0, 1] |
| | | quality: { |
| | | type: Number, |
| | | default: 0.8 |
| | | }, |
| | | // æ¯å¦è¿åbase64(H5é»è®¤ä¸ºbase64) |
| | | returnBase64: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¾çæè½¬è§åº¦ |
| | | rotateAngle: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å¾çæå°ç¼©æ¾æ¯ |
| | | minScale: { |
| | | type: Number, |
| | | default: 0.5 |
| | | }, |
| | | // å¾çæå¤§ç¼©æ¾æ¯ |
| | | maxScale: { |
| | | type: Number, |
| | | default: 2 |
| | | }, |
| | | // èªå®ä¹æä½æ (设置åä¼éèé»è®¤çåºé¨æä½æ ) |
| | | custom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¨å¼åçæ¹åçæ¶åå¼å§è£åª |
| | | // custom为trueæ¶çæ |
| | | startCutting: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è£åªæ¶æ¯å¦æ¾ç¤ºloading |
| | | loading: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æè½¬å¾ç徿 |
| | | rotateIcon: { |
| | | type: String, |
| | | default: 'circle-arrow' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // canvas容å¨id |
| | | CANVAS_ID: 'tn-cropper-canvas', |
| | | // ç§»å¨è£åªè¶
æ¶æ¶é´å®æ¶å¨ |
| | | TIME_CUT_CENTER: null, |
| | | // canvaså®¹å¨ |
| | | ctx: null, |
| | | // ç»å¸xè½´èµ·ç¹ |
| | | cutX: 0, |
| | | // ç»å¸yè½´èµ·ç¹ |
| | | cutY: 0, |
| | | // å¾ç宽度 |
| | | imgWidth: 0, |
| | | // å¾çé«åº¦ |
| | | imgHeight: 0, |
| | | // å¾çåºé¨ä½ç½® |
| | | imgTop: 0, |
| | | // å¾ç左边ä½ç½® |
| | | imgLeft: 0, |
| | | // å¾çç¼©æ¾æ¯ |
| | | scale: 1, |
| | | // å¾çæè½¬è§åº¦ |
| | | angle: 0, |
| | | // å¼å¯å¨ç»è¿æ¸¡ææ |
| | | animation: false, |
| | | // å¨ç»å®æ¶å¨ |
| | | animationTime: null, |
| | | // ç³»ç»ä¿¡æ¯ |
| | | systemInfo: {}, |
| | | // ä¼ éçåæ° |
| | | props: '', |
| | | // æ è®°æ¯å¦åçæ¹å |
| | | sizeChange: 0, |
| | | angleChange: 0, |
| | | resetChange: 0, |
| | | centerChange: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | imageUrl(val) { |
| | | this.imageReset() |
| | | this.showLoading() |
| | | uni.getImageInfo({ |
| | | src: val, |
| | | success: (res) => { |
| | | // 计ç®å¾ç尺寸 |
| | | this.imgComputeSize(res.width, res.height) |
| | | this.angleChange++ |
| | | this.props = `3,${this.angleChange}` |
| | | }, |
| | | fail: (err) => { |
| | | console.log(err); |
| | | this.imgComputeSize() |
| | | this.angleChange++ |
| | | this.props = `3,${this.angleChange}` |
| | | } |
| | | }) |
| | | }, |
| | | rotateAngle(val) { |
| | | this.animation = true |
| | | this.angle = val |
| | | this.angleChanged(val) |
| | | }, |
| | | animation(val) { |
| | | clearTimeout(this.animationTime) |
| | | if (val) { |
| | | this.animationTime = setTimeout(() => { |
| | | this.animation = false |
| | | }, 200) |
| | | } |
| | | }, |
| | | startCutting(val) { |
| | | if (this.custom && val) { |
| | | this.getCutImage() |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.systemInfo = uni.getSystemInfoSync() |
| | | this.imgTop = this.systemInfo.windowHeight / 2 |
| | | this.imgLeft = this.systemInfo.windowWidth / 2 |
| | | this.ctx = uni.createCanvasContext(this.CANVAS_ID, this) |
| | | // åå§å |
| | | this.$nextTick(() => { |
| | | this.props = '1,1' |
| | | }) |
| | | setTimeout(() => { |
| | | this.$emit('ready', {}) |
| | | }, 200) |
| | | }, |
| | | methods: { |
| | | // å°ç½ç»å¾ç转æ¢ä¸ºæ¬å°å¾çã忥æ§è¡ã |
| | | async getLocalImage(url) { |
| | | return await new Promise((resolve, reject) => { |
| | | uni.downloadFile({ |
| | | url: url, |
| | | success: (res) => { |
| | | resolve(res.tempFilePath) |
| | | }, |
| | | fail: (err) => { |
| | | reject(false) |
| | | } |
| | | }) |
| | | }) |
| | | }, |
| | | // è¿åè£åªåçå¾çä¿¡æ¯ |
| | | getCutImage() { |
| | | if (!this.imageUrl) { |
| | | uni.showToast({ |
| | | title: 'è¯·éæ©å¾ç', |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | this.loading && this.showLoading() |
| | | const draw = async () => { |
| | | // å¾çå®é
å¤§å° |
| | | let imgWidth = this.imgWidth * this.scale * this.scaleRatio |
| | | let imgHeight = this.imgHeight * this.scale * this.scaleRatio |
| | | // canvasåå¾ççç¸å¯¹è·ç¦» |
| | | let xpos = this.imgLeft - this.cutX |
| | | let ypos = this.imgTop - this.cutY |
| | | |
| | | |
| | | let imgUrl = this.imageUrl |
| | | // #ifdef APP-PLUS || MP-WEIXIN |
| | | if (~this.imageUrl.indexOf('https:')) { |
| | | imgUrl = await this.getLocalImage(this.imageUrl) |
| | | } |
| | | // #endif |
| | | // æè½¬ç»å¸ |
| | | this.ctx.translate(xpos * this.scaleRatio, ypos * this.scaleRatio) |
| | | // 妿æ¶åå½¢åæªååå½¢ |
| | | if (this.isRound) { |
| | | const r = this.width > this.height ? Math.floor(this.height / 2) : Math.floor(this.width / 2) |
| | | let translateX = Math.floor(this.width / 2) |
| | | let translateY = Math.floor(this.height / 2) |
| | | this.ctx.beginPath() |
| | | this.ctx.arc(translateX - (xpos * this.scaleRatio), translateY - (ypos * this.scaleRatio), r, 0, (360 * Math.PI) / 180) |
| | | this.ctx.closePath() |
| | | this.ctx.stroke() |
| | | this.ctx.clip() |
| | | } |
| | | |
| | | this.ctx.rotate((this.angle * Math.PI) / 180) |
| | | this.ctx.drawImage(imgUrl, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight) |
| | | |
| | | // æ¸
空ååç»§ç»ç»å¶ |
| | | this.ctx.draw(false, () => { |
| | | let params = { |
| | | width: this.width * this.scaleRatio, |
| | | height: Math.round(this.height * this.scaleRatio), |
| | | destWidth: this.width * this.scaleRatio, |
| | | destHeight: Math.round(this.height) * this.scaleRatio, |
| | | fileType: 'png', |
| | | quality: this.quality |
| | | } |
| | | let data = { |
| | | url: '', |
| | | base64: '', |
| | | width: this.width * this.scaleRatio, |
| | | height: this.height * this.scaleRatio |
| | | } |
| | | |
| | | // #ifdef MP-ALIPAY |
| | | if (this.returnBase64) { |
| | | this.ctx.toDataURL(params).then((urlData) => { |
| | | data.base64 = urlData |
| | | this.loading && uni.hideLoading() |
| | | this.$emit('cropper', data) |
| | | }) |
| | | } else { |
| | | this.ctx.toTempFilePath({ |
| | | ...params, |
| | | success: (res) => { |
| | | data.url = res.apFilePath |
| | | this.loading && uni.hideLoading() |
| | | this.$emit('cropper', data) |
| | | } |
| | | }) |
| | | } |
| | | // #endif |
| | | |
| | | let base64Flag = this.returnBase64 |
| | | // #ifndef MP-ALIPAY |
| | | // #ifdef MP-BAIDU || MP-TOUTIAO || H5 |
| | | base64Flag = false |
| | | // #endif |
| | | |
| | | if (base64Flag) { |
| | | uni.canvasGetImageData({ |
| | | canvasId: this.CANVAS_ID, |
| | | x: 0, |
| | | y: 0, |
| | | width: this.width * this.scaleRatio, |
| | | height: Math.round(this.height * this.scaleRatio), |
| | | success: (res) => { |
| | | const arrayBuffer = new Uint8Array(res.data) |
| | | const base64 = uni.arrayBufferToBase64(arrayBuffer) |
| | | data.base64 = base64 |
| | | this.loading && uni.hideLoading() |
| | | this.$emit('cropper', data) |
| | | } |
| | | }, this) |
| | | } else { |
| | | uni.canvasToTempFilePath({ |
| | | ...params, |
| | | canvasId: this.CANVAS_ID, |
| | | success: (res) => { |
| | | data.url = res.tempFilePath |
| | | // #ifdef H5 |
| | | data.base64 = res.tempFilePath |
| | | // #endif |
| | | this.loading && uni.hideLoading() |
| | | this.$emit('cropper', data) |
| | | } |
| | | }, this) |
| | | } |
| | | // #endif |
| | | }) |
| | | } |
| | | draw() |
| | | }, |
| | | // ä¿®æ¹å¾çå触åç彿° |
| | | change(e) { |
| | | this.cutX = e.cutX || 0 |
| | | this.cutY = e.cutY || 0 |
| | | this.imgWidth = e.imgWidth || this.imgWidth |
| | | this.imgHeight = e.imgHeight || this.imgHeight |
| | | this.scale = e.scale || 1 |
| | | this.angle = e.angle || 0 |
| | | this.imgTop = e.imgTop || 0 |
| | | this.imgLeft = e.imgLeft || 0 |
| | | }, |
| | | // éç½®å¾ç |
| | | imageReset() { |
| | | this.scale = 1 |
| | | this.angle = 0 |
| | | let systemInfo = this.systemInfo.windowHeight ? this.systemInfo : uni.getSystemInfoSync() |
| | | this.imgTop = systemInfo.windowHeight / 2 |
| | | this.imgLeft = systemInfo.windowWidth / 2 |
| | | this.resetChange++ |
| | | this.props = `4,${this.resetChange}` |
| | | // åå§æè½¬è§åº¦ |
| | | this.$emit('initAngle', {}) |
| | | }, |
| | | // å¾çççæç尺寸 |
| | | imgComputeSize(width, height) { |
| | | // é»è®¤æå¾ççæå°è¾¹ = 对åºçè£åªæ¡å°ºå¯¸ |
| | | let imgWidth = width, |
| | | imgHeight = height; |
| | | if (imgWidth && imgHeight) { |
| | | if (imgWidth / imgHeight > this.width / this.height) { |
| | | imgHeight = this.height |
| | | imgWidth = (width / height) * imgHeight |
| | | } else { |
| | | imgWidth = this.width |
| | | imgHeight = (height / width) * imgWidth |
| | | } |
| | | } else { |
| | | let systemInfo = this.systemInfo.windowHeight ? this.systemInfo : uni.getSystemInfoSync() |
| | | imgWidth = systemInfo.windowWidth |
| | | imgHeight = 0 |
| | | } |
| | | this.imgWidth = imgWidth |
| | | this.imgHeight = imgHeight |
| | | this.sizeChange++ |
| | | this.props = `2,${this.sizeChange}` |
| | | }, |
| | | // å¾çå è½½å®æ¯ |
| | | imageLoad(e) { |
| | | this.imageReset() |
| | | uni.hideLoading() |
| | | this.$emit('imageLoad', {}) |
| | | }, |
| | | // ç§»å¨ç»æ |
| | | moveStop() { |
| | | clearTimeout(this.TIME_CUT_CENTER) |
| | | this.TIME_CUT_CENTER = setTimeout(() => { |
| | | this.centerChange++ |
| | | this.props = `5,${this.centerChange}` |
| | | }, 688) |
| | | }, |
| | | // ç§»å¨ä¸ |
| | | moveDuring() { |
| | | clearTimeout(this.TIME_CUT_CENTER) |
| | | }, |
| | | // æ¾ç¤ºå è½½æ¡ |
| | | showLoading() { |
| | | uni.showLoading({ |
| | | title: '请ç¨ç......', |
| | | mask: true |
| | | }) |
| | | }, |
| | | // 忢 |
| | | stop() {}, |
| | | // åæ¶/è¿å |
| | | back() { |
| | | uni.navigateBack() |
| | | }, |
| | | // è§åº¦æ¹å |
| | | angleChanged(val) { |
| | | this.moveStop() |
| | | if (val % 90) { |
| | | this.angle = Math.round(val / 90) * 90 |
| | | } |
| | | this.angleChange++ |
| | | this.props = `3,${this.angleChange}` |
| | | }, |
| | | // 设置è§åº¦ |
| | | setAngle() { |
| | | this.animation = true |
| | | this.angle = this.angle + 90 |
| | | this.angleChanged(this.angle) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-cropper { |
| | | width: 100vw; |
| | | height: 100vh; |
| | | background: linear-gradient(-120deg, #F15BB5, #9A5CE5, #01BEFF, #00F5D4); |
| | | // background: linear-gradient(-120deg, #9A5CE5, #01BEFF, #00F5D4, #43e97b); |
| | | // background: linear-gradient(-120deg,#c471f5, #ec008c, #ff4e50,#f9d423); |
| | | // background: linear-gradient(-120deg, #0976ea, #c471f5, #f956b6, #ea7e0a); |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | z-index: 1; |
| | | |
| | | &__image { |
| | | width: 100%; |
| | | border-style: none; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | z-index: 2; |
| | | -webkit-backface-visibility: hidden; |
| | | backface-visibility: hidden; |
| | | transform-origin: center; |
| | | } |
| | | |
| | | &__canvas { |
| | | position: fixed; |
| | | z-index: 10; |
| | | left: -2000px; |
| | | top: -2000px; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | &__wrapper { |
| | | position: fixed; |
| | | z-index: 4; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | border: 3000px solid rgba(0, 0, 0, 0.55); |
| | | pointer-events: none; |
| | | box-sizing: content-box; |
| | | } |
| | | |
| | | &__border { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | box-sizing: border-box; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | &__tabbar { |
| | | width: 100%; |
| | | height: 120rpx; |
| | | padding: 0 40rpx; |
| | | box-sizing: border-box; |
| | | position: fixed; |
| | | left: 0; |
| | | bottom: 0; |
| | | z-index: 99; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | color: #FFFFFF; |
| | | font-size: 32rpx; |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | left: 0; |
| | | border-top: 1rpx solid rgba(255, 255, 255, 0.2); |
| | | -webkit-transform: scaleY(0.5) translateZ(0); |
| | | transform: scaleY(0.5) translateZ(0); |
| | | transform-origin: 0 100%; |
| | | } |
| | | |
| | | &__btn { |
| | | height: 80rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | &__rotate { |
| | | width: 44rpx; |
| | | height: 44rpx; |
| | | font-size: 40rpx; |
| | | text-align: center; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | function setTimeout(instance, cb, time) { |
| | | if (time > 0) { |
| | | var s = getDate().getTime() |
| | | var fn = function () { |
| | | if (getDate().getTime() - s > time) { |
| | | cb && cb() |
| | | } else |
| | | instance.requestAnimationFrame(fn) |
| | | } |
| | | fn() |
| | | } |
| | | else |
| | | cb && cb() |
| | | } |
| | | |
| | | // å¤æè§¦æ¸çç§»å¨æ¹å |
| | | function decideSwiperDirection(startTouches, currentTouches, vertical) { |
| | | // éå¨å移容差 |
| | | var toleranceShake = 150 |
| | | // ç§»å¨å®¹å·® |
| | | var toleranceTranslate = 10 |
| | | |
| | | if (!vertical) { |
| | | // æ°´å¹³æ¹åç§»å¨ |
| | | if (Math.abs(currentTouches.y - startTouches.y) <= toleranceShake) { |
| | | // console.log(currentTouches.x, startTouches.x); |
| | | if (Math.abs(currentTouches.x - startTouches.x) > toleranceTranslate) { |
| | | if (currentTouches.x - startTouches.x > 0) { |
| | | return 'right' |
| | | } else if (currentTouches.x - startTouches.x < 0) { |
| | | return 'left' |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | // åç´æ¹åç§»å¨ |
| | | if (Math.abs(currentTouches.x - startTouches.x) <= toleranceShake) { |
| | | // console.log(currentTouches.x, startTouches.x); |
| | | if (Math.abs(currentTouches.y - startTouches.y) > toleranceTranslate) { |
| | | if (currentTouches.y - startTouches.y > 0) { |
| | | return 'down' |
| | | } else if (currentTouches.y - startTouches.y < 0) { |
| | | return 'up' |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return '' |
| | | } |
| | | |
| | | // swiperItemåæ°æ°æ®æ´æ° |
| | | var itemDataObserver = function(newVal, oldVal, ownerInstance, instance) { |
| | | if (!newVal || newVal === 'undefined') return |
| | | var state = ownerInstance.getState() |
| | | state.itemData = newVal |
| | | } |
| | | |
| | | // swiperIndexæ°æ®æ´æ° |
| | | var currentIndexObserver = function(newVal, oldVal, ownerInstance, instance) { |
| | | if ((!newVal && newVal != 0) || newVal === 'undefined') return |
| | | var state = ownerInstance.getState() |
| | | state.currentIndex = newVal |
| | | } |
| | | |
| | | // containerDataæ°æ®æ´æ° |
| | | var containerDataObserver = function(newVal, oldVal, ownerInstance, instance) { |
| | | if (!newVal || newVal === 'undefined') return |
| | | var state = ownerInstance.getState() |
| | | state.containerData = newVal |
| | | } |
| | | |
| | | // å¼å§è§¦æ¸ |
| | | var touchStart = function(event, ownerInstance) { |
| | | console.log('touchStart'); |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | var itemData = state.itemData |
| | | var containerData = state.containerData |
| | | |
| | | // ç±äºå½åSwiperIndexåå§ä¸º0ï¼å¯è½ä¼å¯¼è´swiperIndexæ°æ®æ²¡ææ´æ° |
| | | if (!state.currentIndex || state.currentIndex === 'undefined') { |
| | | state.currentIndex = 0 |
| | | } |
| | | |
| | | if (!containerData || containerData.circular === 'undefined') { |
| | | containerData.circular = false |
| | | } |
| | | state.containerData = containerData |
| | | |
| | | // 妿å½å忢å¨ç»è¿æ²¡æ§è¡ç»æï¼å次触æ¸ä¼éæ°å 载对åºçswiperContainerçä¿¡æ¯ |
| | | // console.log(containerData.animationFinish); |
| | | if (!containerData.animationFinish) { |
| | | ownerInstance.callMethod('changeParentSwiperContainerStyleStatus',{ |
| | | status: 'reload' |
| | | }) |
| | | } |
| | | |
| | | // 夿æ¯å¦ä¸ºä¸ºå½åæ¾ç¤ºçSwiperItem |
| | | if (itemData.index != state.currentIndex) return |
| | | |
| | | var touches = event.changedTouches[0] |
| | | if (!touches) return |
| | | |
| | | // æ è®°æ»å¨å¼å§æ¶é´ |
| | | state.touchStartTime = getDate().getTime() |
| | | |
| | | // è®°å½å½åæ»å¨å¼å§çxï¼yåæ |
| | | state.touchRelactive = { |
| | | x: touches.pageX, |
| | | y: touches.pageY |
| | | } |
| | | // è®°å½è§¦æ¸idï¼ç¨äºå¤ç夿çæ
åµ |
| | | state.touchId = touches.identifier |
| | | |
| | | // æ è®°å¼å§è§¦æ¸ |
| | | state.touching = true |
| | | ownerInstance.callMethod('updateTouchingStatus', { |
| | | status: true |
| | | }) |
| | | } |
| | | |
| | | // æ£å¨ç§»å¨ |
| | | var touchMove = function(event, ownerInstance) { |
| | | console.log('touchMove'); |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | var itemData = state.itemData |
| | | var containerData = state.containerData |
| | | |
| | | // 夿æ¯å¦ä¸ºä¸ºå½åæ¾ç¤ºçSwiperItem |
| | | if (itemData.index != state.currentIndex) return |
| | | |
| | | // 夿æ¯å¦å¼å§è§¦æ¸ |
| | | if (!state.touching) return |
| | | |
| | | var touches = event.changedTouches[0] |
| | | if (!touches) return |
| | | // 夿æ¯å¦ä¸ºåä¸ä¸ªè§¦æ¸ç¹ |
| | | if (state.touchId != touches.identifier) return |
| | | |
| | | var currentTouchRelactive = { |
| | | x: touches.pageX, |
| | | y: touches.pageY |
| | | } |
| | | |
| | | // 计ç®ç¸å¯¹ä½ç§»æ¯ä¾ |
| | | if (containerData.vertical) { |
| | | var touchDistance = currentTouchRelactive.y - state.touchRelactive.y |
| | | var itemHeight = itemData.itemHeight |
| | | var distanceRate = touchDistance / itemHeight |
| | | // console.log(currentTouchRelactive.y, touchDistance, itemHeight, distanceRate); |
| | | |
| | | // 夿æ¯å¦ä¸ºè¡æ¥è½®æï¼å¦æä¸æ¯è¡æ¥è½®æï¼å¦æå½å为第ä¸ä¸ªswiperItemå¹¶ä¸å䏿»ãå½å为æåä¸ä¸ªswiperItemå¹¶ä¸å䏿»æ¶ä¸è¿è¡æä½ |
| | | if (!containerData.circular && |
| | | ((state.currentIndex === 0 && touchDistance > 0) || (state.currentIndex === containerData.swiperItemLength - 1 && touchDistance < 0)) |
| | | ) { |
| | | return |
| | | } |
| | | |
| | | // 妿è¶
åºäºè·ç¦»åä¸è¿è¡æä½ |
| | | if((Math.abs(touchDistance) > (itemData.itemTop + itemData.itemHeight))) { |
| | | ownerInstance.callMethod('updateParentSwiperContainerStyle', { |
| | | value: distanceRate < 0 ? -1 : 1 |
| | | }) |
| | | return |
| | | } |
| | | } else { |
| | | var touchDistance = currentTouchRelactive.x - state.touchRelactive.x |
| | | var itemWidth = itemData.itemWidth |
| | | var distanceRate = touchDistance / itemWidth |
| | | // console.log(currentTouchRelactive.x, touchDistance, itemWidth, distanceRate); |
| | | |
| | | // 夿æ¯å¦ä¸ºè¡æ¥è½®æï¼å¦æä¸æ¯è¡æ¥è½®æï¼å¦æå½å为第ä¸ä¸ªswiperItemå¹¶ä¸å峿»ãå½å为æåä¸ä¸ªswiperItemå¹¶ä¸åå·¦æ»æ¶ä¸è¿è¡æä½ |
| | | if (!containerData.circular && |
| | | ((state.currentIndex === 0 && touchDistance > 0) || (state.currentIndex === containerData.swiperItemLength - 1 && touchDistance < 0)) |
| | | ) { |
| | | return |
| | | } |
| | | |
| | | // 妿è¶
åºäºè·ç¦»åä¸è¿è¡æä½ |
| | | if((Math.abs(touchDistance) > (itemData.itemLeft + itemData.itemWidth))) { |
| | | ownerInstance.callMethod('updateParentSwiperContainerStyle', { |
| | | value: distanceRate < 0 ? -1 : 1 |
| | | }) |
| | | return |
| | | } |
| | | } |
| | | |
| | | ownerInstance.callMethod('updateParentSwiperContainerStyle', { |
| | | value: distanceRate |
| | | }) |
| | | } |
| | | |
| | | // ç§»å¨ç»æ |
| | | var touchEnd = function(event, ownerInstance) { |
| | | console.log('touchEnd'); |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | var itemData = state.itemData |
| | | var containerData = state.containerData |
| | | |
| | | // 夿æ¯å¦ä¸ºä¸ºå½åæ¾ç¤ºçSwiperItem |
| | | if (itemData.index != state.currentIndex) return |
| | | |
| | | // 夿æ¯å¦å¼å§è§¦æ¸ |
| | | if (!state.touching) return |
| | | |
| | | var touches = event.changedTouches[0] |
| | | if (!touches) return |
| | | // 夿æ¯å¦ä¸ºåä¸ä¸ªè§¦æ¸ç¹ |
| | | if (state.touchId != touches.identifier) return |
| | | |
| | | |
| | | var currentTime = getDate().getTime() |
| | | var currentTouchRelactive = { |
| | | x: touches.pageX, |
| | | y: touches.pageY |
| | | } |
| | | |
| | | if (containerData.vertical) { |
| | | // å¤æè§¦æ¸ç§»å¨æ¹å |
| | | var direction = decideSwiperDirection(state.touchRelactive, currentTouchRelactive, true) |
| | | // 夿æ¯å¦ä¸ºè¡æ¥è½®æï¼å¦æä¸æ¯è¡æ¥è½®æï¼å¦æå½å为第ä¸ä¸ªswiperItemå¹¶ä¸å䏿»ãå½å为æåä¸ä¸ªswiperItemå¹¶ä¸å䏿»æ¶ä¸è¿è¡æä½ |
| | | if (containerData.circular || |
| | | !((state.currentIndex === 0 && direction === 'down') || (state.currentIndex === containerData.swiperItemLength - 1 && direction === 'up')) |
| | | ) { |
| | | // å¤æè§¦æ¸çæ¶é´åç§»å¨çè·ç¦»æ¯å¦è¶
è¿äºå½åitemHeightçä¸åï¼å¦ææ¯åæ§è¡åæ¢æä½ |
| | | // console.log(currentTime - state.touchStartTime, Math.abs(currentTouchRelactive.y - state.touchRelactive.y)); |
| | | if ((currentTime - state.touchStartTime) > 200 && Math.abs(currentTouchRelactive.y - state.touchRelactive.y) < itemData.itemHeight / 2) { |
| | | ownerInstance.callMethod('changeParentSwiperContainerStyleStatus',{ |
| | | status: 'reset' |
| | | }) |
| | | } else { |
| | | // console.log(direction, state.touchRelactive.y, currentTouchRelactive.y); |
| | | |
| | | ownerInstance.callMethod('updateParentSwiperContainerStyleWithDirection', { |
| | | direction: direction |
| | | }) |
| | | } |
| | | } |
| | | } else { |
| | | // å¤æè§¦æ¸ç§»å¨æ¹å |
| | | var direction = decideSwiperDirection(state.touchRelactive, currentTouchRelactive, false) |
| | | // 夿æ¯å¦ä¸ºè¡æ¥è½®æï¼å¦æä¸æ¯è¡æ¥è½®æï¼å¦æå½å为第ä¸ä¸ªswiperItemå¹¶ä¸å峿»ãå½å为æåä¸ä¸ªswiperItemå¹¶ä¸åå·¦æ»æ¶ä¸è¿è¡æä½ |
| | | if (containerData.circular || |
| | | !((state.currentIndex === 0 && direction === 'right') || (state.currentIndex === containerData.swiperItemLength - 1 && direction === 'left')) |
| | | ) { |
| | | // å¤æè§¦æ¸çæ¶é´åç§»å¨çè·ç¦»æ¯å¦è¶
è¿äºå½åitemWidthçä¸åï¼å¦ææ¯åæ§è¡åæ¢æä½ |
| | | // console.log(currentTime - state.touchStartTime, Math.abs(currentTouchRelactive.x - state.touchRelactive.x)); |
| | | if ((currentTime - state.touchStartTime) > 200 && Math.abs(currentTouchRelactive.x - state.touchRelactive.x) < itemData.itemWidth / 2) { |
| | | ownerInstance.callMethod('changeParentSwiperContainerStyleStatus',{ |
| | | status: 'reset' |
| | | }) |
| | | } else { |
| | | // console.log(direction, state.touchRelactive.x, currentTouchRelactive.x); |
| | | |
| | | ownerInstance.callMethod('updateParentSwiperContainerStyleWithDirection', { |
| | | direction: direction |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æ¸
餿 è®° |
| | | state.touchId = null |
| | | state.touchRelactive = null |
| | | state.touchStartTime = 0 |
| | | |
| | | |
| | | // æ è®°åæ¢è§¦æ¸ |
| | | state.touching = true |
| | | ownerInstance.callMethod('updateTouchingStatus', { |
| | | status: false |
| | | }) |
| | | } |
| | | |
| | | module.exports = { |
| | | itemDataObserver: itemDataObserver, |
| | | currentIndexObserver: currentIndexObserver, |
| | | containerDataObserver: containerDataObserver, |
| | | touchStart: touchStart, |
| | | touchMove: touchMove, |
| | | touchEnd: touchEnd |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- #ifdef MP-WEIXIN --> |
| | | <view |
| | | class="tn-c-swiper-item" |
| | | :style="[swiperStyle]" |
| | | :itemData="itemData" |
| | | :currentIndex="currentIndex" |
| | | :containerData="containerData" |
| | | :change:itemData="wxs.itemDataObserver" |
| | | :change:currentIndex="wxs.currentIndexObserver" |
| | | :change:containerData="wxs.containerDataObserver" |
| | | @touchstart="wxs.touchStart" |
| | | :catch:touchmove="touching?wxs.touchMove:''" |
| | | :catch:touchend="touching?wxs.touchEnd:''" |
| | | > |
| | | <view class="item__container tn-c-swiper-item__container" :style="[containerStyle]"> |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | <!-- #endif --> |
| | | <!-- #ifndef MP-WEIXIN --> |
| | | <view |
| | | class="tn-c-swiper-item" |
| | | :style="[swiperStyle]" |
| | | :itemData="itemData" |
| | | :currentIndex="currentIndex" |
| | | :containerData="containerData" |
| | | :change:itemData="wxs.itemDataObserver" |
| | | :change:currentIndex="wxs.currentIndexObserver" |
| | | :change:containerData="wxs.containerDataObserver" |
| | | @touchstart="wxs.touchStart" |
| | | @touchmove="wxs.touchMove" |
| | | @touchend="wxs.touchEnd" |
| | | > |
| | | <view class="item__container tn-c-swiper-item__container" :style="[containerStyle]"> |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | <!-- #endif --> |
| | | </template> |
| | | |
| | | <script src="./index.wxs" lang="wxs" module="wxs"></script> |
| | | <script> |
| | | export default { |
| | | name: 'tn-custom-swiper-item', |
| | | props: { |
| | | |
| | | }, |
| | | computed: { |
| | | // swiperItemå
Œ
±æ°æ® |
| | | itemData() { |
| | | return { |
| | | index: this.index, |
| | | itemWidth: this.itemWidth, |
| | | itemHeight: this.itemHeight, |
| | | itemTop: this.itemTop, |
| | | itemLeft: this.itemLeft |
| | | } |
| | | }, |
| | | currentIndex() { |
| | | return this.parentData.currentIndex |
| | | }, |
| | | containerData() { |
| | | return { |
| | | duration: this.parentData.duration, |
| | | animationFinish: this.parentData.swiperContainerAnimationFinish, |
| | | circular: this.parentData.circular, |
| | | swiperItemLength: this.swiperItemLength, |
| | | vertical: this.parentData.vertical |
| | | } |
| | | }, |
| | | swiperStyle() { |
| | | let style = {} |
| | | style.transform = `translate3d(${this.translateX}%, ${this.translateY}%, 0px)` |
| | | return style |
| | | }, |
| | | containerStyle() { |
| | | let style = {} |
| | | if (this.parentData.customSwiperStyle && Object.keys(this.parentData.customSwiperStyle).length > 0) { |
| | | style = this.parentData.customSwiperStyle |
| | | } |
| | | if ((this.currentIndex === 0 && this.index === this.swiperItemLength - 1) || (this.index === this.currentIndex - 1) && |
| | | (this.parentData.prevSwiperStyle && Object.keys(this.parentData.prevSwiperStyle).length > 0) |
| | | ) { |
| | | // åä¸ä¸ªswiperItem |
| | | const copyStyle = JSON.parse(JSON.stringify(style)) |
| | | style = Object.assign(copyStyle, this.parentData.prevSwiperStyle) |
| | | } |
| | | if ((this.currentIndex === this.swiperItemLength - 1 && this.index === 0) || (this.index === this.currentIndex + 1) && |
| | | (this.parentData.nextSwiperStyle && Object.keys(this.parentData.nextSwiperStyle).length > 0) |
| | | ) { |
| | | // åä¸ä¸ªswiperItem |
| | | const copyStyle = JSON.parse(JSON.stringify(style)) |
| | | style = Object.assign(copyStyle, this.parentData.nextSwiperStyle) |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ç¶ç»ä»¶åæ° |
| | | parentData: { |
| | | duration: 500, |
| | | currentIndex: 0, |
| | | swiperContainerAnimationFinish: false, |
| | | circular: false, |
| | | vertical: false, |
| | | prevSwiperStyle: {}, |
| | | customSwiperStyle: {}, |
| | | nextSwiperStyle: {} |
| | | }, |
| | | // æ è®°å½åæ¯å¦æ£å¨è§¦æ¸ |
| | | touching: true, |
| | | // å½åswiperItemçåç§»ä½ç½® |
| | | translateX: 0, |
| | | translateY: 0, |
| | | // å½åswiperItemçå®½é« |
| | | itemWidth: 0, |
| | | itemHeight: 0, |
| | | // å½åswiperItemçä½ç½®ä¿¡æ¯ |
| | | itemTop: 0, |
| | | itemLeft: 0, |
| | | // å½åswiperItemçç¶æ prev current next |
| | | status: 'current', |
| | | // å½åswiperItemçindexåºå· |
| | | index: 0, |
| | | // swiperItemççæ°é |
| | | swiperItemLength: 0 |
| | | } |
| | | }, |
| | | created() { |
| | | this.parent = false |
| | | this.updateParentData() |
| | | // è·åå½åç¶ç»ä»¶childrençæ°éä½ä¸ºå½åswiperItemçåºå· |
| | | this.index = this.parent.children.length |
| | | this.parent && this.parent.children.push(this) |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.initSwiperItem() |
| | | }) |
| | | }, |
| | | methods: { |
| | | // åå§åswiperItem |
| | | initSwiperItem() { |
| | | this.getSwiperItemRect(() => { |
| | | this.parent.updateAllSwiperItemStyle() |
| | | this.parentData.swiperContainerAnimationFinish = true |
| | | }) |
| | | }, |
| | | // è·åswiperItemçä¿¡æ¯ |
| | | async getSwiperItemRect(callback) { |
| | | const swiperItemRes = await this._tGetRect('.tn-c-swiper-item') |
| | | if (!swiperItemRes.height || !swiperItemRes.width) { |
| | | setTimeout(() => { |
| | | this.getSwiperItemRect() |
| | | }, 30) |
| | | return |
| | | } |
| | | |
| | | this.itemWidth = swiperItemRes.width |
| | | this.itemHeight = swiperItemRes.height |
| | | this.itemTop = swiperItemRes.top |
| | | this.itemLeft = swiperItemRes.left |
| | | callback && callback() |
| | | }, |
| | | // æ´æ°swiperItemæ ·å¼ |
| | | updateSwiperItemStyle(swiperItemLength, currentIndex = undefined) { |
| | | currentIndex = currentIndex != undefined ? currentIndex : this.parentData.currentIndex |
| | | this.swiperItemLength = swiperItemLength |
| | | // æ ¹æ®å½åswiperItemçåºå·è®¾ç½®åç§»ä½ç½® |
| | | // 夿å½åswiperItemæ¯å¦ä¸ºç¬¬ä¸ä¸ªï¼å¦ææ¯åå°æåçswiperItemç§»å¨å°å½åçåä¸ä¸ªä½ç½®ï¼å³æåé¢ï¼ |
| | | if (currentIndex === 0 && this.index === swiperItemLength - 1) { |
| | | if (this.parentData.vertical) { |
| | | this.translateX = 0 |
| | | this.translateY = -100 |
| | | } else { |
| | | this.translateX = -100 |
| | | this.translateY = 0 |
| | | } |
| | | } |
| | | // 夿å½åswiperItemæ¯å¦ä¸ºæåä¸ä¸ªï¼å¦ææ¯åå°æåçswiperItemç§»å¨å°å½åçåä¸ä¸ªä½ç½®ï¼å³æåé¢ï¼ |
| | | else if (currentIndex === swiperItemLength - 1 && this.index === 0) { |
| | | if (this.parentData.vertical) { |
| | | this.translateX = 0 |
| | | this.translateY = swiperItemLength * 100 |
| | | } else { |
| | | this.translateX = swiperItemLength * 100 |
| | | this.translateY = 0 |
| | | } |
| | | } |
| | | // æ£å¸¸æ
åµ |
| | | else { |
| | | if (this.parentData.vertical) { |
| | | this.translateX = 0 |
| | | this.translateY = this.index * 100 |
| | | } else { |
| | | this.translateX = this.index * 100 |
| | | this.translateY = 0 |
| | | } |
| | | } |
| | | }, |
| | | // æ´æ°ç¶ç»ä»¶çåç§»ä½ç½®ä¿¡æ¯ |
| | | updateParentSwiperContainerStyle(e) { |
| | | this.parent.updateSwiperContainerStyleWithValue(e.value) |
| | | }, |
| | | // æ ¹æ®æ¹åæ´æ°ç¶ç»ä»¶çåç§»ä½ç½®ä¿¡æ¯ |
| | | updateParentSwiperContainerStyleWithDirection(e) { |
| | | this.parent.updateSwiperContainerStyleWithDirection(e.direction) |
| | | }, |
| | | // ä¿®æ¹ç¶ç»ä»¶çåç§»ä½ç½®çç¶æ |
| | | changeParentSwiperContainerStyleStatus(e) { |
| | | // reset -> éç½® reload -> éè½½ |
| | | this.parent.updateSwiperContainerStyleWithDirection(e.status) |
| | | }, |
| | | // æ´æ°ç¶ç»ä»¶ä¿¡æ¯ |
| | | updateParentData() { |
| | | this.getParentData('tn-custom-swiper') |
| | | }, |
| | | // æ´æ°è§¦æ¸ç¶æ |
| | | updateTouchingStatus(e) { |
| | | this.touching = e.status |
| | | if (e.status) { |
| | | this.parent.stopAutoPlay() |
| | | } else { |
| | | this.parent.startAutoPlay() |
| | | } |
| | | }, |
| | | // æå对åºç¨æ·èªå®ä¹æ ·å¼ |
| | | extractCustomStyle(customStyle) { |
| | | let data = { |
| | | transform: {}, |
| | | style: {} |
| | | } |
| | | if (!customStyle) return data |
| | | // å
许设置çtransformåæ° |
| | | const allowTransformProps = ['scale','scaleX','scaleY','scaleZ','rotate','rotateX','rotateY','rotateZ'] |
| | | for (let prop in customStyle) { |
| | | if (prop.startsWith('transformProp')) { |
| | | // transforméé¢çæ ·å¼ |
| | | let transformProp = prop.substring('transformProp'.length) |
| | | const index = allowTransformProps.findIndex((item) => { |
| | | return item.toLowerCase() === transformProp.toLowerCase() |
| | | }) |
| | | if (index !== -1) { |
| | | transformProp = allowTransformProps[index] |
| | | data.transform[transformProp] = customStyle[prop] |
| | | } |
| | | } else { |
| | | // æ®éæ ·å¼ |
| | | data.style[prop] = customStyle[prop] |
| | | } |
| | | } |
| | | return data |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-c-swiper-item { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: absolute; |
| | | display: block; |
| | | will-change: transform; |
| | | cursor: none; |
| | | transform: translate3d(0px, 0px, 0px); |
| | | |
| | | .item__container { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: block; |
| | | position: absolute; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-c-swiper-class tn-c-swiper" |
| | | > |
| | | <!-- è½®æitem容å¨--> |
| | | <view class="tn-swiper__container" :style="[swiperContainerStyle]" :animation="containerAnimation"> |
| | | <slot></slot> |
| | | </view> |
| | | |
| | | <!-- è½®ææç¤ºå¨--> |
| | | <view v-if="indicator" class="tn-swiper__indicator" :class="[`tn-swiper__indicator--${vertical ? 'vertical' : 'horizontal'}`]" :style="[indicatorStyle]"> |
| | | <!-- æ¹å½¢ --> |
| | | <block v-if="indicatorType === 'rect'"> |
| | | <view |
| | | v-for="(item, index) in children.length" |
| | | :key="index" |
| | | class="tn-swiper__indicator__rect" |
| | | :class="[ |
| | | `tn-swiper__indicator__rect--${vertical ? 'vertical' : 'horizontal'}`, |
| | | currentIndex === index ? `tn-swiper__indicator__rect--active tn-swiper__indicator__rect--active--${vertical ? 'vertical' : 'horizontal'}` : '' |
| | | ]" |
| | | :style="[indicatorPointStyle(index)]" |
| | | ></view> |
| | | </block> |
| | | <!-- ç¹ --> |
| | | <block v-if="indicatorType === 'dot'"> |
| | | <view |
| | | v-for="(item, index) in children.length" |
| | | :key="index" |
| | | class="tn-swiper__indicator__dot" |
| | | :class="[ |
| | | `tn-swiper__indicator__dot--${vertical ? 'vertical' : 'horizontal'}`, |
| | | currentIndex === index ? `tn-swiper__indicator__dot--active tn-swiper__indicator__dot--active--${vertical ? 'vertical' : 'horizontal'}` : '' |
| | | ]" |
| | | :style="[indicatorPointStyle(index)]" |
| | | ></view> |
| | | </block> |
| | | <!-- åè§æ¹å½¢ --> |
| | | <block v-if="indicatorType === 'round'"> |
| | | <view |
| | | v-for="(item, index) in children.length" |
| | | :key="index" |
| | | class="tn-swiper__indicator__round" |
| | | :class="[ |
| | | `tn-swiper__indicator__round--${vertical ? 'vertical' : 'horizontal'}`, |
| | | currentIndex === index ? `tn-swiper__indicator__round--active tn-swiper__indicator__round--active--${vertical ? 'vertical' : 'horizontal'}` : '' |
| | | ]" |
| | | :style="[indicatorPointStyle(index)]" |
| | | ></view> |
| | | </block> |
| | | <!-- åºå· --> |
| | | <block v-if="indicatorType === 'number' && !vertical"> |
| | | <view class="tn-swiper__indicator__number">{{ currentIndex + 1 }}/{{ children.length }}</view> |
| | | </block> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-custom-swiper', |
| | | props: { |
| | | // å½åæå¨çè½®æä½ç½® |
| | | current: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // èªå¨åæ¢ |
| | | autoplay: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // èªå¨åæ¢æ¶é´é´é |
| | | interval: { |
| | | type: Number, |
| | | default: 5000 |
| | | }, |
| | | // æ»å¨å¨ç»æ¶é¿ |
| | | duration: { |
| | | type: Number, |
| | | default: 500 |
| | | }, |
| | | // æ¯å¦éç¨è¡æ¥æ»å¨ |
| | | circular: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ»å¨æ¹å为纵å |
| | | vertical: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¾ç¤ºæç¤ºç¹ |
| | | indicator: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æç¤ºç¹ç±»å |
| | | // rect -> æ¹å½¢ round -> åè§æ¹å½¢ dot -> ç¹ number -> è½®æå¾ä¸æ |
| | | indicatorType: { |
| | | type: String, |
| | | default: 'dot' |
| | | }, |
| | | // æç¤ºç¹çä½ç½® |
| | | // topLeft \ topCenter \ topRight \ bottomLeft \ bottomCenter \ bottomRight |
| | | indicatorPosition: { |
| | | type: String, |
| | | default: 'bottomCenter' |
| | | }, |
| | | // æç¤ºç¹æ¿æ´»æ¶é¢è² |
| | | indicatorActiveColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æç¤ºç¹æªæ¿æ´»æ¶é¢è² |
| | | indicatorInactiveColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // åä¸ä¸ªè½®æçèªå®ä¹æ ·å¼ |
| | | prevSwiperStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // å½åè½®æçèªå®ä¹æ ·å¼ |
| | | customSwiperStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // åä¸ä¸ªè½®æçèªå®ä¹æ ·å¼ |
| | | nextSwiperStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | parentData() { |
| | | return [ |
| | | this.duration, |
| | | this.currentIndex, |
| | | this.swiperContainerAnimationFinish, |
| | | this.circular, |
| | | this.vertical, |
| | | this.prevSwiperStyle, |
| | | this.customSwiperStyle, |
| | | this.nextSwiperStyle |
| | | ] |
| | | }, |
| | | indicatorStyle() { |
| | | let style = {} |
| | | if (this.vertical) { |
| | | if (this.indicatorPosition === 'topLeft' || this.indicatorPosition === 'bottomLeft') style.justifyContent = 'flex-start' |
| | | if (this.indicatorPosition === 'topCenter' || this.indicatorPosition === 'bottomCenter') style.justifyContent = 'center' |
| | | if (this.indicatorPosition === 'topRight' || this.indicatorPosition === 'bottomRight') style.justifyContent = 'flex-end' |
| | | if (['topLeft','topCenter','topRight'].indexOf(this.indicatorPosition) >= 0) { |
| | | if (this.vertical) { |
| | | style.right = '12rpx' |
| | | style.left = 'auto' |
| | | } else { |
| | | style.top = '12rpx' |
| | | style.bottom = 'auto' |
| | | } |
| | | } else { |
| | | if (this.vertical) { |
| | | style.right = 'auto' |
| | | style.left = '12rpx' |
| | | } else { |
| | | style.top = 'auto' |
| | | style.bottom = '12rpx' |
| | | } |
| | | } |
| | | } else { |
| | | if (this.indicatorPosition === 'topLeft' || this.indicatorPosition === 'bottomLeft') style.justifyContent = 'flex-start' |
| | | if (this.indicatorPosition === 'topCenter' || this.indicatorPosition === 'bottomCenter') style.justifyContent = 'center' |
| | | if (this.indicatorPosition === 'topRight' || this.indicatorPosition === 'bottomRight') style.justifyContent = 'flex-end' |
| | | if (['topLeft','topCenter','topRight'].indexOf(this.indicatorPosition) >= 0) { |
| | | style.top = '12rpx' |
| | | style.bottom = 'auto' |
| | | } else { |
| | | style.top = 'auto' |
| | | style.bottom = '12rpx' |
| | | } |
| | | } |
| | | return style |
| | | }, |
| | | indicatorPointStyle() { |
| | | return (index) => { |
| | | let style = {} |
| | | if (index === this.currentIndex && this.indicatorActiveColor !== '') { |
| | | style.backgroundColor = this.indicatorActiveColor |
| | | } else if (this.indicatorInactiveColor !== '') { |
| | | style.backgroundColor = this.indicatorInactiveColor |
| | | } |
| | | return style |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | parentData() { |
| | | if (this.children.length) { |
| | | this.children.forEach((item) => { |
| | | // 夿åç»ä»¶å¦ææupdateParentDataæ¹æ³çè¯ï¼å°±å°±æ§è¡(æ§è¡çç»ææ¯åç»ä»¶éæ°ä»ç¶ç»ä»¶æåäºææ°çå¼) |
| | | typeof(item.updateParentData) === 'function' && item.updateParentData() |
| | | }) |
| | | } |
| | | }, |
| | | current(nVal, oVal) { |
| | | if (this.currentIndex === nVal) return |
| | | this.currentIndex = nVal > this.children.length ? this.children.length - 1 : nVal |
| | | this.swiperContainerAnimationFinish = false |
| | | // 设置å¨ç»è¿æ¸¡æ¶é´ |
| | | this.swiperContainerStyle.transitionDuration = `${this.duration + 90}ms` |
| | | this.updateSwiperContainerItem(oVal) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ¸
é¤å¨ç»å®æ¶å¨ |
| | | clearAnimationTimer: null, |
| | | // ååè¡æ¥æ§è¡å®æ¶å¨ |
| | | convergeTimer: null, |
| | | // èªå¨è½®æTimer |
| | | autoPlayTimer: null, |
| | | // å½åéä¸çè½®æ |
| | | currentIndex: this.current, |
| | | // swiperContaineræ ·å¼ |
| | | swiperContainerStyle: { |
| | | transform: 'translate3d(0px, 0px, 0px)', |
| | | transitionDuration: '0ms' |
| | | }, |
| | | // swiperContainerå¨ç» |
| | | containerAnimation: {}, |
| | | // æ»å¨å¨ç»ç»ææ è®° |
| | | swiperContainerAnimationFinish: false |
| | | } |
| | | }, |
| | | created() { |
| | | this.children = [] |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | const index = this.currentIndex > this.children.length ? this.children.length - 1 : this.currentIndex |
| | | this.updateSwiperContainerStyle(index) |
| | | this.startAutoPlay() |
| | | }) |
| | | }, |
| | | methods: { |
| | | // æ´æ°å
¨é¨swiperItemçæ ·å¼ |
| | | updateAllSwiperItemStyle() { |
| | | this.children.forEach((item, index) => { |
| | | typeof(item.updateSwiperItemStyle) === 'function' && item.updateSwiperItemStyle(this.children.length) |
| | | }) |
| | | |
| | | }, |
| | | // æ ¹æ®swiperIndexæ´æ°swiperItemContainerçæ ·å¼ |
| | | updateSwiperContainerStyle(index) { |
| | | if (this.vertical) { |
| | | this.swiperContainerStyle.transform = `translate3d(0px, ${-index * 100}%, 0px)` |
| | | } else { |
| | | this.swiperContainerStyle.transform = `translate3d(${-index * 100}%, 0px, 0px)` |
| | | } |
| | | }, |
| | | // æ ¹æ®ä¼ éç弿´æ°swiperItemContainerçä½ç½® |
| | | updateSwiperContainerStyleWithValue(value) { |
| | | if (this.vertical) { |
| | | this.swiperContainerStyle.transform = `translate3d(0px, ${(-this.currentIndex * 100) + value * 100}%, 0px)` |
| | | } else { |
| | | this.swiperContainerStyle.transform = `translate3d(${(-this.currentIndex * 100) + value * 100}%, 0px, 0px)` |
| | | } |
| | | }, |
| | | // æ ¹æ®ä¼ éçæ¹åæ´æ°swiperItemContainerçä½ç½® |
| | | updateSwiperContainerStyleWithDirection(direction) { |
| | | const oldCurrent = this.currentIndex |
| | | const childrenLength = this.children.length |
| | | const lastSwiperItemIndex = childrenLength - 1 |
| | | this.swiperContainerAnimationFinish = false |
| | | |
| | | |
| | | // åå忢ä¸ä¸ªSwiperItem |
| | | if (direction === 'reset') { |
| | | // 设置å¨ç»è¿æ¸¡æ¶é´ |
| | | this.swiperContainerStyle.transitionDuration = `${this.duration}ms` |
| | | this.updateSwiperContainerStyle(this.currentIndex) |
| | | this.clearAnimationTimer = setTimeout(() => { |
| | | this.clearSwiperContainerAnimation() |
| | | }, this.duration) |
| | | } else if (direction === 'reload') { |
| | | this.clearConvergeSwiperItemTimer() |
| | | this.clearSwiperContainerAnimation() |
| | | this.updateSwiperItemStyle(0) |
| | | this.updateSwiperItemStyle(lastSwiperItemIndex) |
| | | } else { |
| | | if (direction === 'left' || direction === 'up') { |
| | | if (oldCurrent === childrenLength - 1 && !this.circular) { |
| | | this.clearSwiperContainerAnimation() |
| | | this.clearConvergeSwiperItemTimer() |
| | | return |
| | | } |
| | | this.currentIndex = oldCurrent + 1 >= childrenLength ? 0 : oldCurrent + 1 |
| | | } else if (direction === 'right' || direction === 'down') { |
| | | if (oldCurrent === 0 && !this.circular) { |
| | | this.clearSwiperContainerAnimation() |
| | | this.clearConvergeSwiperItemTimer() |
| | | return |
| | | } |
| | | this.currentIndex = oldCurrent - 1 < 0 ? childrenLength - 1 : oldCurrent - 1 |
| | | } |
| | | // 设置å¨ç»è¿æ¸¡æ¶é´ |
| | | this.swiperContainerStyle.transitionDuration = `${this.duration + 90}ms` |
| | | // this.updateSwiperItemContainerRect(this.currentIndex) |
| | | } |
| | | |
| | | // console.log(direction, oldCurrent, this.currentIndex); |
| | | this.updateSwiperContainerItem(oldCurrent) |
| | | |
| | | // åæ¢è½®ææ¶è§¦åäºä»¶ |
| | | this.$emit('change', { |
| | | current: this.currentIndex |
| | | }) |
| | | }, |
| | | // 设置èªå¨è½®æ |
| | | startAutoPlay() { |
| | | if (this.autoplay && !this.autoPlayTimer && this.circular) { |
| | | this.autoPlayTimer = setInterval(() => { |
| | | this.updateSwiperContainerStyleWithDirection('left') |
| | | }, this.interval) |
| | | } |
| | | }, |
| | | // 忢èªå¨è½®æ |
| | | stopAutoPlay() { |
| | | if (this.autoPlayTimer) { |
| | | clearInterval(this.autoPlayTimer) |
| | | this.autoPlayTimer = null |
| | | } |
| | | }, |
| | | // æ´æ°swiperContaineråswiperItemç¸å
³èä¿¡æ¯ |
| | | updateSwiperContainerItem(oldCurrent) { |
| | | const childrenLength = this.children.length |
| | | const lastSwiperItemIndex = childrenLength - 1 |
| | | // 夿å½åæ¯å¦ä¸ºå¤´å°¾ï¼å¦ææ¯æ´æ°å¯¹åºç头尾SwiperItemæ ·å¼ |
| | | // æ´æ°swiperItemContainerçæ ·å¼ |
| | | if (oldCurrent === 0 && this.currentIndex === lastSwiperItemIndex) { |
| | | // å
ç§»å¨å°æå·¦è¾¹ç¶ååå»é¤å¨ç»åç§»å°æ£å¸¸çä½ç½® |
| | | // this.swiperContainerStyle.transform = `translate3d(100%, 0px, 0px)` |
| | | this.updateSwiperContainerStyle(-1) |
| | | this.clearSwiperContainerAnimationTimer() |
| | | this.clearAnimationTimer = setTimeout(() => { |
| | | this.convergeSwiperItem() |
| | | }, this.duration) |
| | | } else if (oldCurrent === lastSwiperItemIndex && this.currentIndex === 0) { |
| | | // å
ç§»å¨å°æå³è¾¹ç¶ååå»é¤å¨ç»åç§»å°æ£å¸¸çä½ç½® |
| | | // this.swiperContainerStyle.transform = `translate3d(${-childrenLength * 100}%, 0px, 0px)` |
| | | this.updateSwiperContainerStyle(childrenLength) |
| | | this.clearSwiperContainerAnimationTimer() |
| | | this.clearAnimationTimer = setTimeout(() => { |
| | | this.convergeSwiperItem() |
| | | }, this.duration) |
| | | } else { |
| | | this.updateSwiperContainerStyle(this.currentIndex) |
| | | this.updateSwiperItemStyle(0) |
| | | this.updateSwiperItemStyle(lastSwiperItemIndex) |
| | | this.clearAnimationTimer = setTimeout(() => { |
| | | this.clearSwiperContainerAnimation() |
| | | }, this.duration) |
| | | } |
| | | }, |
| | | // æ´æ°å¯¹åºswiperItemçä¿¡æ¯ |
| | | updateSwiperItemStyle(index) { |
| | | const childrenLength = this.children.length |
| | | if (index < 0) index = 0 |
| | | if (index > childrenLength - 1) index = childrenLength - 1 |
| | | |
| | | typeof(this.children[index].updateSwiperItemStyle) === 'function' && this.children[index].updateSwiperItemStyle(childrenLength, this.currentIndex) |
| | | }, |
| | | // æ´æ°å¯¹åºswiperItemç容å¨ä¿¡æ¯ |
| | | updateSwiperItemContainerRect(index) { |
| | | const childrenLength = this.children.length |
| | | if (index < 0) index = 0 |
| | | if (index > childrenLength - 1) index = childrenLength - 1 |
| | | |
| | | typeof(this.children[index].getSwiperItemRect) === 'function' && this.children[index].getSwiperItemRect() |
| | | }, |
| | | // æ§è¡ååè¡æ¥ |
| | | convergeSwiperItem() { |
| | | const lastSwiperItemIndex = this.children.length - 1 |
| | | this.clearSwiperContainerAnimation() |
| | | this.clearConvergeSwiperItemTimer() |
| | | this.convergeTimer = setTimeout(() => { |
| | | this.updateSwiperItemStyle(0) |
| | | this.updateSwiperItemStyle(lastSwiperItemIndex) |
| | | this.updateSwiperContainerStyle(this.currentIndex) |
| | | this.clearConvergeSwiperItemTimer() |
| | | }, 30) |
| | | }, |
| | | // 忢/æ¸
é¤åæ¢å¨ç» |
| | | clearSwiperContainerAnimation() { |
| | | this.swiperContainerStyle.transitionDuration = `0ms` |
| | | this.swiperContainerAnimationFinish = true |
| | | this.clearSwiperContainerAnimationTimer() |
| | | }, |
| | | // 忢/æ¸
餿§è¡ååè¡æ¥å®æ¶å¨ |
| | | clearConvergeSwiperItemTimer() { |
| | | if (this.convergeTimer) { |
| | | clearTimeout(this.convergeTimer) |
| | | this.convergeTimer = null |
| | | } |
| | | }, |
| | | // 忢/æ¸
é¤åæ¢å¨ç»å®æ¶å¨ |
| | | clearSwiperContainerAnimationTimer() { |
| | | if (this.clearAnimationTimer) { |
| | | clearTimeout(this.clearAnimationTimer) |
| | | this.clearAnimationTimer = null |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-c-swiper { |
| | | position: relative; |
| | | overflow: hidden; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .tn-swiper { |
| | | &__container { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | |
| | | will-change: transform; |
| | | transition-property: all; |
| | | transition-timing-function: ease-out; |
| | | } |
| | | |
| | | &__indicator { |
| | | position: absolute; |
| | | display: flex; |
| | | z-index: 1; |
| | | |
| | | &--horizontal { |
| | | padding: 0 24rpx; |
| | | flex-direction: row; |
| | | width: 100%; |
| | | } |
| | | &--vertical { |
| | | padding: 24rpx 0; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | &__rect { |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | transition: all 0.5s; |
| | | |
| | | &--horizontal { |
| | | width: 26rpx; |
| | | height: 8rpx; |
| | | } |
| | | &--vertical { |
| | | width: 8rpx; |
| | | height: 26rpx; |
| | | } |
| | | |
| | | &--active { |
| | | background-color: rgba(255, 255, 255, 0.8); |
| | | } |
| | | } |
| | | |
| | | &__dot { |
| | | width: 14rpx; |
| | | height: 14rpx; |
| | | border-radius: 20rpx; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | transition: all 0.5s; |
| | | |
| | | &--horizontal { |
| | | margin: 0 6rpx; |
| | | } |
| | | &--vertical { |
| | | margin: 6rpx 0; |
| | | } |
| | | |
| | | &--active { |
| | | background-color: rgba(255, 255, 255, 0.8); |
| | | } |
| | | } |
| | | |
| | | &__round { |
| | | width: 14rpx; |
| | | height: 14rpx; |
| | | border-radius: 20rpx; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | transition: all 0.5s; |
| | | |
| | | &--horizontal { |
| | | margin: 0 6rpx; |
| | | } |
| | | &--vertical { |
| | | margin: 6rpx 0; |
| | | } |
| | | |
| | | &--active { |
| | | background-color: rgba(255, 255, 255, 0.8); |
| | | |
| | | &--horizontal { |
| | | width: 34rpx; |
| | | } |
| | | &--vertical { |
| | | height: 34rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__number { |
| | | padding: 6rpx 16rpx; |
| | | line-height: 1; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | color: rgba(255, 255, 255, 0.8); |
| | | border-radius: 100rpx; |
| | | font-size: 26rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // 夿æ¯å¦åºç |
| | | var isOutRange = function(x1, y1, x2, y2, x3, y3) { |
| | | return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3 |
| | | } |
| | | var edit = false |
| | | |
| | | function bool(str) { |
| | | return str === 'true' || str === true |
| | | } |
| | | /** |
| | | * æåºæ ¸å¿ |
| | | * @param {Object} startKey å¼å§æ¶ä½ç½® |
| | | * @param {Object} endKey ç»ææ¶ä½ç½® |
| | | * @param {Object} instance wxså
çå±é¨åéå¿«ç
§ |
| | | */ |
| | | var sortCore = function(startKey, endKey, state) { |
| | | var basedata = state.basedata |
| | | var excludeFix = function(sortKey, type) { |
| | | // fixed å
ç´ ä½ç½®ä¸ä¼åå, è¿éç´æ¥ç¨ sortKey è·åï¼æ´å ä¾¿æ· |
| | | if (state.list[sortKey].fixed) { |
| | | var _sortKey = type ? --sortKey : ++sortKey |
| | | return excludeFix(sortKey, type) |
| | | } |
| | | return sortKey |
| | | } |
| | | |
| | | // å
è·åå° endKey 对åºç realKey, 鲿¢ä¸é¢æåºè¿ç¨ä¸è¯¥ realKey è¢«ä¿®æ¹ |
| | | var endRealKey = -1 |
| | | state.list.forEach(function(item) { |
| | | if (item.sortKey === endKey) endRealKey = item.realKey |
| | | }) |
| | | |
| | | return state.list.map(function(item) { |
| | | if (item.fixed) return item |
| | | var sortKey = item.sortKey |
| | | var realKey = item.realKey |
| | | |
| | | if (startKey < endKey) { |
| | | // æ£åºæå¨ |
| | | if (sortKey > startKey && sortKey <= endKey) { |
| | | --realKey |
| | | sortKey = excludeFix(--sortKey, true) |
| | | } else if (sortKey === startKey) { |
| | | realKey = endRealKey |
| | | sortKey = endKey |
| | | } |
| | | } else if (startKey > endKey) { |
| | | // ååºæå¨ |
| | | if (sortKey >= endKey && sortKey < startKey) { |
| | | ++realKey |
| | | sortKey = excludeFix(++sortKey, false) |
| | | } else if (sortKey === startKey) { |
| | | realKey = endRealKey |
| | | sortKey = endKey |
| | | } |
| | | } |
| | | |
| | | if (item.sortKey != sortKey) { |
| | | item.translateX = (sortKey % basedata.columns) * 100 + '%' |
| | | item.translateY = Math.floor(sortKey / basedata.columns) * 100 + '%' |
| | | item.sortKey = sortKey |
| | | item.realKey = realKey |
| | | } |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | var triggerCustomEvent = function(list, type, instance) { |
| | | if (!instance) return |
| | | var _list = [], |
| | | listData = []; |
| | | |
| | | list.forEach(function(item) { |
| | | _list[item.sortKey] = item |
| | | }) |
| | | _list.forEach(function(item) { |
| | | listData.push(item.data) |
| | | }) |
| | | |
| | | // ç¼è¯å°å°ç¨åº funcNameä½ä¸ºåæ°ä¼ é导è´äºä»¶ä¸æ§è¡ |
| | | switch(type) { |
| | | case 'change': |
| | | instance.callMethod('change', {data: listData}) |
| | | break |
| | | case 'sortEnd': |
| | | instance.callMethod('sortEnd', {data: listData}) |
| | | break |
| | | } |
| | | } |
| | | |
| | | var listObserver = function(newVal, oldVal, ownerInstance, instance) { |
| | | var state = ownerInstance.getState() |
| | | state.itemsInstance = ownerInstance.selectAllComponents('.tn-drag__item') |
| | | |
| | | state.list = newVal || [] |
| | | |
| | | state.list.forEach(function(item, index) { |
| | | var itemInstance = state.itemsInstance[index] |
| | | if (item && itemInstance) { |
| | | itemInstance.setStyle({ |
| | | 'transform': 'translate3d('+ item.translateX + ',' + item.translateY +', 0)' |
| | | }) |
| | | if (item.fixed) itemInstance.addClass('tn-drag__fixed') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | var baseDataObserver = function(newVal, oldVal, ownerInstance, instance) { |
| | | var state = ownerInstance.getState() |
| | | state.basedata = newVal |
| | | } |
| | | |
| | | var longPress = function(event, ownerInstance) { |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | |
| | | edit = bool(dataset.edit) |
| | | if (!edit) return |
| | | if (!state.basedata || state.basedata === 'undefined') { |
| | | state.basedata = JSON.parse(dataset.basedata) |
| | | } |
| | | var basedata = state.basedata |
| | | var touches = event.changedTouches[0] |
| | | if (!touches) return |
| | | |
| | | state.current = +dataset.index |
| | | |
| | | // åå§é¡¹æ¯åºå®é¡¹åè¿å |
| | | var item = state.list[state.current] |
| | | if (item && item.fixed) return |
| | | |
| | | // 妿已ç»å¨ drag ä¸åè¿å, 鲿¢å¤æè§¦å drag å¨ä½, touchstart äºä»¶ä¸æææ |
| | | if (state.dragging) return |
| | | |
| | | ownerInstance.callMethod("drag", { |
| | | dragging: true |
| | | }) |
| | | |
| | | // 计ç®X, Yè½´åå§ä½ç§»ï¼ä½¿itemä¸å¿ç§»å¨å°ç¹å»å¤ï¼ååçæ¶åXè½´åå§ä¸åä½ç§» |
| | | state.translateX = basedata.columns === 1 ? 0 : touches.pageX - (basedata.itemWidth / 2 + basedata.left) |
| | | state.translateY = touches.pageY - (basedata.itemHeight / 2 + basedata.top) |
| | | state.touchId = touches.identifier |
| | | |
| | | instance.setStyle({ |
| | | 'transform': 'translate3d(' + state.translateX + 'px,' + state.translateY +'px, 0)' |
| | | }) |
| | | state.itemsInstance.forEach(function(item, index) { |
| | | item.removeClass("tn-drag__transition").removeClass("tn-drag__current") |
| | | item.addClass(index === state.current ? "tn-drag__current" : "tn-drag__transition") |
| | | }) |
| | | |
| | | ownerInstance.callMethod("vibrate") |
| | | state.dragging = true |
| | | } |
| | | |
| | | var touchStart = function(event, ownerInstance) { |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | edit = bool(dataset.edit) |
| | | } |
| | | |
| | | var touchMove = function(event, ownerInstance) { |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | var basedata = state.basedata |
| | | |
| | | if (!state.dragging || !edit) return |
| | | var touches = event.changedTouches[0] |
| | | if (!touches) return |
| | | |
| | | // 妿䏿¯åä¸ä¸ªè§¦åç¹åè¿å |
| | | if (state.touchId !== touches.identifier) return |
| | | |
| | | // 计ç®X,Yè½´ä½ç§», ååæ¶åXè½´åå§ä¸åä½ç§» |
| | | var translateX = basedata.columns === 1 ? 0 : touches.pageX - (basedata.itemWidth / 2 + basedata.left) |
| | | var translateY = touches.pageY - (basedata.itemHeight / 2 + basedata.top) |
| | | |
| | | // å°é¡¶å°ä½èªå¨æ»å¨ |
| | | if (touches.clientY > basedata.windowHeight - basedata.itemHeight - basedata.realBottomSize) { |
| | | // å½å触æ¸ç¹pageY + itemé«åº¦ - (å±å¹é«åº¦ - åºé¨åºå®åºåé«åº¦) |
| | | ownerInstance.callMethod('pageScroll', { |
| | | scrollTop: touches.pageY + basedata.itemHeight - (basedata.windowHeight - basedata.realBottomSize) |
| | | }) |
| | | } else if (touches.clientY < basedata.itemHeight + basedata.realTopSize) { |
| | | // å½å触æ¸ç¹pageY - itemé«åº¦ - é¡¶é¨åºå®åºåé« |
| | | ownerInstance.callMethod('pageScroll', { |
| | | scrollTop: touches.pageY - basedata.itemHeight - basedata.realTopSize |
| | | }) |
| | | } |
| | | |
| | | // 设置å½åæ¿æ´»å
ç´ çåç§»é |
| | | instance.setStyle({ |
| | | 'transform': 'translate3d('+ translateX + 'px,' + translateY + 'px, 0)' |
| | | }) |
| | | |
| | | var startKey = state.list[state.current].sortKey |
| | | var currentX = Math.round(translateX / basedata.itemWidth) |
| | | var currentY = Math.round(translateY / basedata.itemHeight) |
| | | var endKey = currentX + basedata.columns * currentY |
| | | |
| | | // ç®æ 项æ¶åºå®é¡¹åè¿å |
| | | var item = state.list[endKey] |
| | | if (item && item.fixed) return |
| | | |
| | | // Xè½´æè
Yè½´è¶
åºèå´åè¿å |
| | | if (isOutRange(currentX, basedata.columns, currentY, basedata.rows, endKey, state.list.length)) return |
| | | |
| | | // 鲿¢ææ½è¿ç¨ä¸åçä¹±åºé®é¢ |
| | | if (startKey === endKey || startKey === state.preStartKey) return |
| | | state.preStartKey = startKey |
| | | |
| | | var list = sortCore(startKey, endKey, state) |
| | | state.itemsInstance.forEach(function(itemInstance, index) { |
| | | var item = list[index] |
| | | if (index !== state.current) { |
| | | itemInstance.setStyle({ |
| | | 'transform': 'translate3d('+ item.translateX + ',' + item.translateY +', 0)' |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | // ownerInstance.callMethod('vibrate') |
| | | ownerInstance.callMethod('listDataChange', { |
| | | data: list |
| | | }) |
| | | triggerCustomEvent(list, "change", ownerInstance) |
| | | } |
| | | |
| | | var touchEnd = function(event, ownerInstance) { |
| | | var instance = event.instance |
| | | var dataset = instance.getDataset() |
| | | var state = ownerInstance.getState() |
| | | var basedata = state.basedata |
| | | |
| | | if (!state.dragging || !edit) return |
| | | triggerCustomEvent(state.list, "sortEnd", ownerInstance) |
| | | |
| | | instance.addClass('tn-drag__transition') |
| | | instance.setStyle({ |
| | | 'transform': 'translate3d('+ state.list[state.current].translateX + ',' + state.list[state.current].translateY + ', 0)' |
| | | }) |
| | | state.itemsInstance.forEach(function(item, index) { |
| | | item.removeClass('tn-drag__transition') |
| | | }) |
| | | |
| | | state.preStartKey = -1 |
| | | state.dragging = false |
| | | ownerInstance.callMethod('drag', { |
| | | dragging: false |
| | | }) |
| | | state.current = -1 |
| | | state.translateX = 0 |
| | | state.translateY = 0 |
| | | } |
| | | |
| | | module.exports = { |
| | | longPress: longPress, |
| | | touchStart: touchStart, |
| | | touchMove: touchMove, |
| | | touchEnd: touchEnd, |
| | | baseDataObserver: baseDataObserver, |
| | | listObserver: listObserver |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-drag-class tn-drag" |
| | | :style="{ |
| | | height: wrapHeight + 'rpx' |
| | | }" |
| | | :list="listData" |
| | | :basedata="baseData" |
| | | :change:list="wxs.listObserver" |
| | | :change:basedata="wxs.baseDataObserver" |
| | | > |
| | | <!-- #ifdef MP-WEIXIN --> |
| | | <view |
| | | v-for="(item, index) in listData" |
| | | :key="item.id" |
| | | class="tn-drag__item" |
| | | :style="{ |
| | | width: 100 / columns + '%', |
| | | height: itemHeight + 'rpx' |
| | | }" |
| | | :data-index="index" |
| | | :data-basedata="baseData" |
| | | :data-edit="edit" |
| | | @longpress="wxs.longPress" |
| | | @touchstart="wxs.touchStart" |
| | | :catch:touchmove="dragging?wxs.touchMove:''" |
| | | :catch:touchend="dragging?wxs.touchEnd:''" |
| | | > |
| | | <slot :entity="item.data" :fixed="item.fixed" :index="index" :height="itemHeight" :isEdit="edit"></slot> |
| | | </view> |
| | | <!-- #endif --> |
| | | |
| | | <!-- #ifndef MP-WEIXIN --> |
| | | <view |
| | | v-for="(item, index) in listData" |
| | | :key="item.id" |
| | | class="tn-drag__item" |
| | | :style="{ |
| | | width: 100 / columns + '%', |
| | | height: itemHeight + 'rpx' |
| | | }" |
| | | @longpress="wxs.longPress" |
| | | :data-index="index" |
| | | :data-basedata="baseData" |
| | | :data-edit="edit" |
| | | @touchstart="wxs.touchStart" |
| | | @touchmove="wxs.touchMove" |
| | | @touchend="wxs.touchEnd" |
| | | > |
| | | <slot :entity="item.data" :fixed="item.fixed" :index="index" :height="itemHeight" :isEdit="edit"></slot> |
| | | </view> |
| | | <!-- #endif --> |
| | | </view> |
| | | </template> |
| | | <script src="./index.wxs" lang="wxs" module="wxs"></script> |
| | | <script> |
| | | export default { |
| | | name: 'tn-drag', |
| | | props: { |
| | | // æ°æ®æº |
| | | // 妿屿§ä¸å
å«fixedï¼åæ è¯å½åæ°æ®ä¸å
许æå¨ |
| | | list: { |
| | | type: Array, |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | // æ¯å¦å
许æå¨ç¼è¾ |
| | | edit: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // åæ° |
| | | columns: { |
| | | type: Number, |
| | | default: 3 |
| | | }, |
| | | // itemå
ç´ é«åº¦, åä½rpx |
| | | itemHeight: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å½åç¶å
ç´ æ»å¨çé«åº¦ |
| | | scrollTop: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | wrapHeight() { |
| | | return this.rows * this.itemHeight |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // æªæ¸²æåèç¹æ°æ® |
| | | baseData: {}, |
| | | // æå¨åçæ°æ® |
| | | dragData: [], |
| | | // è¡æ° |
| | | rows: 0, |
| | | // æ¸²ææ°æ® |
| | | listData: [], |
| | | // æ è®°æ¯å¦æ£å¨æå¨ |
| | | dragging: false |
| | | } |
| | | }, |
| | | watch: { |
| | | list(val) { |
| | | this.listData = [] |
| | | this.$nextTick(() => { |
| | | this.init() |
| | | }) |
| | | }, |
| | | columns(val) { |
| | | this.listData = [] |
| | | this.$nextTick(() => { |
| | | this.init() |
| | | }) |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.init() |
| | | }) |
| | | }, |
| | | methods: { |
| | | // åå§å |
| | | init() { |
| | | this.dragging = true |
| | | const initDragItem = item => { |
| | | const obj = { |
| | | ...item |
| | | } |
| | | const fixed = obj?.fixed || false |
| | | delete obj["fixed"] |
| | | return { |
| | | id: this.unique(), |
| | | fixed, |
| | | data: { |
| | | ...obj |
| | | } |
| | | } |
| | | } |
| | | |
| | | let i = 0 |
| | | const listData = (this.list || []).map((item, index) => { |
| | | let listItem = initDragItem(item) |
| | | // çå®æåº |
| | | listItem.realKey = i++ |
| | | // æ´ä½æåº |
| | | listItem.sortKey = index |
| | | listItem.translateX = `${(listItem.sortKey % this.columns) * 100}%` |
| | | listItem.translateY = `${Math.floor(listItem.sortKey / this.columns) * 100}%` |
| | | return listItem |
| | | }) |
| | | this.rows = Math.ceil(listData.length / this.columns) |
| | | this.listData = listData |
| | | this.dragData = listData |
| | | |
| | | if (listData.length === 0) return |
| | | // console.log(listData); |
| | | |
| | | // åå§ådomå
ç´ |
| | | this.$nextTick(() => { |
| | | this.initRect() |
| | | }) |
| | | }, |
| | | // åå§ådomå
ç´ |
| | | initRect() { |
| | | const { |
| | | windowWidth, |
| | | windowHeight |
| | | } = uni.getSystemInfoSync() |
| | | |
| | | let baseData = {} |
| | | baseData.windowHeight = windowHeight |
| | | baseData.realTopSize = 0 |
| | | baseData.realBottomSize = 0 |
| | | baseData.columns = this.columns |
| | | baseData.rows = this.rows |
| | | |
| | | const query = uni.createSelectorQuery().in(this) |
| | | query.select('.tn-drag').boundingClientRect() |
| | | query.select('.tn-drag__item').boundingClientRect() |
| | | query.exec(res => { |
| | | if (!res) { |
| | | setTimeout(() => { |
| | | this.initRect() |
| | | }, 10) |
| | | return |
| | | } |
| | | |
| | | baseData.itemWidth = res[1].width |
| | | baseData.itemHeight = res[1].height |
| | | baseData.left = res[0].left |
| | | baseData.top = res[0].top + this.scrollTop |
| | | this.dragging = false |
| | | this.baseData = baseData |
| | | }) |
| | | |
| | | }, |
| | | |
| | | // 触åéå¨ |
| | | vibrate() { |
| | | uni.vibrateShort() |
| | | }, |
| | | // æ»å¨å°æå®çä½ç½® |
| | | pageScroll(e) { |
| | | uni.pageScrollTo({ |
| | | scrollTop: e.scrollTop, |
| | | duration: 0 |
| | | }) |
| | | }, |
| | | // ä¿®æ¹æå¨ç¶æ |
| | | drag(e) { |
| | | this.dragging = e.dragging |
| | | }, |
| | | // ææ½æ°æ®åçæ¹å |
| | | listDataChange(e) { |
| | | this.dragData = e.data |
| | | }, |
| | | // item被ç¹å» |
| | | itemClick(index) { |
| | | const item = this.dragData[index] |
| | | this.$emit('click', { |
| | | key: item.realKey, |
| | | data: item.data |
| | | }) |
| | | }, |
| | | |
| | | // ææ½ç»æäºä»¶ |
| | | sortEnd(e) { |
| | | this.$emit('end', { |
| | | data: e.data |
| | | }) |
| | | }, |
| | | // æåºåçæ¹åäºä»¶ |
| | | change(e) { |
| | | this.$emit('change', { |
| | | data: e.data |
| | | }) |
| | | }, |
| | | |
| | | // çæå
ç´ å¯ä¸id |
| | | unique(n = 6) { |
| | | let id = '' |
| | | for (let i = 0; i < n; i++) id += Math.floor(Math.random() * 10) |
| | | return 'tn_' + new Date().getTime() + id |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-drag { |
| | | position: relative; |
| | | |
| | | &__item { |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | left: 0; |
| | | } |
| | | |
| | | &__transition { |
| | | transition: transform 0.25s !important; |
| | | } |
| | | |
| | | &__current { |
| | | z-index: 10 !important; |
| | | } |
| | | |
| | | &__fixed { |
| | | z-index: 1 !important; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="show" class="tn-empty-class tn-empty" :style="[emptyStyle]"> |
| | | <view |
| | | v-if="!isImage" |
| | | class="tn-empty__icon" |
| | | :class="[icon ? `tn-icon-${icon}` : `tn-icon-empty-${mode}`]" |
| | | :style="[iconStyle]" |
| | | ></view> |
| | | <image |
| | | v-else |
| | | class="tn-empty__image" |
| | | :style="[imageStyle]" |
| | | :src="icon" |
| | | mode="widthFix" |
| | | ></image> |
| | | |
| | | <view |
| | | class="tn-empty__text" |
| | | :style="[textStyle]" |
| | | >{{ text ? text : icons[mode]}}</view> |
| | | <view v-if="$slots.default || $slots.$default" class="tn-empty__slot"> |
| | | <slot/> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-empty', |
| | | props: { |
| | | // æ¾ç¤ºç©ºç½é¡µ |
| | | show: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å
ç½®iconçåç§° |
| | | // å¾çè·¯å¾ï¼å»ºè®®ä½¿ç¨ç»å¯¹è·¯å¾ |
| | | icon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // é¢ç½®å¾æ ç±»å |
| | | mode: { |
| | | type: String, |
| | | default: 'data' |
| | | }, |
| | | // æç¤ºæå |
| | | text: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æåé¢è² |
| | | textColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æå大å°ï¼åä½rpx |
| | | textSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // 徿 é¢è² |
| | | iconColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 徿 大å°ï¼åä½rpx |
| | | iconSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å¾ç宽度ï¼å½å¾æ 为å¾çæ¶çæï¼ï¼åä½rpx |
| | | imgWidth: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å¾çé«åº¦ï¼å½å¾æ 为å¾çæ¶çæï¼ï¼åä½rpx |
| | | imgHeight: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // èªå®ä¹ç»ä»¶æ ·å¼ |
| | | customStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | emptyStyle() { |
| | | let style = {} |
| | | Object.assign(style, this.customStyle) |
| | | return style |
| | | }, |
| | | iconStyle() { |
| | | let style = {} |
| | | if (this.iconSize) { |
| | | style.fontSize = this.iconSize + 'rpx' |
| | | } |
| | | if (this.iconColor) { |
| | | style.color = this.iconColor |
| | | } |
| | | return style |
| | | }, |
| | | imageStyle() { |
| | | let style = {} |
| | | if (this.imgWidth) { |
| | | style.width = this.imgWidth + 'rpx' |
| | | } |
| | | if (this.imgHeight) { |
| | | style.height = this.imgHeight + 'rpx' |
| | | } |
| | | return style |
| | | }, |
| | | textStyle() { |
| | | let style = {} |
| | | if (this.textColor) { |
| | | style.color = this.textColor |
| | | } |
| | | if (this.textSize) { |
| | | style.fontSize = this.textSize + 'rpx' |
| | | } |
| | | return style |
| | | }, |
| | | // å¤æä¼ éçiconæ¯å¦ä¸ºå¾ç |
| | | isImage() { |
| | | return this.icon.indexOf('/') >= 0 |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | icons: { |
| | | cart: 'è´ç©è½¦ä¸ºç©º', |
| | | page: '页é¢ä¸åå¨', |
| | | search: 'æç´¢ç»æä¸ºç©º', |
| | | address: 'å°å为空', |
| | | network: 'ç½ç»ä¸é', |
| | | order: '订å为空', |
| | | coupon: '伿 å¸ä¸ºç©º', |
| | | favor: 'ææ æ¶è', |
| | | permission: 'æ æé', |
| | | history: 'åå²è®°å½ä¸ºç©º', |
| | | message: 'ææ æ¶æ¯', |
| | | list: 'å表为空', |
| | | data: 'ææ æ°æ®', |
| | | comment: 'ææ è¯è®º' |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-empty { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | &__icon { |
| | | margin-top: 14rpx; |
| | | color: #AAAAAA; |
| | | font-size: 90rpx; |
| | | } |
| | | |
| | | &__image { |
| | | width: 160rpx; |
| | | height: 160rpx; |
| | | } |
| | | |
| | | &__text { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: 20rpx; |
| | | color: #AAAAAA; |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | &__slot { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: 20rpx; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-fab-class tn-fab" @touchmove.stop.prevent> |
| | | <view |
| | | class="tn-fab__box" |
| | | :class="{'tn-fab--right': left === 'auto'}" |
| | | :style="{ |
| | | left: $t.string.getLengthUnitValue(fabLeft || left), |
| | | right: $t.string.getLengthUnitValue(fabRight || right), |
| | | bottom: $t.string.getLengthUnitValue(fabBottom || bottom), |
| | | zIndex: elZIndex |
| | | }" |
| | | > |
| | | <view |
| | | v-if="visibleSync" |
| | | class="tn-fab__btns" |
| | | :class="[`tn-fab__btns__animation--${animationType}`, |
| | | showFab ? `tn-fab__btns--visible--${animationType}` : '' |
| | | ]" |
| | | > |
| | | <view |
| | | v-for="(item, index) in btnList" |
| | | :key="index" |
| | | class="tn-fab__item" |
| | | :class="[ |
| | | `tn-fab__item__animation--${animationType}`, |
| | | {'tn-fab__item--left': right === 'auto'} |
| | | ]" |
| | | :style="[fabItemStyle(index)]" |
| | | @tap.stop="handleClick(index)" |
| | | > |
| | | <!-- 另徿 æè
å¾çæ¶æ¾ç¤ºçæåä¿¡æ¯ --> |
| | | <view |
| | | v-if="animationType !== 'around' && (item.imgUrl || item.icon)" |
| | | :class="[left === 'auto' ? 'tn-fab__item__text--right' : 'tn-fab__item__text--left']" |
| | | :style="{ |
| | | color: item.textColor || '#FFF', |
| | | fontSize: $t.string.getLengthUnitValue(item.textSize || 28) |
| | | }" |
| | | >{{ item.text || '' }}</view> |
| | | |
| | | <!-- 带å¾çæè
徿 æ¶çå¾çã徿 ä¿¡æ¯ --> |
| | | <view |
| | | class="tn-fab__item__btn" |
| | | :class="[!item.bgColor ? backgroundColorClass : '']" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: $t.string.getLengthUnitValue(height), |
| | | lineHeight: $t.string.getLengthUnitValue(height), |
| | | backgroundColor: item.bgColor || backgroundColorStyle || '#01BEFF', |
| | | borderRadius: $t.string.getLengthUnitValue(radius) |
| | | }" |
| | | > |
| | | <!-- æ å¾çåæ å¾æ æ¶åªæ¾ç¤ºæå --> |
| | | <view |
| | | v-if="!item.imgUrl && !item.icon" |
| | | class="tn-fab__item__btn__title" |
| | | :style="{ |
| | | color: item.textColor || '#fff', |
| | | fontSize: $t.string.getLengthUnitValue(item.textSize || 28) |
| | | }" |
| | | >{{ item.text || '' }}</view> |
| | | <!-- 徿 --> |
| | | <view |
| | | v-if="item.icon" |
| | | class="tn-fab__item__btn__icon" |
| | | :class="[`tn-icon-${item.icon}`]" |
| | | :style="{ |
| | | color: item.iconColor || '#fff', |
| | | fontSize: $t.string.getLengthUnitValue(item.iconSize || iconSize || 64) |
| | | }" |
| | | ></view> |
| | | <!-- å¾ç --> |
| | | <image |
| | | v-else-if="!item.icon && item.imgUrl" |
| | | class="tn-fab__item__btn__image" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(item.imgWidth || 64), |
| | | height: $t.string.getLengthUnitValue(item.imgHeight || 64), |
| | | }" |
| | | :src="item.imgUrl" |
| | | ></image> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-fab__item__btn tn-fab__item__btn--fab" |
| | | :class="[backgroundColorClass, fontColorClass, {'tn-fab__item__btn--active': showFab}]" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: $t.string.getLengthUnitValue(height), |
| | | backgroundColor: backgroundColorStyle || !backgroundColorClass ? '#01BEFF' : '', |
| | | color: fontColorStyle || '#fff', |
| | | borderRadius: $t.string.getLengthUnitValue(radius), |
| | | zIndex: elZIndex - 1 |
| | | }" |
| | | @tap.stop="fabClick" |
| | | > |
| | | <slot> |
| | | <view class="tn-fab__item__btn__icon" :class="[`tn-icon-${icon}`]" :style="{fontSize: $t.string.getLengthUnitValue(iconSize || 64)}"></view> |
| | | </slot> |
| | | </view> |
| | | </view> |
| | | <view v-if="visibleSync && showMask" class="tn-fab__mask" :class="{'tn-fab__mask--visible': showFab}" :style="{zIndex: elZIndex - 3}" @tap="clickMask()"></view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-fab', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // æé®å表 |
| | | // { |
| | | // // èæ¯é¢è² |
| | | // bgColor: '#fff', |
| | | // // å¾çå°å |
| | | // imgUrl: '', |
| | | // // å¾ç宽度 |
| | | // imgWidth: 60, |
| | | // // å¾çé«åº¦ |
| | | // imgHeight: 60, |
| | | // // 徿 åç§° |
| | | // icon: '', |
| | | // // 徿 尺寸 |
| | | // iconSize: 60, |
| | | // // 徿 é¢è² |
| | | // iconColor: '#fff', |
| | | // // æç¤ºæå |
| | | // text: '', |
| | | // // æåå¤§å° |
| | | // textSize: 30, |
| | | // // åä½é¢è² |
| | | // textColor: '#fff' |
| | | // } |
| | | btnList: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // èªå®ä¹æ¬æµ®æé®å
容 |
| | | customBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¬æµ®æé®ç宽度 |
| | | width: { |
| | | type: [String, Number], |
| | | default: 88 |
| | | }, |
| | | // æ¬æµ®æé®çé«åº¦ |
| | | height: { |
| | | type: [String, Number], |
| | | default: 88 |
| | | }, |
| | | // 徿 å¤§å° |
| | | iconSize: { |
| | | type: [String, Number], |
| | | default: 64 |
| | | }, |
| | | // 徿 åç§° |
| | | icon: { |
| | | type: String, |
| | | default: 'open' |
| | | }, |
| | | // æé®åè§ |
| | | radius: { |
| | | type: [String, Number], |
| | | default: '50%' |
| | | }, |
| | | // æé®è·ç¦»å·¦è¾¹çä½ç½® |
| | | left: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | }, |
| | | // æé®è·ç¦»å³è¾¹çä½ç½® |
| | | right: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | }, |
| | | // æé®è·ç¦»åºé¨çä½ç½® |
| | | bottom: { |
| | | type: [String, Number], |
| | | default: 100 |
| | | }, |
| | | // å±ç¤ºå¨ç»ç±»å up å¾ä¸å±ç¤º around ç¯ç» |
| | | animationType: { |
| | | type: String, |
| | | default: 'up' |
| | | }, |
| | | // å½å¨ç»ä¸ºåç¯æ¶ï¼æ¯ä¸ªå¼¹åºæé®ä¹é´çè·ç¦», åä½px |
| | | aroundBtnDistance: { |
| | | type: Number, |
| | | default: 10 |
| | | }, |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¾ç¤ºé®ç½© |
| | | showMask: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ç¹å»é®ç½©æ¯å¦å¯ä»¥å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | showFab: false, |
| | | visibleSync: false, |
| | | timer: null, |
| | | fabLeft: 0, |
| | | fabRight: 0, |
| | | fabBottom: 0, |
| | | fabBtnInfo: { |
| | | width: 0, |
| | | height: 0, |
| | | left: 0, |
| | | right: 0, |
| | | bottom: 0 |
| | | }, |
| | | systemInfo: { |
| | | width: 0, |
| | | height: 0 |
| | | }, |
| | | updateProps: false |
| | | } |
| | | }, |
| | | computed: { |
| | | elZIndex() { |
| | | return this.zIndex || this.$t.zIndex.fab |
| | | }, |
| | | propsData() { |
| | | return [this.width, this.height, this.left, this.right, this.bottom] |
| | | }, |
| | | fabItemStyle() { |
| | | return (index) => { |
| | | let style = { |
| | | zIndex: this.elZIndex - 2 |
| | | } |
| | | if (this.animationType === 'up' || !this.showFab) { |
| | | return style |
| | | } |
| | | let base = 1 |
| | | if (this.left === 'auto') { |
| | | base = 1 |
| | | } else if (this.right === 'auto') { |
| | | base = -1 |
| | | } |
| | | style.transform = `rotate(${base * index * 60}deg) translateX(${(this.aroundBtnDistance + this.fabBtnInfo.width) * (-(base))}px)` |
| | | return style |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | propsData() { |
| | | // æ´æ°æé®ä¿¡æ¯ |
| | | this.updateProps = true |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.getFabBtnRectInfo() |
| | | }) |
| | | }, |
| | | beforeDestroy() { |
| | | if (this.timer) { |
| | | clearTimeout(this.timer) |
| | | } |
| | | }, |
| | | methods: { |
| | | // æé®ç¹å»äºä»¶ |
| | | handleClick(index) { |
| | | this.close() |
| | | this.$emit('click', {index: index}) |
| | | }, |
| | | // ç¹å»æ¬æµ®æé® |
| | | fabClick() { |
| | | if (this.showFab) { |
| | | this.close() |
| | | } else { |
| | | // console.log(this.visibleSync); |
| | | if (this.visibleSync) { |
| | | this.visibleSync = false |
| | | return |
| | | } |
| | | this.open() |
| | | } |
| | | }, |
| | | // ç¹å»é®ç½© |
| | | clickMask() { |
| | | if (!this.showMask || !this.maskCloseable) return |
| | | this.close() |
| | | }, |
| | | |
| | | open() { |
| | | this.change('visibleSync', 'showFab', true) |
| | | this.translateFabPosition() |
| | | }, |
| | | close() { |
| | | this.change('showFab', 'visibleSync', false) |
| | | this.fabLeft = 0 |
| | | this.fabRight = 0 |
| | | this.fabBottom = 0 |
| | | }, |
| | | // å
³éæ¶å
éè¿å¨ç»éèå¼¹çªåé®ç½©ï¼åç§»é¤æ´ä¸ªç»ä»¶ |
| | | // æå¼æ¶ï¼å
渲æç»ä»¶ï¼å»¶æ¶ä¸å®æ¶é´å让é®ç½©åå¼¹çªçå¨ç»èµ·ä½ç¨ |
| | | change(param1, param2, status) { |
| | | this[param1] = status |
| | | if (status) { |
| | | // #ifdef H5 || MP |
| | | this.timer = setTimeout(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | clearTimeout(this.timer) |
| | | }, 10) |
| | | // #endif |
| | | // #ifndef H5 || MP |
| | | this.$nextTick(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | }) |
| | | // #endif |
| | | } else { |
| | | this.timer = setTimeout(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | clearTimeout(this.timer) |
| | | }, 250) |
| | | } |
| | | }, |
| | | |
| | | /******************** æè½¬å¨ç»ç¸å
³å½æ° ********************/ |
| | | // è·åæé®çä¿¡æ¯ |
| | | async getFabBtnRectInfo() { |
| | | const systemInfo = uni.getSystemInfoSync() |
| | | const btnRectInfo = await this._tGetRect('.tn-fab__item__btn--fab') |
| | | if (!btnRectInfo) { |
| | | setTimeout(() => { |
| | | this.getFabBtnRectInfo() |
| | | }, 10) |
| | | return |
| | | } |
| | | console.log(btnRectInfo); |
| | | this.systemInfo = { |
| | | width: systemInfo.windowWidth, |
| | | height: systemInfo.windowHeight |
| | | } |
| | | this.fabBtnInfo.width = btnRectInfo.width |
| | | this.fabBtnInfo.height = btnRectInfo.height |
| | | this.fabBtnInfo.left = btnRectInfo.left |
| | | this.fabBtnInfo.right = btnRectInfo.right |
| | | this.fabBtnInfo.bottom = btnRectInfo.bottom |
| | | }, |
| | | // æ´æ°æ¬æµ®æé®çä½ç½® |
| | | translateFabPosition() { |
| | | if (this.updateProps) { |
| | | this.getFabBtnRectInfo() |
| | | this.updateProps = false |
| | | } |
| | | if (this.animationType === 'up') return |
| | | // æé®ç»ç宽度 |
| | | const btnGroupWidth = this.fabBtnInfo.width + this.aroundBtnDistance + 10 |
| | | // 夿å½åæé®æ¯å¨å·¦è¾¹è¿æ¯å³è¾¹ |
| | | if (this.left === 'auto' && btnGroupWidth > this.systemInfo.width - this.fabBtnInfo.right) { |
| | | // è·ç¦»ä¸å¤éè¦ç§»å¨ |
| | | this.fabRight = btnGroupWidth + 'px' |
| | | } else if (this.right === 'auto' && btnGroupWidth > this.fabBtnInfo.left) { |
| | | this.fabLeft = btnGroupWidth + 'px' |
| | | } |
| | | |
| | | if (btnGroupWidth > this.systemInfo.height - this.fabBtnInfo.bottom) { |
| | | this.fabBottom = btnGroupWidth + 'px' |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-fab { |
| | | &__box { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | flex-direction: column; |
| | | position: fixed; |
| | | transition: all 0.25s ease-in-out; |
| | | } |
| | | |
| | | &--right { |
| | | align-items: flex-end; |
| | | } |
| | | |
| | | &__btns { |
| | | transition: all 0.25s cubic-bezier(0,.13,0,1.43); |
| | | transform-origin: 80% bottom; |
| | | |
| | | &__animation--up { |
| | | opacity: 0; |
| | | transform: translateY(100%); |
| | | } |
| | | &__animation--around { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | } |
| | | |
| | | &--visible--up { |
| | | // visibility: visible; |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | &--visible--around { |
| | | // visibility: visible; |
| | | // opacity: 1; |
| | | } |
| | | } |
| | | |
| | | &__item { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | padding-bottom: 20rpx; |
| | | |
| | | &__animation--around { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | transition: transform 0.25s ease-in-out; |
| | | transform-origin: 50% 50%; |
| | | padding-bottom: 0 !important; |
| | | } |
| | | |
| | | &--left { |
| | | flex-flow: row-reverse; |
| | | } |
| | | |
| | | &__text { |
| | | &--left { |
| | | padding-left: 14rpx; |
| | | } |
| | | &--right { |
| | | padding-right: 14rpx; |
| | | } |
| | | } |
| | | |
| | | &__btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 0 5rpx 2rpx rgba(0, 0, 0, 0.07); |
| | | transition: all 0.2s linear; |
| | | |
| | | &--active { |
| | | animation-name: fab-button-animation; |
| | | animation-duration: 0.2s; |
| | | animation-timing-function: cubic-bezier(0,.13,0,1.43); |
| | | } |
| | | |
| | | &__title { |
| | | width: 90%; |
| | | text-align: center; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | &__icon { |
| | | text-align: center; |
| | | font-size: 64rpx; |
| | | } |
| | | |
| | | &__image { |
| | | display: block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__mask { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: $tn-mask-bg-color; |
| | | transition: all 0.2s ease-in-out; |
| | | opacity: 0; |
| | | |
| | | &--visible { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @keyframes fab-button-animation { |
| | | 0% { |
| | | transform: scale(0.6); |
| | | } |
| | | // 20% { |
| | | // transform: scale(1.8); |
| | | // } |
| | | // 40% { |
| | | // transform: scale(0.4); |
| | | // } |
| | | // 50% { |
| | | // transform: scale(1.4); |
| | | // } |
| | | // 80% { |
| | | // transform: scale(0.8); |
| | | // } |
| | | 100% { |
| | | transform: scale(1); |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-form-item-class tn-form-item" |
| | | :class="{ |
| | | 'tn-border-solid-bottom': elBorderBottom, |
| | | 'tn-form-item__border-bottom--error': validateState === 'error' && showError('border-bottom') |
| | | }" |
| | | > |
| | | <view |
| | | class="tn-form-item__body" |
| | | :style="{ |
| | | flexDirection: elLabelPosition == 'left' ? 'row' : 'column' |
| | | }" |
| | | > |
| | | <!-- å¤ç微信å°ç¨åºä¸è®¾ç½®å±æ§çé®é¢ï¼ä¸è®¾ç½®å¼çæ¶åä¼åætrue --> |
| | | <view |
| | | class="tn-form-item--left" |
| | | :style="{ |
| | | width: wLabelWidth, |
| | | flex: `0 0 ${wLabelWidth}`, |
| | | marginBottom: elLabelPosition == 'left' ? 0 : '10rpx' |
| | | }" |
| | | > |
| | | <!-- åå¯¹é½ --> |
| | | <view v-if="required || leftIcon || label" class="tn-form-item--left__content" |
| | | :style="[leftContentStyle]" |
| | | > |
| | | <!-- nvue䏿¯æä¼ªå
ç´ before --> |
| | | <view v-if="leftIcon" class="tn-form-item--left__content__icon"> |
| | | <view :class="[`tn-icon-${leftIcon}`]" :style="leftIconStyle"></view> |
| | | </view> |
| | | <!-- <view |
| | | class="tn-form-item--left__content__label" |
| | | :style="[elLabelStyle, { |
| | | 'justify-content': elLabelAlign === 'left' ? 'flex-satrt' : elLabelAlign === 'center' ? 'center' : 'flex-end' |
| | | }]" |
| | | > |
| | | {{label}} |
| | | </view> --> |
| | | <view |
| | | class="tn-form-item--left__content__label" |
| | | :style="[elLabelStyle]" |
| | | > |
| | | {{label}} |
| | | </view> |
| | | <text v-if="required" class="tn-form-item--left__content--required">*</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="tn-form-item--right tn-flex"> |
| | | <view class="tn-form-item--right__content"> |
| | | <view class="tn-form-item--right__content__slot"> |
| | | <slot></slot> |
| | | </view> |
| | | <view v-if="$slots.right || rightIcon" class="tn-form-item--right__content__icon tn-flex"> |
| | | <view v-if="rightIcon" :class="[`tn-icon-${rightIcon}`]" :style="rightIconStyle"></view> |
| | | <slot name="right"></slot> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view |
| | | v-if="validateState === 'error' && showError('message')" |
| | | class="tn-form-item__message" |
| | | :style="{ |
| | | paddingLeft: elLabelPosition === 'left' ? elLabelWidth + 'rpx' : '0' |
| | | }" |
| | | > |
| | | {{validateMessage}} |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Emitter from '../../libs/utils/emitter.js' |
| | | import schema from '../../libs/utils/async-validator.js' |
| | | // å»é¤è¦åä¿¡æ¯ |
| | | schema.warning = function() {} |
| | | |
| | | export default { |
| | | mixins: [Emitter], |
| | | name: 'tn-form-item', |
| | | inject: { |
| | | tnForm: { |
| | | default() { |
| | | return null |
| | | } |
| | | } |
| | | }, |
| | | props: { |
| | | // labelæç¤ºè¯ |
| | | label: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ç»å®çå¼ |
| | | prop: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¡¨ååçä¸åçº¿è¾¹æ¡ |
| | | borderBottom: { |
| | | type:Boolean, |
| | | default: true |
| | | }, |
| | | // label(æ ç¾åç§°)çä½ç½® |
| | | // left - 左边 |
| | | // top - ä¸è¾¹ |
| | | labelPosition: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // labelç宽度 |
| | | labelWidth: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // labelç坹齿¹å¼ |
| | | // left - å·¦å¯¹é½ |
| | | // top - ä¸å¯¹é½ |
| | | // right - å³å¯¹é½ |
| | | // bottom - ä¸å¯¹é½ |
| | | labelAlign: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // label çæ ·å¼ |
| | | labelStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // 左侧徿 |
| | | leftIcon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å³ä¾§å¾æ |
| | | rightIcon: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 左侧徿 æ ·å¼ |
| | | leftIconStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // å³ä¾§å¾æ æ ·å¼ |
| | | rightIconStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå¿
填项ç*ï¼ä¸åæ ¡éªç¨é |
| | | required: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // å¤ç微信å°ç¨åºlabelç宽度 |
| | | wLabelWidth() { |
| | | // å¦æç¨æ·è®¾ç½®label为空å符串(微信å°ç¨åºç©ºå符串æç»ä¼åæå符串ç'true')ï¼æå³çè¦å°labelçä½ç½®å®½åº¦è®¾ç½®ä¸ºauto |
| | | return this.elLabelPosition === 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.elLabelWidth + 'rpx') : '100%' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé误æç¤º |
| | | showError() { |
| | | return type => { |
| | | if (this.errorType.indexOf('none') >= 0) return false |
| | | else if (this.errorType.indexOf(type) >= 0) return true |
| | | else return false |
| | | } |
| | | }, |
| | | // labelç宽度(é»è®¤å¼ä¸º90) |
| | | elLabelWidth() { |
| | | return this.labelWidth != 0 ? this.labelWidth : (this.parentData.labelWidth != 0 ? this.parentData.labelWidth : 90) |
| | | }, |
| | | // labelçæ ·å¼ |
| | | elLabelStyle() { |
| | | return Object.keys(this.labelStyle).length ? this.labelStyle : (Object.keys(this.parentData.labelStyle).length ? this.parentData.labelStyle : {}) |
| | | }, |
| | | // labelæ¾ç¤ºä½ç½® |
| | | elLabelPosition() { |
| | | return this.labelPosition ? this.labelPosition : (this.parentData.labelPosition ? this.parentData.labelPosition : 'left') |
| | | }, |
| | | // label坹齿¹å¼ |
| | | elLabelAlign() { |
| | | return this.labelAlign ? this.labelAlign : (this.parentData.labelAlign ? this.parentData.labelAlign : 'left') |
| | | }, |
| | | // labelä¸å线 |
| | | elBorderBottom() { |
| | | return this.borderBottom !== '' ? this.borderBottom : (this.parentData.borderBottom !== '' ? this.parentData.borderBottom : true) |
| | | }, |
| | | leftContentStyle() { |
| | | let style = {} |
| | | if (this.elLabelPosition === 'left') { |
| | | switch(this.elLabelAlign) { |
| | | case 'left': |
| | | style.justifyContent = 'flex-start' |
| | | break |
| | | case 'center': |
| | | style.justifyContent = 'center' |
| | | break |
| | | default: |
| | | style.justifyContent = 'flex-end' |
| | | break |
| | | } |
| | | } |
| | | |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // é»è®¤å¼ |
| | | initialValue: '', |
| | | // æ¯å¦æ ¡éªæå |
| | | validateState: '', |
| | | // æ ¡éªå¤±è´¥æç¤ºä¿¡æ¯ |
| | | validateMessage: '', |
| | | // é误çæç¤ºæ¹å¼ï¼åèformç»ä»¶ï¼ |
| | | errorType: ['message'], |
| | | // å½ååç»ä»¶è¾å
¥çå¼ |
| | | fieldValue: '', |
| | | // ç¶ç»ä»¶çåæ° |
| | | // ç±äºåcomputed䏿 æ³å¾ç¥this.parentçååï¼æä»¥æ¾å¨dataä¸ |
| | | parentData: { |
| | | borderBottom: true, |
| | | labelWidth: 90, |
| | | labelPosition: 'left', |
| | | labelAlign: 'left', |
| | | labelStyle: {}, |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | validateState(val) { |
| | | this.broadcastInputError() |
| | | }, |
| | | "tnForm.errorType"(val) { |
| | | this.errorType = val |
| | | this.broadcastInputError() |
| | | } |
| | | }, |
| | | mounted() { |
| | | // ç»ä»¶åå»ºå®æåï¼ä¿åå½åå®ä¾å°formç»ä»¶ä¸ |
| | | // æ¯ä»å®ã头æ¡å°ç¨åºä¸æ¯æprovide/injectï¼æä»¥ä½¿ç¨è¿ä¸ªæ¹æ³è·åæ´ä¸ªç¶ç»ä»¶ï¼å¨createdå®ä¹ï¼é¿å
循ç¯åºç¨\ |
| | | this.parent = this.$t.$parent.call(this, 'tn-form') |
| | | if (this.parent) { |
| | | // éåparentData屿§ï¼å°parentä¸ååç屿§èµå¼ç»parentData |
| | | Object.keys(this.parentData).map(key => { |
| | | this.parentData[key] = this.parent[key] |
| | | }) |
| | | // å¦ææ²¡æä¼ å
¥propæè
tnForm为空ï¼åç¬ä½¿ç¨form-itemç»ä»¶çæ¶åï¼ï¼å°±ä¸è¿è¡æ ¡éª |
| | | if (this.prop) { |
| | | // å°æ¬å®ä¾æ·»å å°ç¶ç»ä»¶ä¸ |
| | | this.parent.fields.push(this) |
| | | this.errorType = this.parent.errorType |
| | | // 设置åå§å¼ |
| | | this.initialValue = this.fieldValue |
| | | // æ·»å è¡¨åæ ¡éªï¼è¿éå¿
é¡»è¦åå¨$nextTickä¸ï¼å 为tn-formçrulesæ¯éè¿refæå¨ä¼ å
¥ç |
| | | // ä¸å¨$nextTickä¸çè¯ï¼å¯è½ä¼é ææ§è¡æ¤å¤ä»£ç æ¶ï¼ç¶ç»ä»¶è¿æ²¡éè¿refæè§åç»tn-formï¼å¯¼è´è§å为空 |
| | | this.$nextTick(() => { |
| | | this.setRules() |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | // ç»ä»¶éæ¯åï¼å°å®ä¾ä»tn-formçç¼åä¸ç§»é¤ |
| | | // 妿å½å没æpropçè¯è¡¨ç¤ºå½åä¸è¿è¡å é¤ |
| | | if (this.parent && this.prop) { |
| | | this.parent.fields.map((item, index) => { |
| | | if (item === this) this.parent.fields.splice(index, 1) |
| | | }) |
| | | } |
| | | }, |
| | | methods: { |
| | | // åinputç»ä»¶ååºé误äºä»¶ |
| | | broadcastInputError() { |
| | | this.broadcast('tn-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border')) |
| | | }, |
| | | // è®¾ç½®æ ¡éªè§å |
| | | setRules() { |
| | | let that = this |
| | | // ä»ç¶ç»ä»¶tn-formæ¿å°å½åtn-form-iteméè¦éªè¯ çè§å |
| | | // let rules = this.getRules() |
| | | // if (rules.length) { |
| | | // this.isRequired = rules.some(rule => { |
| | | // // 妿æå¿
填项ï¼å°±è¿åï¼æ²¡æçè¯ï¼å°±æ¯undefined |
| | | // return rule.required |
| | | // }) |
| | | // } |
| | | |
| | | // bluräºä»¶ |
| | | this.$on('on-form-blur', that.onFieldBlur) |
| | | // changeäºä»¶ |
| | | this.$on('on-form-change', that.onFieldChange) |
| | | }, |
| | | // ä»formçrules屿§ä¸ååºå½åform-itemçæ ¡éªè§å |
| | | getRules() { |
| | | let rules = this.parent.rules |
| | | rules = rules ? rules[this.prop] : [] |
| | | |
| | | // è¿åæ°å¼å½¢å¼çå¼ |
| | | return [].concat(rules || []) |
| | | }, |
| | | // bluräºä»¶æ¶è¿è¡è¡¨åè®¤è¯ |
| | | onFieldBlur() { |
| | | this.validation('blur') |
| | | }, |
| | | // changeäºä»¶æ¶è¿è¡è¡¨åè®¤è¯ |
| | | onFieldChange() { |
| | | this.validation('change') |
| | | }, |
| | | // è¿æ»¤åºç¬¦åè¦æ±çruleè§å |
| | | getFilterRule(triggerType = '') { |
| | | let rules = this.getRules() |
| | | // æ´ä½éªè¯è¡¨åæ¶ï¼triggerType为空åç¬¦ä¸²ï¼æ¤æ¶è¿åææè§åè¿è¡éªè¯ |
| | | if (!triggerType) return rules |
| | | // æäºåºæ¯å¯è½ç夿è§åï¼å¯è½ä¸åå¨trigger屿§ï¼æ
å
夿æ¯å¦å卿¤å±æ§ |
| | | // åé夿è§åæ¯å¦æå¯¹åºçäºä»¶ï¼æ¯å¦blurï¼change触åççäºä»¶ |
| | | // 使ç¨indexOfå¤æï¼æ¯å 为æäºæ¶å设置çéªè¯è§åçtrigger屿§å¯è½ä¸ºå¤ä¸ªï¼æ¯å¦['blur','change'] |
| | | return rules.filter(rule => rule.trigger && rule.trigger.indexOf(triggerType) !== -1) |
| | | }, |
| | | // æ ¡éªæ°æ® |
| | | validation(trigger, callback = ()=>{}) { |
| | | // æ ¡éªä¹åå
è·åéè¦æ ¡éªçå¼ |
| | | this.fieldValue = this.parent.model[this.prop] |
| | | // bluråchangeæ¯å¦æå½åæ¹å¼çæ ¡éªè§å |
| | | let rules = this.getFilterRule(trigger) |
| | | // 夿æ¯å¦æéªè¯è§åï¼å¦ææ²¡æè§åï¼ä¹è°ç¨åè°æ¹æ³ï¼å¦åç¶ç»ä»¶tn-formä¼å 为 |
| | | // 对countåéçç»è®¡éè¯¯èæ æ³è¿å
¥ä¸ä¸å±çåè° |
| | | if (!rules || rules.length === 0) { |
| | | return callback('') |
| | | } |
| | | // 设置å½åä¸ºæ ¡éªä¸ |
| | | this.validateState = 'validating' |
| | | // è°ç¨async-validatorçæ¹æ³ |
| | | let validator = new schema({ |
| | | [this.prop]: rules |
| | | }) |
| | | validator.validate({ |
| | | [this.prop]: this.fieldValue |
| | | }, { |
| | | firstFields: true |
| | | }, (errors, fields) => { |
| | | // è®°å½ç¶æåæ¥éä¿¡æ¯ |
| | | this.validateState = !errors ? 'success' : 'error' |
| | | this.validateMessage = errors ? errors[0].message : '' |
| | | |
| | | callback(this.validateMessage) |
| | | }) |
| | | }, |
| | | |
| | | // æ¸
空å½åitemä¿¡æ¯ |
| | | resetField() { |
| | | this.parent.model[this.prop] = this.initialValue |
| | | // æ¸
空é误æ è®° |
| | | this.validateState = 'success' |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-form-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 20rpx 0; |
| | | font-size: 28rpx; |
| | | color: $tn-font-color; |
| | | box-sizing: border-box; |
| | | line-height: $tn-form-item-height; |
| | | |
| | | &__border-bottom--error:after { |
| | | border-color: $tn-color-red; |
| | | } |
| | | |
| | | &__body { |
| | | display: flex; |
| | | flex-direction: row; |
| | | } |
| | | |
| | | &--left { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | |
| | | &__content { |
| | | display: flex; |
| | | flex-direction: row; |
| | | position: relative; |
| | | align-items: center; |
| | | padding-right: 18rpx; |
| | | flex: 1; |
| | | |
| | | &--required { |
| | | position: relative; |
| | | right: 0; |
| | | vertical-align: middle; |
| | | color: $tn-color-red; |
| | | } |
| | | |
| | | &__icon { |
| | | color: $tn-font-sub-color; |
| | | margin-right: 8rpx; |
| | | } |
| | | |
| | | &__label { |
| | | // display: flex; |
| | | // flex-direction: row; |
| | | // align-items: center; |
| | | // flex: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &--right { |
| | | flex: 1; |
| | | |
| | | &__content { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | flex: 1; |
| | | |
| | | &__slot { |
| | | flex: 1; |
| | | /* #ifndef MP */ |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | /* #endif */ |
| | | } |
| | | |
| | | &__icon { |
| | | margin-left: 10rpx; |
| | | color: $tn-font-sub-color; |
| | | font-size: 30rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__message { |
| | | font-size: 24rpx; |
| | | line-height: 24rpx; |
| | | color: $tn-color-red; |
| | | margin-top: 12rpx; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-form-class tn-form"> |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-form', |
| | | props: { |
| | | // è¡¨åæ°æ®å¯¹è±¡ï¼éè¦éªè¯çè¡¨åæ°æ®ï¼ |
| | | model: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // åçé误æ¶çæç¤ºæ¹å¼ |
| | | // toast - å¼¹åºtoastæ¡ |
| | | // message - æç¤ºä¿¡æ¯ |
| | | // border - å¦æè®¾ç½®äºè¾¹æ¡ï¼è¾¹æ¡ä¼åæçº¢è² |
| | | // border-bottom - ä¸è¾¹æ¡ä¼åç°çº¢è² |
| | | // none - æ æç¤º |
| | | errorType: { |
| | | type: Array, |
| | | default() { |
| | | return ['message', 'toast'] |
| | | } |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¡¨ååçä¸åçº¿è¾¹æ¡ |
| | | borderBottom: { |
| | | type:Boolean, |
| | | default: true |
| | | }, |
| | | // label(æ ç¾åç§°)çä½ç½® |
| | | // left - 左边 |
| | | // top - ä¸è¾¹ |
| | | labelPosition: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // labelç宽度 |
| | | labelWidth: { |
| | | type: Number, |
| | | default: 90 |
| | | }, |
| | | // labelç坹齿¹å¼ |
| | | // left - å·¦å¯¹é½ |
| | | // center - å±
ä¸å¯¹é½ |
| | | // right - å³å¯¹é½ |
| | | labelAlign: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // label çæ ·å¼ |
| | | labelStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | // åååä¼ éæ°æ® |
| | | provide() { |
| | | return { |
| | | tnForm: this |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | rules: {} |
| | | } |
| | | }, |
| | | created() { |
| | | // åå¨å½åformä¸çææform-itemçå®ä¾ |
| | | // ä¸è½å®ä¹ådataä¸ï¼å¦åå°ç¨åºä¼å¾ªç¯å¼ç¨èæ¥é |
| | | this.fields = [] |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 设置è§å |
| | | * |
| | | * @param {Object} rules |
| | | */ |
| | | setRules(rules) { |
| | | this.rules = rules |
| | | }, |
| | | /** |
| | | * æ¸
空form-itemç»ä»¶ |
| | | */ |
| | | resetFields() { |
| | | this.fields.map(field => { |
| | | field.resetField() |
| | | }) |
| | | }, |
| | | /** |
| | | * æ ¡éªæ°æ® |
| | | * @param {Object} callback æ ¡éªåè°æ¹æ³ |
| | | */ |
| | | validate(callback) { |
| | | return new Promise(resolve => { |
| | | // æ è®°æ ¡éªæ¯å¦éè¿ |
| | | let valid = true |
| | | // æ è®°æ¯å¦æ£æ¥å®æ¯ |
| | | let count = 0 |
| | | // åæ¾éè¯¯ä¿¡æ¯ |
| | | let errors = [] |
| | | |
| | | // 对ææform-itemè¿è¡æ ¡éª |
| | | this.fields.map(field => { |
| | | // è°ç¨å¯¹åºform-itemå®ä¾çvalidationæ ¡éªæ¹æ³ |
| | | field.validation('', error => { |
| | | // 妿æä¸ä¸ªform-itemæ ¡éªä¸éè¿ï¼åæ´ä¸ªè¡¨åæ ¡éªä¸éè¿ |
| | | if (error) { |
| | | valid = false |
| | | errors.push(error) |
| | | } |
| | | // å½éå宿æçform-itemçæ ¡éªè§åï¼è¿åä¿¡æ¯ |
| | | if (++count === this.fields.length) { |
| | | resolve(valid) |
| | | // 夿æ¯å¦è®¾ç½®äºtoastçæç¤ºæ¹å¼ï¼åªæç¤ºè¡¨åå䏿åé¢ç䏿¡éè¯¯ä¿¡æ¯ |
| | | if (this.errorType.indexOf('none') === -1 && |
| | | this.errorType.indexOf('toast') >= 0 && |
| | | errors.length > 0) { |
| | | this.$t.message.toast(errors[0]) |
| | | } |
| | | // è°ç¨åè°æ¹æ³ |
| | | if (typeof callback == 'function') callback(valid) |
| | | } |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-goods-nav-class tn-goods-nav" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | { |
| | | 'tn-goods-nav--fixed': fixed, |
| | | 'tn-safe-area-inset-bottom': safeAreaInsetBottom, |
| | | 'tn-goods-nav--shadow': shadow |
| | | } |
| | | ]" |
| | | :style="[backgroundColorStyle, navStyle]" |
| | | > |
| | | <view class="options"> |
| | | <view |
| | | v-for="(item, index) in optionsData" |
| | | :key="index" |
| | | class="options__item" |
| | | :class="[{'options__item--avatar': item.showAvatar}]" |
| | | @tap="handleOptionClick(index)" |
| | | > |
| | | <block v-if="item.showAvatar"> |
| | | <tn-avatar |
| | | :src="item.avatar" |
| | | size="sm" |
| | | :badge="item.showBadge" |
| | | :badgeText="item.count" |
| | | :badgeBgColor="item.countBackgroundColor" |
| | | :badgeColor="item.countFontColor" |
| | | :badgeSize="26" |
| | | ></tn-avatar> |
| | | </block> |
| | | <block v-else> |
| | | <view class="options__item__icon" :class="[`tn-icon-${item.icon}`]" :style="[optionStyle(index, 'icon')]"> |
| | | <tn-badge v-if="item.showBadge" :absolute="true" :backgroundColor="item.countBackgroundColor" :fontColor="item.countFontColor" :fontSize="16" padding="2rpx 5rpx">{{ item.count }}</tn-badge> |
| | | </view> |
| | | <view class="options__item__text" :style="[optionStyle(index, 'text')]">{{ item.text }}</view> |
| | | </block> |
| | | </view> |
| | | </view> |
| | | <view class="buttons"> |
| | | <view |
| | | v-for="(item, index) in buttonGroupsData" |
| | | :key="index" |
| | | class="buttons__item" |
| | | :class="[buttonClass(index)]" |
| | | :style="[buttonStyle(index)]" |
| | | @tap="handleButtonClick(index)" |
| | | > |
| | | <view class="buttons__item__text">{{ item.text }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-goods-nav', |
| | | props: { |
| | | // éé¡¹ä¿¡æ¯ |
| | | // 建议ä¸è¶
è¿3个 |
| | | // { |
| | | // icon: '', // 徿 åç§° |
| | | // text: '', // æ¾ç¤ºçææ¬ |
| | | // count: '', // è§æ çå¼ |
| | | // countBackgroundColor: '', // è§æ èæ¯é¢è² |
| | | // countFontColor: '', // è§æ åä½é¢è² |
| | | // iconColor: '', // 徿 é¢è² |
| | | // textColor: '', // ææ¬é¢è² |
| | | // avatar: '', // æ¾ç¤ºå¤´åï¼æ¤æ¶å°ä¸æ¾ç¤ºå¾æ åææ¬ï¼ |
| | | // } |
| | | options: { |
| | | type: Array, |
| | | default() { |
| | | return [{ |
| | | icon: 'shop', |
| | | text: 'åºéº' |
| | | },{ |
| | | icon: 'service', |
| | | text: '客æ' |
| | | },{ |
| | | icon: 'star', |
| | | text: 'æ¶è' |
| | | }] |
| | | } |
| | | }, |
| | | // æé®ç» |
| | | // 建议ä¸è¶
è¿2个 |
| | | // { |
| | | // text: '', // æ¾ç¤ºçææ¬ |
| | | // backgroundColor: '', // æé®èæ¯é¢è² |
| | | // color: '' // ææ¬é¢è² |
| | | // } |
| | | buttonGroups: { |
| | | type: Array, |
| | | default() { |
| | | return [{ |
| | | text: 'å å
¥è´ç©è½¦', |
| | | backgroundColor: '#FFA726', |
| | | color: '#FFFFFF' |
| | | },{ |
| | | text: 'ç»ç®', |
| | | backgroundColor: '#FF7043', |
| | | color: '#FFFFFF' |
| | | }] |
| | | } |
| | | }, |
| | | // èæ¯é¢è² |
| | | backgroundColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 导èªçé«åº¦ï¼åä½rpx |
| | | height: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¾ç¤ºé´å½± |
| | | shadow: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 导èªçå±çº§ |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æé®ç±»å |
| | | // rect -> æ¹å½¢ paddingRect -> ä¸ä¸å¸¦è¾¹è·æ¹å½¢ round -> åè§ |
| | | buttonType: { |
| | | type: String, |
| | | default: 'rect' |
| | | }, |
| | | // æ¯å¦åºå®å¨åºé¨ |
| | | fixed: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¼å¯åºé¨å®å
¨åºéé
ï¼å¼å¯çè¯ï¼ä¼å¨iPhoneXæºååºé¨æ·»å ä¸å®çå
è¾¹è· |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | backgroundColorStyle() { |
| | | return this.$t.color.getBackgroundColorStyle(this.backgroundColor) |
| | | }, |
| | | backgroundColorClass() { |
| | | return this.$t.color.getBackgroundColorInternalClass(this.backgroundColor) |
| | | }, |
| | | navStyle() { |
| | | let style = {} |
| | | if (this.height) { |
| | | style.height = this.height + 'rpx' |
| | | } |
| | | style.zIndex = this.zIndex ? this.zIndex : this.$t.zIndex.goodsNav |
| | | return style |
| | | }, |
| | | // é项style |
| | | optionStyle() { |
| | | return (index, type) => { |
| | | let style = {} |
| | | const item = this.optionsData[index] |
| | | if (type === 'icon' && item.iconColor) { |
| | | style.color = item.iconColor |
| | | } else if (type === 'text' && item.fontColor) { |
| | | style.color = item.fontColor |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | // æé®class |
| | | buttonClass() { |
| | | return (index) => { |
| | | let clazz = '' |
| | | const item = this.buttonGroupsData[index] |
| | | if (item.backgroundColorClass) { |
| | | clazz += ` ${item.backgroundColorClass}` |
| | | } |
| | | if (item.colorClass) { |
| | | clazz += ` ${item.colorClass}` |
| | | } |
| | | |
| | | clazz += ` buttons__item--${this.$t.string.humpConvertChar(this.buttonType, '-')}` |
| | | |
| | | return clazz |
| | | } |
| | | }, |
| | | // æé®style |
| | | buttonStyle() { |
| | | return (index) => { |
| | | let style = {} |
| | | const item = this.buttonGroupsData[index] |
| | | if (item.backgroundColorStyle) { |
| | | style.backgroundColor = item.backgroundColorStyle |
| | | } |
| | | if (item.colorStyle) { |
| | | style.color = item.colorStyle |
| | | } |
| | | return style |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | options(val) { |
| | | this.initData() |
| | | }, |
| | | buttonGroups(val) { |
| | | this.initData() |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ä¿åéé¡¹æ°æ® |
| | | optionsData: [], |
| | | // ä¿åæé®ç»æ°æ® |
| | | buttonGroupsData: [] |
| | | } |
| | | }, |
| | | created() { |
| | | this.initData() |
| | | }, |
| | | methods: { |
| | | // åå§åé项åæé®æ°æ® |
| | | initData() { |
| | | this.handleOptionsData() |
| | | this.handleButtonGroupsData() |
| | | }, |
| | | // é项ç¹å»äºä»¶ |
| | | handleOptionClick(index) { |
| | | this.$emit('optionClick', { |
| | | index: index |
| | | }) |
| | | }, |
| | | // æé®ç¹å»äºä»¶ |
| | | handleButtonClick(index) { |
| | | this.$emit('buttonClick', { |
| | | index: index |
| | | }) |
| | | }, |
| | | // å¤çéé¡¹ç»æ°æ® |
| | | handleOptionsData() { |
| | | this.optionsData = this.options.map((item) => { |
| | | let option = {...item} |
| | | option.showAvatar = item.hasOwnProperty('avatar') |
| | | if (item.hasOwnProperty('count')) { |
| | | const count = this.$t.number.formatNumberString(item.count, 2) |
| | | option.showBadge = true |
| | | option.count = typeof count === 'number' ? String(count) : count |
| | | option.countBackgroundColor = item.countBackgroundColor ? item.countBackgroundColor : '#01BEFF' |
| | | option.countFontColor = item.countFontColor ? item.countFontColor : '#FFFFFF' |
| | | } |
| | | |
| | | return option |
| | | }) |
| | | }, |
| | | // å¤çæé®ç»æ°æ® |
| | | handleButtonGroupsData() { |
| | | this.buttonGroupsData = this.buttonGroups.map((item) => { |
| | | let button = {...item} |
| | | if (item.hasOwnProperty('backgroundColor')) { |
| | | button.backgroundColorClass = this.$t.color.getBackgroundColorInternalClass(item.backgroundColor) |
| | | button.backgroundColorStyle = this.$t.color.getBackgroundColorStyle(item.backgroundColor) |
| | | } |
| | | if (item.hasOwnProperty('color')) { |
| | | button.colorClass = this.$t.color.getBackgroundColorInternalClass(item.color) |
| | | button.colorStyle = this.$t.color.getBackgroundColorStyle(item.color) |
| | | } |
| | | return button |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-goods-nav { |
| | | background-color: #FFFFFF; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | height: 88rpx; |
| | | width: 100%; |
| | | box-sizing: content-box; |
| | | |
| | | &--shadow { |
| | | box-shadow: 0rpx -10rpx 30rpx 0rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | &::before { |
| | | content: " "; |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | background-color: transparent; |
| | | z-index: -1; |
| | | } |
| | | } |
| | | |
| | | &--fixed { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | } |
| | | |
| | | .options { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | height: 100%; |
| | | color: #AAAAAA; |
| | | |
| | | &__item { |
| | | padding: 0 26rpx; |
| | | |
| | | &--avatar { |
| | | padding: 0rpx 0rpx 0rpx 26rpx !important; |
| | | } |
| | | |
| | | &__icon { |
| | | position: relative; |
| | | font-size: 36rpx; |
| | | margin-bottom: 6rpx; |
| | | } |
| | | |
| | | &__text { |
| | | font-size: 22rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .buttons { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | height: 100%; |
| | | |
| | | &__item { |
| | | flex: 1; |
| | | padding: 0 10rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | &--rect { |
| | | height: 100%; |
| | | } |
| | | |
| | | &--padding-rect { |
| | | height: 80%; |
| | | } |
| | | |
| | | &--round { |
| | | height: 75%; |
| | | &:first-child { |
| | | border-top-left-radius: 100rpx; |
| | | border-bottom-left-radius: 100rpx; |
| | | } |
| | | &:last-child { |
| | | border-top-right-radius: 100rpx; |
| | | border-bottom-right-radius: 100rpx; |
| | | } |
| | | } |
| | | |
| | | &__text { |
| | | display: inline-block; |
| | | font-weight: bold; |
| | | font-size: 30rpx; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-grid-item-class tn-grid-item" |
| | | :class="[ |
| | | backgroundColorClass |
| | | ]" |
| | | :hover-class="hoverClass" |
| | | :hover-stay-time="150" |
| | | :style="{ |
| | | backgroundColor: backgroundColorStyle, |
| | | width: gridWidth |
| | | }" |
| | | @tap="click" |
| | | > |
| | | <view |
| | | class="tn-grid-item__box" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [ componentsColorMixin ], |
| | | name: 'tn-grid-item', |
| | | props: { |
| | | // åºå· |
| | | index: { |
| | | type: [Number, String], |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ç¶ç»ä»¶æ°æ® |
| | | parentData: { |
| | | // æä¸å»çæ ·å¼ |
| | | hoverClass: '', |
| | | col: 3 |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // ç¶ç»ä»¶å®ä¾ |
| | | this.updateParentData() |
| | | this.parent.children.push(this) |
| | | }, |
| | | computed: { |
| | | // è®¡ç®æ¯ä¸ªå®«æ ¼ç宽度 |
| | | gridWidth() { |
| | | // #ifdef MP-WEIXIN |
| | | return '100%' |
| | | // #endif |
| | | // #ifndef MP-WEIXIN |
| | | return 100 / Number(this.parentData.col) + '%' |
| | | // #endif |
| | | }, |
| | | // ç¹å»ææ |
| | | hoverClass() { |
| | | return this.parentData.hoverClass !== 'none' |
| | | ? this.parentData.hoverClass + ' tn-grid-item--hover' |
| | | : this.parentData.hoverClass |
| | | } |
| | | }, |
| | | methods: { |
| | | // è·åç¶ç»ä»¶åæ° |
| | | updateParentData() { |
| | | this.getParentData('tn-grid') |
| | | }, |
| | | click() { |
| | | this.$emit('click', this.index) |
| | | this.parent && this.parent.click(this.index) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-grid-item { |
| | | box-sizing: border-box; |
| | | background-color: #FFFFFF; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | flex-direction: row; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: relative; |
| | | flex-direction: column; |
| | | |
| | | /* #ifdef MP */ |
| | | // float: left; |
| | | /* #endif */ |
| | | |
| | | &__box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | flex-direction: row; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-direction: column; |
| | | flex: 1; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | &--hover { |
| | | background: $tn-space-color !important; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-grid-class tn-grid" |
| | | :style="{ |
| | | justifyContent: gridAlignStyle |
| | | }" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-grid', |
| | | props: { |
| | | // åæå å |
| | | col: { |
| | | type: [Number, String], |
| | | default: 3 |
| | | }, |
| | | // å®«æ ¼å¯¹é½æ¹å¼ |
| | | // left å·¦å¯¹é½ center å±
ä¸å¯¹é½ right å³å¯¹é½ |
| | | align: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // ç¹å»æ¶çææï¼noneæ²¡æææ |
| | | hoverClass: { |
| | | type: String, |
| | | default: 'tn-hover' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | watch: { |
| | | // å½ç¶ç»ä»¶ååç»ä»¶éè¦å
±äº«åæ°ååï¼éç¥åç»ä»¶ |
| | | parentData() { |
| | | if (this.children.length) { |
| | | this.children.map(child => { |
| | | // 夿åç»ä»¶æ¯å¦æupdateParentDataæ¹å¼ï¼æææ§è¡ |
| | | typeof(child.updateParentData) === 'function' && child.updateParentData() |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // 妿å°childrenå®ä¹å¨dataä¸ï¼å¨å¾®ä¿¡å°ç¨åºä¼é æå¾ªç¯å¼ç¨èæ¥é |
| | | this.children = [] |
| | | }, |
| | | computed: { |
| | | // 计ç®ç¶ç»ä»¶ç弿¯å¦åçåå |
| | | parentData() { |
| | | return [this.hoverClass, this.col, this.border] |
| | | }, |
| | | // å®«æ ¼å¯¹é½æ¹å¼ |
| | | gridAlignStyle() { |
| | | switch(this.align) { |
| | | case 'left': |
| | | return 'flex-start' |
| | | case 'center': |
| | | return 'center' |
| | | case 'right': |
| | | return 'flex-end' |
| | | default: |
| | | return 'flex-start' |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | click(index) { |
| | | this.$emit('click', index) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | // ç»ä»¶ä¸å
¼å®¹å°ç¨åºçæ¹å¼ï¼ä¸è¿ä¸è½ä½¿ç¨å¯¹é½æ¹å¼ |
| | | // .tn-grid { |
| | | // width: 100%; |
| | | // /* #ifdef MP */ |
| | | // position: relative; |
| | | // box-sizing: border-box; |
| | | // overflow: hidden; |
| | | // /* #endif */ |
| | | |
| | | // /* #ifndef MP */ |
| | | // /* #ifndef APP-NVUE */ |
| | | // display: flex; |
| | | // flex-direction: row; |
| | | // /* #endif */ |
| | | // flex-wrap: wrap; |
| | | // align-items: center; |
| | | // /* #endif */ |
| | | // } |
| | | |
| | | // å¨ä½¿ç¨ç»ä»¶æ¶å
¼å®¹å°ç¨åº |
| | | .tn-grid { |
| | | width: 100%; |
| | | |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="!disabled" class="tn-image-upload-class tn-image-upload"> |
| | | <movable-area |
| | | class="tn-image-upload__movable-area" |
| | | :style="{ |
| | | height: movableAreaHeight |
| | | }" |
| | | @mouseenter="mouseEnterArea" |
| | | @mouseleave="mouseLeaveArea" |
| | | > |
| | | <block |
| | | v-for="(item, index) in lists" |
| | | :key="item.id" |
| | | > |
| | | <movable-view |
| | | class="tn-image-upload__movable-view" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: $t.string.getLengthUnitValue(height), |
| | | zIndex: item.zIndex, |
| | | opacity: item.opacity, |
| | | |
| | | }" |
| | | :x="item.x" |
| | | :y="item.y" |
| | | direction="all" |
| | | :damping="40" |
| | | :disabled="item.disabled" |
| | | @change="movableChange($event, item)" |
| | | @touchstart="movableStart(item)" |
| | | @mousedown="movableStart(item)" |
| | | @touchend="movableEnd(item)" |
| | | @mouseup="movableEnd(item)" |
| | | @longpress="movableLongPress(item)" |
| | | > |
| | | <view |
| | | class="tn-image-upload__item tn-image-upload__item-preview" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(itemWidth, 'px'), |
| | | height: $t.string.getLengthUnitValue(itemHeight, 'px'), |
| | | transform: `scale(${item.scale})` |
| | | }" |
| | | > |
| | | <!-- å é¤æé® --> |
| | | <view |
| | | v-if="deleteable" |
| | | class="tn-image-upload__item-preview__delete" |
| | | @tap.stop="deleteItem(index)" |
| | | :style="{ |
| | | borderTopColor: deleteBackgroundColor |
| | | }" |
| | | > |
| | | <view |
| | | class="tn-image-upload__item-preview__delete--icon" |
| | | :class="[`tn-icon-${deleteIcon}`]" |
| | | :style="{ |
| | | color: deleteColor |
| | | }" |
| | | ></view> |
| | | </view> |
| | | <!-- è¿åº¦æ¡ --> |
| | | <tn-line-progress |
| | | v-if="showProgress && item.data.progress > 0 && !item.data.error" |
| | | class="tn-image-upload__item-preview__progress" |
| | | :percent="item.data.progress" |
| | | :showPercent="false" |
| | | :round="false" |
| | | :height="8" |
| | | ></tn-line-progress> |
| | | <!-- éè¯æé® --> |
| | | <view v-if="item.data.error" class="tn-image-upload__item-preview__error-btn" @tap.stop="retry(index)">ç¹å»éè¯</view> |
| | | <!-- å¾çä¿¡æ¯ --> |
| | | <image |
| | | class="tn-image-upload__item-preview__image" |
| | | :src="item.data.url || item.data.path" |
| | | :mode="imageMode" |
| | | @tap.stop="doPreviewImage(item.data.url || item.data.path, index)" |
| | | ></image> |
| | | </view> |
| | | </movable-view> |
| | | </block> |
| | | |
| | | <!-- æ·»å æé® --> |
| | | <view |
| | | v-if="maxCount > lists.length" |
| | | class="tn-image-upload__add" |
| | | :style="{ |
| | | top: addBtn.y + 'px', |
| | | left: addBtn.x + 'px', |
| | | width: $t.string.getLengthUnitValue(itemWidth, 'px'), |
| | | height: $t.string.getLengthUnitValue(itemHeight, 'px') |
| | | }" |
| | | @tap="selectFile" |
| | | > |
| | | <!-- æ·»å æé® --> |
| | | <view |
| | | class="tn-image-upload__item tn-image-upload__item-add" |
| | | hover-class="tn-hover-class" |
| | | hover-stay-time="150" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(itemWidth, 'px'), |
| | | height: $t.string.getLengthUnitValue(itemHeight, 'px') |
| | | }" |
| | | > |
| | | <view class="tn-image-upload__item-add--icon tn-icon-add"></view> |
| | | <view class="tn-image-upload__item-add__tips">{{ uploadText }}</view> |
| | | </view> |
| | | </view> |
| | | </movable-area> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-image-upload-drag', |
| | | props: { |
| | | // å·²ä¸ä¼ çæä»¶å表 |
| | | fileList: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // ä¸ä¼ å¾çå°å |
| | | action: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ä¸ä¼ æä»¶çåæ®µåç§° |
| | | name: { |
| | | type: String, |
| | | default: 'file' |
| | | }, |
| | | // 头é¨ä¿¡æ¯ |
| | | header: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æºå¸¦çåæ° |
| | | formData: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¯å¦ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦èªå¨ä¸ä¼ |
| | | autoUpload: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æå¤§ä¸ä¼ æ°é |
| | | maxCount: { |
| | | type: Number, |
| | | default: 9 |
| | | }, |
| | | // é¢è§ä¸ä¼ å¾ççè£åªæ¨¡å¼ |
| | | imageMode: { |
| | | type: String, |
| | | default: 'aspectFill' |
| | | }, |
| | | // ç¹å»å¾çæ¯å¦å
¨å±é¢è§ |
| | | previewFullImage: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¿åº¦æ¡ |
| | | showProgress: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå é¤æé® |
| | | deleteable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å 餿é®å¾æ |
| | | deleteIcon: { |
| | | type: String, |
| | | default: 'close' |
| | | }, |
| | | // å 餿é®çèæ¯é¢è² |
| | | deleteBackgroundColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å 餿é®çé¢è² |
| | | deleteColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ä¸ä¼ åºåæç¤ºæå |
| | | uploadText: { |
| | | type: String, |
| | | default: 'éæ©å¾ç' |
| | | }, |
| | | // æ¾ç¤ºtoastæç¤º |
| | | showTips: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é¢è§å¾çåéæ©å¾çåºåç宽度 |
| | | width: { |
| | | type: Number, |
| | | default: 200 |
| | | }, |
| | | // é¢è§å¾çåéæ©å¾çåºåçé«åº¦ |
| | | height: { |
| | | type: Number, |
| | | default: 200 |
| | | }, |
| | | // éæ©å¾çç尺寸 |
| | | // åèä¸ä¼ ææ¡£ https://uniapp.dcloud.io/api/media/image |
| | | sizeType: { |
| | | type: Array, |
| | | default() { |
| | | return ['original', 'compressed'] |
| | | } |
| | | }, |
| | | // å¾çæ¥æº |
| | | sourceType: { |
| | | type: Array, |
| | | default() { |
| | | return ['album', 'camera'] |
| | | } |
| | | }, |
| | | // æ¯å¦å¯ä»¥å¤é |
| | | multiple: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æä»¶å¤§å°(byte) |
| | | maxSize: { |
| | | type: Number, |
| | | default: 10 * 1024 * 1024 |
| | | }, |
| | | // å
许ä¸ä¼ çç±»å |
| | | limitType: { |
| | | type: Array, |
| | | default() { |
| | | return ['png','jpg','jpeg','webp','gif','image'] |
| | | } |
| | | }, |
| | | // æ¯å¦èªå®è½¬æ¢ä¸ºjson |
| | | toJson: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ä¸ä¼ åé©å彿°ï¼æ¯ä¸ªæä»¶ä¸ä¼ åé½ä¼æ§è¡ |
| | | beforeUpload: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | // å 餿件åé©å彿° |
| | | beforeRemove: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | index: { |
| | | type: [Number, String], |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | movableAreaHeight() { |
| | | if (this.lists.length < this.maxCount) { |
| | | return Math.ceil((this.lists.length + 1) / this.baseData.columns) * uni.upx2px(this.height) + 'px' |
| | | } else { |
| | | return Math.ceil(this.lists.length / this.baseData.columns) * uni.upx2px(this.height) + 'px' |
| | | } |
| | | }, |
| | | itemWidth() { |
| | | return uni.upx2px(this.width) - (uni.upx2px(10) * 2) |
| | | }, |
| | | itemHeight() { |
| | | return uni.upx2px(this.height) - (uni.upx2px(10) * 2) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | lists: [], |
| | | uploading: false, |
| | | baseData: { |
| | | windowWidth: 0, |
| | | columns: 0, |
| | | dragItem: null, |
| | | widthPx: 0, |
| | | heightPx: 0 |
| | | }, |
| | | addBtn: { |
| | | x: 0, |
| | | y: 0 |
| | | }, |
| | | timer: null, |
| | | dragging: false |
| | | } |
| | | }, |
| | | watch: { |
| | | // fileList: { |
| | | // handler(val) { |
| | | // val.map(value => { |
| | | // // é¦å
æ£æ¥å
鍿¯å¦å·²ç»æ·»å è¿è¿å¼ å¾çï¼å 为å¤é¨ç»å®äºä¸ä¸ªå¯¹è±¡ç»fileListçè¯(对象å¼ç¨)ï¼è¿è¡ä¿®æ¹å¤é¨fileListæ¶ï¼ |
| | | // // ä¼è§¦åwatchï¼å¯¼è´éæ°æåæ¥çå¾ç忬¡æ·»å å°this.lists |
| | | // // æ°ç»çsomeæ¹æ³æææ¯ï¼åªè¦æ°ç»å
ç´ æä»»æä¸ä¸ªå
ç´ æ¡ä»¶ç¬¦åï¼å°±è¿åtrueï¼èå¦ä¸ä¸ªæ°ç»çeveryæ¹æ³çæææ¯æ°ç»ææå
ç´ é½ç¬¦åæ¡ä»¶æè¿åtrue |
| | | // let tmp = this.lists.some(listVal => { |
| | | // return listVal.url === value.url |
| | | // }) |
| | | // // 妿å
鍿²¡æè¿å¼ å¾çï¼åæ·»å å°å
é¨ |
| | | // !tmp && this.lists.push({ url: value.url, error: false, progress: 100 }) |
| | | // }) |
| | | // }, |
| | | // immediate: true |
| | | // }, |
| | | lists(val) { |
| | | this.$emit('on-list-change', this.sortList(), this.index) |
| | | } |
| | | }, |
| | | created() { |
| | | this.baseData.windowWidth = uni.getSystemInfoSync().windowWidth |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.updateDragInfo() |
| | | }) |
| | | }, |
| | | methods: { |
| | | // æ¸
é¤å表 |
| | | clear() { |
| | | this.lists = [] |
| | | this.updateAddBtnPositioin() |
| | | }, |
| | | // éæ°ä¸ä¼ éåä¸ä¸ä¼ å¤±è´¥æææä»¶ |
| | | reUpload() { |
| | | this.uploadFile() |
| | | }, |
| | | // éæ©å¾ç |
| | | selectFile() { |
| | | if (this.disabled) return |
| | | const { |
| | | name = '', |
| | | maxCount, |
| | | multiple, |
| | | maxSize, |
| | | sizeType, |
| | | lists, |
| | | camera, |
| | | compressed, |
| | | sourceType |
| | | } = this |
| | | let chooseFile = null |
| | | const newMaxCount = maxCount - lists.length |
| | | // åªéæ©å¾ççæ¶åä½¿ç¨ chooseImage æ¥å®ç° |
| | | chooseFile = new Promise((resolve, reject) => { |
| | | uni.chooseImage({ |
| | | count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1, |
| | | sourceType, |
| | | sizeType, |
| | | success: resolve, |
| | | fail: reject |
| | | }) |
| | | }) |
| | | chooseFile.then(res => { |
| | | let file = null |
| | | let listOldLength = lists.length |
| | | res.tempFiles.map((val, index) => { |
| | | if (!this.checkFileExt(val)) return |
| | | |
| | | // æ¯å¦è¶
åºæå¤§éå¶æ°é |
| | | if (!multiple && index >= 1) return |
| | | if (val.size > maxSize) { |
| | | this.$emit('on-oversize', val, this.sortList(), this.index) |
| | | this.showToast('è¶
åºå¯å
许æä»¶å¤§å°') |
| | | } else { |
| | | if (maxCount <= lists.length) { |
| | | this.$emit('on-exceed', val, this.sortList(), this.index) |
| | | this.showToast('è¶
åºæå¤§å
许çæä»¶æ°') |
| | | return |
| | | } |
| | | lists.push(this.handleDragListItem({ |
| | | url: val.path, |
| | | progress: 0, |
| | | error: false, |
| | | file: val |
| | | })) |
| | | this.updateAddBtnPositioin() |
| | | } |
| | | }) |
| | | this.$emit('on-choose-complete', this.sortList(), this.index) |
| | | if (this.autoUpload) this.uploadFile(listOldLength) |
| | | }).catch(err => { |
| | | this.$emit('on-choose-fail', err) |
| | | }) |
| | | }, |
| | | // æç¤ºç¨æ·ä¿¡æ¯ |
| | | showToast(message, force = false) { |
| | | if (this.showTips || force) { |
| | | this.$t.message.toast(message) |
| | | } |
| | | }, |
| | | // æå¨ä¸ä¼ ï¼éè¿refè¿è¡è°ç¨ |
| | | upload() { |
| | | this.uploadFile() |
| | | }, |
| | | // 对失败å¾çè¿è¡å次ä¸ä¼ |
| | | retry(index) { |
| | | this.lists[index].data.progress = 0 |
| | | this.lists[index].data.error = false |
| | | this.lists[index].data.response = null |
| | | this.$t.message.loading('éæ°ä¸ä¼ ') |
| | | this.uploadFile(index) |
| | | }, |
| | | // ä¸ä¼ æä»¶ |
| | | async uploadFile(index = 0) { |
| | | if (this.disabled) return |
| | | if (this.uploading) return |
| | | // å
¨é¨ä¸ä¼ 宿 |
| | | if (index >= this.lists.length) { |
| | | this.$emit('on-uploaded', this.sortList(), this.index) |
| | | return |
| | | } |
| | | // æ£æ¥æ¯å¦å·²ç»å
¨é¨ä¸ä¼ æè
ä¸ä¼ ä¸ |
| | | if (this.lists[index].data.progress === 100) { |
| | | this.lists[index].data.uploadTask = null |
| | | if (this.autoUpload) this.uploadFile(index + 1) |
| | | return |
| | | } |
| | | // æ§è¡before-uploadé©å |
| | | if (this.beforeUpload && typeof(this.beforeUpload) === 'function') { |
| | | // å¨å¾®ä¿¡ï¼æ¯ä»å®çç¯å¢(H5æ£å¸¸)ï¼ä¼å¯¼è´ç¶ç»ä»¶å®ä¹ç彿°ä½ä¸çthisåæåç»ä»¶çthis |
| | | // éè¿bind()æ¹æ³ï¼ç»å®ç¶ç»ä»¶çthisï¼è®©thisçthis为ç¶ç»ä»¶çä¸ä¸æ |
| | | // å 为uploadç»ä»¶å¯è½ä¼è¢«åµå¥å¨å
¶ä»ç»ä»¶å
ï¼æ¯å¦tn-formï¼è¿æ¶this.$parentå
¶å®ä¸ºtn-formçthisï¼ |
| | | // é页é¢çthisï¼æä»¥è¿ééè¦å¾ä¸åéï¼ä¸ç´å¯»æ¾å°æé¡¶ç«¯ç$parentï¼è¿éç¨äºthis.$u.$parent.call(this) |
| | | let beforeResponse = this.beforeUpload.bind(this.$t.$parent.call(this))(index, this.lists) |
| | | // 夿æ¯å¦è¿åäºPromise |
| | | if (!!beforeResponse && typeof beforeResponse.then === 'function') { |
| | | await beforeResponse.then(res => { |
| | | // promiseè¿åæåï¼ä¸è¿è¡æä½ç»§ç» |
| | | }).catch(err => { |
| | | // è¿å
¥catchåè°çè¯ï¼ç»§ç»ä¸ä¸å¼ |
| | | return this.uploadFile(index + 1) |
| | | }) |
| | | } else if (beforeResponse === false) { |
| | | // 妿è¿åflaseï¼ç»§ç»ä¸ä¸å¼ å¾çä¸ä¼ |
| | | return this.uploadFile(index + 1) |
| | | } else { |
| | | // 为trueçæ
åµï¼ä¸è¿è¡æä½ |
| | | } |
| | | } |
| | | // æ£æ¥ä¸ä¼ å°å |
| | | if (!this.action) { |
| | | this.showToast('请é
ç½®ä¸ä¼ å°å', true) |
| | | return |
| | | } |
| | | this.lists[index].data.error = false |
| | | this.uploading = true |
| | | // å建ä¸ä¼ 对象 |
| | | const task = uni.uploadFile({ |
| | | url: this.action, |
| | | filePath: this.lists[index].data.url, |
| | | name: this.name, |
| | | formData: this.formData, |
| | | header: this.header, |
| | | success: res => { |
| | | // 夿忝å¦ä¸ºjsonå符串ï¼å°å
¶è½¬æ¢ä¸ºjsonæ ¼å¼ |
| | | let data = this.toJson && this.$t.test.jsonString(res.data) ? JSON.parse(res.data) : res.data |
| | | if (![200, 201, 204].includes(res.statusCode)) { |
| | | this.uploadError(index, data) |
| | | } else { |
| | | this.lists[index].data.response = data |
| | | this.lists[index].data.progress = 100 |
| | | this.lists[index].data.error = false |
| | | this.$emit('on-success', data, index, this.sortList(), this.index) |
| | | } |
| | | }, |
| | | fail: err => { |
| | | this.uploadError(index, err) |
| | | }, |
| | | complete: res => { |
| | | this.$t.message.closeLoading() |
| | | this.uploading = false |
| | | this.uploadFile(index + 1) |
| | | this.$emit('on-change', res, index, this.sortList(), this.index) |
| | | } |
| | | }) |
| | | this.lists[index].uploadTask = task |
| | | task.onProgressUpdate(res => { |
| | | if (res.progress > 0) { |
| | | this.lists[index].data.progress = res.progress |
| | | this.$emit('on-progress', res, index, this.sortList(), this.index) |
| | | } |
| | | }) |
| | | }, |
| | | // ä¸ä¼ 失败 |
| | | uploadError(index, err) { |
| | | this.lists[index].data.progress = 0 |
| | | this.lists[index].data.error = true |
| | | this.lists[index].data.response = null |
| | | this.showToast('ä¸ä¼ 失败ï¼è¯·éè¯') |
| | | this.$emit('on-error', err, index, this.sortList(), this.index) |
| | | }, |
| | | // å é¤ä¸ä¸ªå¾ç |
| | | deleteItem(index) { |
| | | if (!this.deleteable) return |
| | | this.$t.message.modal( |
| | | 'æç¤º', |
| | | 'ä½ ç¡®å®è¦å é¤åï¼', |
| | | async () => { |
| | | // å
æ£æ¥æ¯å¦æå®ä¹before-removeç§»é¤åé©å |
| | | // æ§è¡before-removeé©å |
| | | if (this.beforeRemove && typeof(this.beforeRemove) === 'function') { |
| | | let beforeResponse = this.beforeRemove.bind(this.$t.$parent.call(this))(index, this.lists) |
| | | // 夿æ¯å¦è¿åpromise |
| | | if (!!beforeResponse && typeof beforeResponse.then === 'function') { |
| | | await beforeResponse.then(res => { |
| | | // promiseè¿åæåä¸è¿è¡æä½ |
| | | this.handlerDeleteItem(index) |
| | | }).catch(err => { |
| | | this.showToast('å 餿ä½è¢«ä¸æ') |
| | | }) |
| | | } else if (beforeResponse === false) { |
| | | this.showToast('å 餿ä½è¢«ä¸æ') |
| | | } else { |
| | | this.handlerDeleteItem(index) |
| | | } |
| | | } else { |
| | | this.handlerDeleteItem(index) |
| | | } |
| | | }, true) |
| | | }, |
| | | // ç§»é¤æä»¶æä½ |
| | | handlerDeleteItem(index) { |
| | | // 妿æä»¶æ£å¨ä¸ä¼ ä¸ï¼ç»æ¢ä¸ä¼ ä»»å¡ |
| | | if (this.lists[index].data.progress < 100 && this.lists[index].data.progress > 0) { |
| | | typeof this.lists[index].data.uploadTask !== 'undefined' && this.lists[index].data.uploadTask.abort() |
| | | } |
| | | this.remove(index) |
| | | this.$forceUpdate() |
| | | this.$emit('on-remove', index, this.sortList(), this.index) |
| | | this.showToast('å 餿å') |
| | | }, |
| | | // ç§»é¤æä»¶ï¼éè¿refæå¨å½¢å¼è¿è¡è°ç¨ |
| | | remove(index) { |
| | | if (!this.deleteable) return |
| | | // å¤æç´¢å¼åæ³ |
| | | if (index >= 0 && index < this.lists.length) { |
| | | let currentItemIndex = this.lists[index].index |
| | | this.lists.splice(index, 1) |
| | | // éæ°æååè¡¨ä¿¡æ¯ |
| | | for (let item of this.lists) { |
| | | if (item.index > currentItemIndex) { |
| | | item.index -= 1 |
| | | item.x = item.positionX * this.baseData.widthPx |
| | | item.y = item.positionY * this.baseData.heightPx |
| | | item.positionX = item.index % this.baseData.columns |
| | | item.positionY = Math.floor(item.index / this.baseData.columns) |
| | | this.$nextTick(() => { |
| | | item.x = item.positionX * this.baseData.widthPx |
| | | item.y = item.positionY * this.baseData.heightPx |
| | | }) |
| | | } |
| | | } |
| | | |
| | | this.updateAddBtnPositioin() |
| | | } |
| | | }, |
| | | // é¢è§å¾ç |
| | | doPreviewImage(url, index) { |
| | | if (!this.previewFullImage) return |
| | | const images = this.lists.sort((l1, l2) => { return l1.index - l2.index}).map(item => item.data.url || item.data.path) |
| | | uni.previewImage({ |
| | | urls: images, |
| | | current: url, |
| | | success: () => { |
| | | this.$emit('on-preview', url, this.sortList(), this.index) |
| | | }, |
| | | fail: () => { |
| | | this.showToast('é¢è§å¾ç失败') |
| | | } |
| | | }) |
| | | }, |
| | | // æ£æ¥æä»¶åç¼æ¯å¦åæ³ |
| | | checkFileExt(file) { |
| | | // æ¯å¦ä¸ºåæ³åç¼ |
| | | let noArrowExt = false |
| | | // åç¼å |
| | | let fileExt = '' |
| | | const reg = /.+\./ |
| | | |
| | | // #ifdef H5 |
| | | fileExt = file.name.replace(reg, '').toLowerCase() |
| | | // #endif |
| | | // #ifndef H5 |
| | | fileExt = file.path.replace(reg, '').toLowerCase() |
| | | // #endif |
| | | noArrowExt = this.limitType.some(ext => { |
| | | return ext.toLowerCase() === fileExt |
| | | }) |
| | | if (!noArrowExt) this.showToast(`䏿¯æ${fileExt}æ ¼å¼çæä»¶`) |
| | | return noArrowExt |
| | | }, |
| | | |
| | | /********************* ææ½å¤ç ********************/ |
| | | |
| | | // æ´æ°ææ½ä¿¡æ¯ |
| | | updateDragInfo() { |
| | | this.baseData.widthPx = uni.upx2px(this.width) |
| | | this.baseData.heightPx = uni.upx2px(this.height) |
| | | |
| | | // è·åå¯ç§»å¨åºåçä¿¡æ¯ï¼ç¨äºå¤æå½åæå¤å°å |
| | | const query = uni.createSelectorQuery().in(this) |
| | | query.select('.tn-image-upload__movable-area').boundingClientRect() |
| | | query.exec((res) => { |
| | | if (!res) { |
| | | setTimeout(() => { |
| | | this.updateDragInfo() |
| | | }, 10) |
| | | return |
| | | } |
| | | this.baseData.columns = Math.floor(res[0].width / this.baseData.widthPx) |
| | | |
| | | // åå§å坿æ½åè¡¨ä¿¡æ¯ |
| | | this.lists = [] |
| | | this.fileList.forEach((item) => { |
| | | // é¦å
æ£æ¥å
鍿¯å¦å·²ç»æ·»å è¿è¿å¼ å¾çï¼å 为å¤é¨ç»å®äºä¸ä¸ªå¯¹è±¡ç»fileListçè¯(对象å¼ç¨)ï¼è¿è¡ä¿®æ¹å¤é¨fileListæ¶ï¼ |
| | | // ä¼è§¦åwatchï¼å¯¼è´éæ°æåæ¥çå¾ç忬¡æ·»å å°this.lists |
| | | // æ°ç»çsomeæ¹æ³æææ¯ï¼åªè¦æ°ç»å
ç´ æä»»æä¸ä¸ªå
ç´ æ¡ä»¶ç¬¦åï¼å°±è¿åtrueï¼èå¦ä¸ä¸ªæ°ç»çeveryæ¹æ³çæææ¯æ°ç»ææå
ç´ é½ç¬¦åæ¡ä»¶æè¿åtrue |
| | | let tmp = this.lists.map(value => { |
| | | return value.data |
| | | }).some(listVal => { |
| | | return listVal.url === item.url |
| | | }) |
| | | // 妿å
鍿²¡æè¿å¼ å¾çï¼åæ·»å å°å
é¨ |
| | | !tmp && this.lists.push(this.handleDragListItem({ |
| | | url: item.url, |
| | | error: false, |
| | | progress: 100 |
| | | })) |
| | | }) |
| | | |
| | | // æ´æ°æ·»å æé®ä½ç½® |
| | | this.updateAddBtnPositioin() |
| | | }) |
| | | }, |
| | | // å¤çææ½åè¡¨ä¿¡æ¯ |
| | | handleDragListItem(item) { |
| | | const positionX = this.lists.length % this.baseData.columns |
| | | const positionY = Math.floor(this.lists.length / this.baseData.columns) |
| | | const x = positionX * this.baseData.widthPx |
| | | const y = positionY * this.baseData.heightPx |
| | | return { |
| | | id: this.unique(), |
| | | x, |
| | | y, |
| | | preX: x, |
| | | preY: y, |
| | | positionX, |
| | | positionY, |
| | | zIndex:1, |
| | | disabled: true, |
| | | opacity: 1, |
| | | scale: 1, |
| | | index: this.lists.length, |
| | | offset: 0, |
| | | moveEnd: false, |
| | | moving: false, |
| | | data: { |
| | | ...item |
| | | } |
| | | } |
| | | }, |
| | | // çæå
ç´ å¯ä¸id |
| | | unique(n = 6) { |
| | | let id = '' |
| | | for (let i = 0; i < n; i++) id += Math.floor(Math.random() * 10) |
| | | return 'tn_' + new Date().getTime() + id |
| | | }, |
| | | // æ´æ°æ·»å æé®ä½ç½® |
| | | updateAddBtnPositioin() { |
| | | if (this.lists.length >= this.maxCount) return |
| | | |
| | | this.addBtn.x = (this.lists.length % this.baseData.columns) * this.baseData.widthPx |
| | | this.addBtn.y = Math.floor(this.lists.length / this.baseData.columns) * this.baseData.heightPx |
| | | }, |
| | | // è·åæåºåæ°æ® |
| | | sortList() { |
| | | const list = this.lists.slice() |
| | | list.sort((l1, l2) => { |
| | | return l1.index - l2.index |
| | | }) |
| | | return list.map(item => { |
| | | return item.data |
| | | }) |
| | | }, |
| | | mouseEnterArea () { |
| | | // #ifdef H5 |
| | | this.lists.forEach(item => { |
| | | item.disabled = false |
| | | }) |
| | | // #endif |
| | | }, |
| | | mouseLeaveArea () { |
| | | // #ifdef H5 |
| | | if (this.baseData.dragItem) { |
| | | this.lists.forEach(item => { |
| | | item.disabled = true |
| | | item.zIndex = 1 |
| | | item.offset = 0 |
| | | item.moveEnd = true |
| | | if (item.id === this.baseData.dragItem.id) { |
| | | if (this.timer) { |
| | | clearTimeout(this.timer) |
| | | this.timer = null |
| | | } |
| | | item.x = item.preX |
| | | item.y = item.preY |
| | | this.$nextTick(() => { |
| | | item.x = item.positionX * this.baseData.widthPx |
| | | item.y = item.positionY * this.baseData.heightPx |
| | | this.baseData.dragItem = null |
| | | }) |
| | | } |
| | | }) |
| | | this.dragging = false |
| | | } |
| | | // #endif |
| | | }, |
| | | movableLongPress(item) { |
| | | // #ifndef H5 |
| | | uni.vibrateShort() |
| | | // console.log("LongPress--------------------------------------------------------------"); |
| | | this.lists.forEach(value => { |
| | | value.moving = false |
| | | }) |
| | | this.dragging = true |
| | | // 设置对åºçå
ç´ å
许æå¨ |
| | | const index = this.lists.findIndex(obj => { |
| | | return obj.id === item.id |
| | | }) |
| | | item.disabled = false |
| | | item.opacity = 0.7 |
| | | item.scale = 1.1 |
| | | this.$set(this.lists, index, item) |
| | | // #endif |
| | | }, |
| | | movableChange (e, item) { |
| | | if (!item || !this.dragging) return |
| | | // console.log("movableChange"); |
| | | item.moving = true |
| | | item.preX = e.detail.x |
| | | item.preY = e.detail.y |
| | | // console.log(item.preX, item.preY); |
| | | |
| | | if (e.detail.source === 'touch') { |
| | | if (!item.moveEnd) { |
| | | item.offset = Math.sqrt( |
| | | Math.pow(item.preX - item.positionX * this.baseData.widthPx, 2) + |
| | | Math.pow(item.preY - item.positionY * this.baseData.heightPx, 2)) |
| | | } |
| | | let x = Math.floor((e.detail.x + this.baseData.widthPx / 2) / this.baseData.widthPx) |
| | | if (x > this.baseData.columns) return |
| | | let y = Math.floor((e.detail.y + this.baseData.heightPx / 2) / this.baseData.heightPx) |
| | | let index = this.baseData.columns * y + x |
| | | if (item.index !== index && index < this.lists.length) { |
| | | for (let obj of this.lists) { |
| | | if (item.index > index && obj.index >= index && obj.index < item.index) { |
| | | this.updateItemPosition(obj, 1) |
| | | } else if (item.index < index && obj.index <= index && obj.index > item.index) { |
| | | this.updateItemPosition(obj, -1) |
| | | } else if (item.id != obj.id) { |
| | | // obj.offset = 0 |
| | | // console.log(obj.moving); |
| | | // if (!obj.moving) { |
| | | // obj.preX = obj.positionX * this.baseData.widthPx |
| | | // obj.preY = obj.positionY * this.baseData.heightPx |
| | | // console.log("moving", obj.id, obj.preX, obj.preY); |
| | | // } |
| | | // obj.x = obj.preX |
| | | // obj.y = obj.preY |
| | | // // console.log(obj.id, obj.preX, obj.preY); |
| | | // this.$nextTick(() => { |
| | | // obj.x = obj.positionX * this.baseData.widthPx |
| | | // obj.y = obj.positionY * this.baseData.heightPx |
| | | // }) |
| | | } |
| | | } |
| | | item.index = index |
| | | item.positionX = x |
| | | item.positionY = y |
| | | // TODO åéäºä»¶ |
| | | } |
| | | } |
| | | }, |
| | | movableStart (item) { |
| | | // console.log("movableStart"); |
| | | this.lists.forEach(item => { |
| | | item.zIndex = 1 |
| | | // #ifdef H5 |
| | | item.disabled = false |
| | | // #endif |
| | | }) |
| | | item.zIndex = 10 |
| | | item.moveEnd = false |
| | | this.baseData.dragItem = item |
| | | // #ifdef H5 |
| | | this.dragging =true |
| | | this.timer = setTimeout(() => { |
| | | item.opacity = 0.7 |
| | | item.scale = 1.1 |
| | | clearTimeout(this.timer) |
| | | this.timer = null |
| | | }, 200) |
| | | // #endif |
| | | }, |
| | | movableEnd (item) { |
| | | if (!this.dragging) return |
| | | // console.log("movableEnd"); |
| | | const index = this.lists.findIndex(obj => { |
| | | return obj.id === item.id |
| | | }) |
| | | if (!item.moving) { |
| | | item.preX = item.positionX * this.baseData.widthPx |
| | | item.preY = item.positionY * this.baseData.heightPx |
| | | } |
| | | item.x = item.preX |
| | | item.y = item.preY |
| | | item.offset = 0 |
| | | item.moveEnd = true |
| | | item.moving = false |
| | | item.disabled = true |
| | | // console.log(item.x, item.y); |
| | | // console.log(item.id, item.moving); |
| | | // this.$set(this.lists, index, item) |
| | | // this.lists[index] = item |
| | | // console.log(this.lists[index]); |
| | | this.lists.forEach(listValue => { |
| | | listValue.moving = false |
| | | listValue.disabled = true |
| | | }) |
| | | this.$nextTick(() => { |
| | | item.x = item.positionX * this.baseData.widthPx |
| | | item.y = item.positionY * this.baseData.heightPx |
| | | item.opacity = 1 |
| | | item.scale = 1 |
| | | this.baseData.dragItem = null |
| | | this.dragging = false |
| | | // console.log(item.x, item.y); |
| | | this.$set(this.lists, index, item) |
| | | }) |
| | | this.$emit('sort-list', this.sortList()) |
| | | }, |
| | | // æ´æ°å¾çä½ç½®ä¿¡æ¯ |
| | | updateItemPosition(item, offset) { |
| | | const index = this.lists.findIndex(obj => { |
| | | return obj.id === item.id |
| | | }) |
| | | item.index += offset |
| | | item.offset = 0 |
| | | item.positionX = item.index % this.baseData.columns |
| | | item.positionY = Math.floor(item.index / this.baseData.columns) |
| | | if (!item.moving) { |
| | | item.preX = item.positionX * this.baseData.widthPx |
| | | item.preY = item.positionY * this.baseData.heightPx |
| | | } |
| | | item.x = item.preX |
| | | item.y = item.preY |
| | | // console.log("updateItemPosition", item.id, item.preX, item.preY); |
| | | // this.$set(this.lists, index, item) |
| | | this.$nextTick(() => { |
| | | item.x = item.positionX * this.baseData.widthPx |
| | | item.y = item.positionY * this.baseData.heightPx |
| | | this.$set(this.lists, index, item) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-image-upload { |
| | | position: relative; |
| | | |
| | | &__movable-area { |
| | | width: 100%; |
| | | } |
| | | |
| | | &__movable-view { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &__item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | background-color: transparent; |
| | | position: relative; |
| | | border-radius: 5rpx; |
| | | overflow: hidden; |
| | | |
| | | &-preview { |
| | | border: 1rpx solid $tn-space-color; |
| | | |
| | | &__delete { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | z-index: 10; |
| | | border-top: 60rpx solid; |
| | | border-left: 60rpx solid transparent; |
| | | border-top-color: rgba(0,0,0,0.1); |
| | | width: 0rpx; |
| | | height: 0rpx; |
| | | |
| | | &--icon { |
| | | position: absolute; |
| | | top: -50rpx; |
| | | right: 6rpx; |
| | | color: #FFFFFF; |
| | | font-size: 24rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | &__progress { |
| | | position: absolute; |
| | | width: auto; |
| | | bottom: 0rpx; |
| | | left: 0rpx; |
| | | right: 0rpx; |
| | | z-index: 9; |
| | | /* #ifdef MP-WEIXIN */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | } |
| | | |
| | | &__error-btn { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: rgba(0,0,0,0.5); |
| | | color: #FFFFFF; |
| | | font-size: 20rpx; |
| | | padding: 8rpx 0; |
| | | text-align: center; |
| | | z-index: 9; |
| | | line-height: 1; |
| | | } |
| | | |
| | | &__image { |
| | | display: block; |
| | | width: 100%; |
| | | height: 100%; |
| | | // border-radius: 10rpx; |
| | | } |
| | | } |
| | | |
| | | &-add { |
| | | flex-direction: column; |
| | | color: $tn-content-color; |
| | | font-size: 26rpx; |
| | | |
| | | &--icon { |
| | | font-size: 40rpx; |
| | | } |
| | | |
| | | &__tips { |
| | | margin-top: 20rpx; |
| | | line-height: 40rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__add { |
| | | background-color: $tn-space-color; |
| | | position: absolute; |
| | | // border-radius: 10rpx; |
| | | // margin: 10rpx; |
| | | // margin-left: 0; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="!disabled" class="tn-image-upload-class tn-image-upload"> |
| | | <block v-if="showUploadList"> |
| | | <view |
| | | v-for="(item, index) in lists" |
| | | :key="index" |
| | | class="tn-image-upload__item tn-image-upload__item-preview" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: $t.string.getLengthUnitValue(height) |
| | | }" |
| | | > |
| | | <!-- å é¤æé® --> |
| | | <view |
| | | v-if="deleteable" |
| | | class="tn-image-upload__item-preview__delete" |
| | | @tap.stop="deleteItem(index)" |
| | | :style="{ |
| | | borderTopColor: deleteBackgroundColor |
| | | }" |
| | | > |
| | | <view |
| | | class="tn-image-upload__item-preview__delete--icon" |
| | | :class="[`tn-icon-${deleteIcon}`]" |
| | | :style="{ |
| | | color: deleteColor |
| | | }" |
| | | ></view> |
| | | </view> |
| | | <!-- è¿åº¦æ¡ --> |
| | | <tn-line-progress |
| | | v-if="showProgress && item.progress > 0 && !item.error" |
| | | class="tn-image-upload__item-preview__progress" |
| | | :percent="item.progress" |
| | | :showPercent="false" |
| | | :round="false" |
| | | :height="8" |
| | | ></tn-line-progress> |
| | | <!-- éè¯æé® --> |
| | | <view v-if="item.error" class="tn-image-upload__item-preview__error-btn" @tap.stop="retry(index)">ç¹å»éè¯</view> |
| | | <!-- å¾çä¿¡æ¯ --> |
| | | <image |
| | | class="tn-image-upload__item-preview__image" |
| | | :src="item.url || item.path" |
| | | :mode="imageMode" |
| | | @tap.stop="doPreviewImage(item.url || item.path, index)" |
| | | ></image> |
| | | </view> |
| | | </block> |
| | | <!-- <view v-if="$slots.file || $slots.$file" style="width: 100%;"> |
| | | |
| | | </view> --> |
| | | <!-- èªå®ä¹å¾çå±ç¤ºå表 --> |
| | | <slot name="file" :file="lists"></slot> |
| | | |
| | | <!-- æ·»å æé® --> |
| | | <view v-if="maxCount > lists.length" class="tn-image-upload__add" :class="{'tn-image-upload__add--custom': customBtn}" @tap="selectFile"> |
| | | <!-- æ·»å æé® --> |
| | | <view |
| | | v-if="!customBtn" |
| | | class="tn-image-upload__item tn-image-upload__item-add" |
| | | hover-class="tn-hover-class" |
| | | hover-stay-time="150" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(width), |
| | | height: $t.string.getLengthUnitValue(height) |
| | | }" |
| | | > |
| | | <view class="tn-image-upload__item-add--icon tn-icon-add"></view> |
| | | <view class="tn-image-upload__item-add__tips">{{ uploadText }}</view> |
| | | </view> |
| | | <!-- èªå®ä¹æ·»å æé® --> |
| | | <view> |
| | | <slot name="addBtn"></slot> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-image-upload', |
| | | props: { |
| | | // å·²ä¸ä¼ çæä»¶å表 |
| | | fileList: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // ä¸ä¼ å¾çå°å |
| | | action: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ä¸ä¼ æä»¶çåæ®µåç§° |
| | | name: { |
| | | type: String, |
| | | default: 'file' |
| | | }, |
| | | // 头é¨ä¿¡æ¯ |
| | | header: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æºå¸¦çåæ° |
| | | formData: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¯å¦ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦èªå¨ä¸ä¼ |
| | | autoUpload: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æå¤§ä¸ä¼ æ°é |
| | | maxCount: { |
| | | type: Number, |
| | | default: 9 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºç»ä»¶èªå¸¦çå¾çé¢è§ |
| | | showUploadList: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é¢è§ä¸ä¼ å¾ççè£åªæ¨¡å¼ |
| | | imageMode: { |
| | | type: String, |
| | | default: 'aspectFill' |
| | | }, |
| | | // ç¹å»å¾çæ¯å¦å
¨å±é¢è§ |
| | | previewFullImage: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¿åº¦æ¡ |
| | | showProgress: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå é¤æé® |
| | | deleteable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å 餿é®å¾æ |
| | | deleteIcon: { |
| | | type: String, |
| | | default: 'close' |
| | | }, |
| | | // å 餿é®çèæ¯é¢è² |
| | | deleteBackgroundColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å 餿é®çé¢è² |
| | | deleteColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ä¸ä¼ åºåæç¤ºæå |
| | | uploadText: { |
| | | type: String, |
| | | default: 'éæ©å¾ç' |
| | | }, |
| | | // æ¾ç¤ºtoastæç¤º |
| | | showTips: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // èªå®ä¹éæ©å¾æ æé® |
| | | customBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // é¢è§å¾çåéæ©å¾çåºåç宽度 |
| | | width: { |
| | | type: Number, |
| | | default: 200 |
| | | }, |
| | | // é¢è§å¾çåéæ©å¾çåºåçé«åº¦ |
| | | height: { |
| | | type: Number, |
| | | default: 200 |
| | | }, |
| | | // éæ©å¾çç尺寸 |
| | | // åèä¸ä¼ ææ¡£ https://uniapp.dcloud.io/api/media/image |
| | | sizeType: { |
| | | type: Array, |
| | | default() { |
| | | return ['original', 'compressed'] |
| | | } |
| | | }, |
| | | // å¾çæ¥æº |
| | | sourceType: { |
| | | type: Array, |
| | | default() { |
| | | return ['album', 'camera'] |
| | | } |
| | | }, |
| | | // æ¯å¦å¯ä»¥å¤é |
| | | multiple: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æä»¶å¤§å°(byte) |
| | | maxSize: { |
| | | type: Number, |
| | | default: 10 * 1024 * 1024 |
| | | }, |
| | | // å
许ä¸ä¼ çç±»å |
| | | limitType: { |
| | | type: Array, |
| | | default() { |
| | | return ['png','jpg','jpeg','webp','gif','image'] |
| | | } |
| | | }, |
| | | // æ¯å¦èªå®è½¬æ¢ä¸ºjson |
| | | toJson: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ä¸ä¼ åé©å彿°ï¼æ¯ä¸ªæä»¶ä¸ä¼ åé½ä¼æ§è¡ |
| | | beforeUpload: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | // å 餿件åé©å彿° |
| | | beforeRemove: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | index: { |
| | | type: [Number, String], |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | lists: [], |
| | | uploading: false |
| | | } |
| | | }, |
| | | watch: { |
| | | fileList: { |
| | | handler(val) { |
| | | val.map(value => { |
| | | // é¦å
æ£æ¥å
鍿¯å¦å·²ç»æ·»å è¿è¿å¼ å¾çï¼å 为å¤é¨ç»å®äºä¸ä¸ªå¯¹è±¡ç»fileListçè¯(对象å¼ç¨)ï¼è¿è¡ä¿®æ¹å¤é¨fileListæ¶ï¼ |
| | | // ä¼è§¦åwatchï¼å¯¼è´éæ°æåæ¥çå¾ç忬¡æ·»å å°this.lists |
| | | // æ°ç»çsomeæ¹æ³æææ¯ï¼åªè¦æ°ç»å
ç´ æä»»æä¸ä¸ªå
ç´ æ¡ä»¶ç¬¦åï¼å°±è¿åtrueï¼èå¦ä¸ä¸ªæ°ç»çeveryæ¹æ³çæææ¯æ°ç»ææå
ç´ é½ç¬¦åæ¡ä»¶æè¿åtrue |
| | | let tmp = this.lists.some(listVal => { |
| | | return listVal.url === value.url |
| | | }) |
| | | // 妿å
鍿²¡æè¿å¼ å¾çï¼åæ·»å å°å
é¨ |
| | | !tmp && this.lists.push({ url: value.url, error: false, progress: 100 }) |
| | | }) |
| | | }, |
| | | immediate: true |
| | | }, |
| | | lists(val) { |
| | | this.$emit('on-list-change', val, this.index) |
| | | } |
| | | }, |
| | | methods: { |
| | | // æ¸
é¤å表 |
| | | clear() { |
| | | this.lists = [] |
| | | }, |
| | | // éæ°ä¸ä¼ éåä¸ä¸ä¼ å¤±è´¥æææä»¶ |
| | | reUpload() { |
| | | this.uploadFile() |
| | | }, |
| | | // éæ©å¾ç |
| | | selectFile() { |
| | | if (this.disabled) return |
| | | const { |
| | | name = '', |
| | | maxCount, |
| | | multiple, |
| | | maxSize, |
| | | sizeType, |
| | | lists, |
| | | camera, |
| | | compressed, |
| | | sourceType |
| | | } = this |
| | | let chooseFile = null |
| | | const newMaxCount = maxCount - lists.length |
| | | // åªéæ©å¾ççæ¶åä½¿ç¨ chooseImage æ¥å®ç° |
| | | chooseFile = new Promise((resolve, reject) => { |
| | | uni.chooseImage({ |
| | | count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1, |
| | | sourceType, |
| | | sizeType, |
| | | success: resolve, |
| | | fail: reject |
| | | }) |
| | | }) |
| | | chooseFile.then(res => { |
| | | let file = null |
| | | let listOldLength = lists.length |
| | | res.tempFiles.map((val, index) => { |
| | | if (!this.checkFileExt(val)) return |
| | | |
| | | // æ¯å¦è¶
åºæå¤§éå¶æ°é |
| | | if (!multiple && index >= 1) return |
| | | if (val.size > maxSize) { |
| | | this.$emit('on-oversize', val, lists, this.index) |
| | | this.showToast('è¶
åºå¯å
许æä»¶å¤§å°') |
| | | } else { |
| | | if (maxCount <= lists.length) { |
| | | this.$emit('on-exceed', val, lists, this.index) |
| | | this.showToast('è¶
åºæå¤§å
许çæä»¶æ°') |
| | | return |
| | | } |
| | | lists.push({ |
| | | url: val.path, |
| | | progress: 0, |
| | | error: false, |
| | | file: val |
| | | }) |
| | | } |
| | | }) |
| | | this.$emit('on-choose-complete', this.lists, this.index) |
| | | if (this.autoUpload) this.uploadFile(listOldLength) |
| | | }).catch(err => { |
| | | this.$emit('on-choose-fail', err) |
| | | }) |
| | | }, |
| | | // æç¤ºç¨æ·ä¿¡æ¯ |
| | | showToast(message, force = false) { |
| | | if (this.showTips || force) { |
| | | this.$t.message.toast(message) |
| | | } |
| | | }, |
| | | // æå¨ä¸ä¼ ï¼éè¿refè¿è¡è°ç¨ |
| | | upload() { |
| | | this.uploadFile() |
| | | }, |
| | | // 对失败å¾çè¿è¡å次ä¸ä¼ |
| | | retry(index) { |
| | | this.lists[index].progress = 0 |
| | | this.lists[index].error = false |
| | | this.lists[index].response = null |
| | | this.$t.message.loading('éæ°ä¸ä¼ ') |
| | | this.uploadFile(index) |
| | | }, |
| | | // ä¸ä¼ æä»¶ |
| | | async uploadFile(index = 0) { |
| | | if (this.disabled) return |
| | | if (this.uploading) return |
| | | // å
¨é¨ä¸ä¼ 宿 |
| | | if (index >= this.lists.length) { |
| | | this.$emit('on-uploaded', this.lists, this.index) |
| | | return |
| | | } |
| | | // æ£æ¥æ¯å¦å·²ç»å
¨é¨ä¸ä¼ æè
ä¸ä¼ ä¸ |
| | | if (this.lists[index].progress === 100) { |
| | | this.lists[index].uploadTask = null |
| | | if (this.autoUpload) this.uploadFile(index + 1) |
| | | return |
| | | } |
| | | // æ§è¡before-uploadé©å |
| | | if (this.beforeUpload && typeof(this.beforeUpload) === 'function') { |
| | | // å¨å¾®ä¿¡ï¼æ¯ä»å®çç¯å¢(H5æ£å¸¸)ï¼ä¼å¯¼è´ç¶ç»ä»¶å®ä¹ç彿°ä½ä¸çthisåæåç»ä»¶çthis |
| | | // éè¿bind()æ¹æ³ï¼ç»å®ç¶ç»ä»¶çthisï¼è®©thisçthis为ç¶ç»ä»¶çä¸ä¸æ |
| | | // å 为uploadç»ä»¶å¯è½ä¼è¢«åµå¥å¨å
¶ä»ç»ä»¶å
ï¼æ¯å¦tn-formï¼è¿æ¶this.$parentå
¶å®ä¸ºtn-formçthisï¼ |
| | | // é页é¢çthisï¼æä»¥è¿ééè¦å¾ä¸åéï¼ä¸ç´å¯»æ¾å°æé¡¶ç«¯ç$parentï¼è¿éç¨äºthis.$u.$parent.call(this) |
| | | let beforeResponse = this.beforeUpload.bind(this.$t.$parent.call(this))(index, this.lists) |
| | | // 夿æ¯å¦è¿åäºPromise |
| | | if (!!beforeResponse && typeof beforeResponse.then === 'function') { |
| | | await beforeResponse.then(res => { |
| | | // promiseè¿åæåï¼ä¸è¿è¡æä½ç»§ç» |
| | | }).catch(err => { |
| | | // è¿å
¥catchåè°çè¯ï¼ç»§ç»ä¸ä¸å¼ |
| | | return this.uploadFile(index + 1) |
| | | }) |
| | | } else if (beforeResponse === false) { |
| | | // 妿è¿åflaseï¼ç»§ç»ä¸ä¸å¼ å¾çä¸ä¼ |
| | | return this.uploadFile(index + 1) |
| | | } else { |
| | | // 为trueçæ
åµï¼ä¸è¿è¡æä½ |
| | | } |
| | | } |
| | | // æ£æ¥ä¸ä¼ å°å |
| | | if (!this.action) { |
| | | this.showToast('请é
ç½®ä¸ä¼ å°å', true) |
| | | return |
| | | } |
| | | this.lists[index].error = false |
| | | this.uploading = true |
| | | // å建ä¸ä¼ 对象 |
| | | const task = uni.uploadFile({ |
| | | url: this.action, |
| | | filePath: this.lists[index].url, |
| | | name: this.name, |
| | | formData: this.formData, |
| | | header: this.header, |
| | | success: res => { |
| | | // 夿忝å¦ä¸ºjsonå符串ï¼å°å
¶è½¬æ¢ä¸ºjsonæ ¼å¼ |
| | | let data = this.toJson && this.$t.test.jsonString(res.data) ? JSON.parse(res.data) : res.data |
| | | if (![200, 201, 204].includes(res.statusCode)) { |
| | | this.uploadError(index, data) |
| | | } else { |
| | | this.lists[index].response = data |
| | | this.lists[index].progress = 100 |
| | | this.lists[index].error = false |
| | | this.$emit('on-success', data, index, this.lists, this.index) |
| | | } |
| | | }, |
| | | fail: err => { |
| | | this.uploadError(index, err) |
| | | }, |
| | | complete: res => { |
| | | this.$t.message.closeLoading() |
| | | this.uploading = false |
| | | this.uploadFile(index + 1) |
| | | this.$emit('on-change', res, index, this.lists, this.index) |
| | | } |
| | | }) |
| | | this.lists[index].uploadTask = task |
| | | task.onProgressUpdate(res => { |
| | | if (res.progress > 0) { |
| | | this.lists[index].progress = res.progress |
| | | this.$emit('on-progress', res, index, this.lists, this.index) |
| | | } |
| | | }) |
| | | }, |
| | | // ä¸ä¼ 失败 |
| | | uploadError(index, err) { |
| | | this.lists[index].progress = 0 |
| | | this.lists[index].error = true |
| | | this.lists[index].response = null |
| | | this.showToast('ä¸ä¼ 失败ï¼è¯·éè¯') |
| | | this.$emit('on-error', err, index, this.lists, this.index) |
| | | }, |
| | | // å é¤ä¸ä¸ªå¾ç |
| | | deleteItem(index) { |
| | | if (!this.deleteable) return |
| | | this.$t.message.modal( |
| | | 'æç¤º', |
| | | 'æ¨ç¡®å®è¦å é¤åï¼', |
| | | async () => { |
| | | // å
æ£æ¥æ¯å¦æå®ä¹before-removeç§»é¤åé©å |
| | | // æ§è¡before-removeé©å |
| | | if (this.beforeRemove && typeof(this.beforeRemove) === 'function') { |
| | | let beforeResponse = this.beforeRemove.bind(this.$t.$parent.call(this))(index, this.lists) |
| | | // 夿æ¯å¦è¿åpromise |
| | | if (!!beforeResponse && typeof beforeResponse.then === 'function') { |
| | | await beforeResponse.then(res => { |
| | | // promiseè¿åæåä¸è¿è¡æä½ |
| | | this.handlerDeleteItem(index) |
| | | }).catch(err => { |
| | | this.showToast('å 餿ä½è¢«ä¸æ') |
| | | }) |
| | | } else if (beforeResponse === false) { |
| | | this.showToast('å 餿ä½è¢«ä¸æ') |
| | | } else { |
| | | this.handlerDeleteItem(index) |
| | | } |
| | | } else { |
| | | this.handlerDeleteItem(index) |
| | | } |
| | | }, true) |
| | | }, |
| | | // ç§»é¤æä»¶æä½ |
| | | handlerDeleteItem(index) { |
| | | // 妿æä»¶æ£å¨ä¸ä¼ ä¸ï¼ç»æ¢ä¸ä¼ ä»»å¡ |
| | | if (this.lists[index].progress < 100 && this.lists[index].progress > 0) { |
| | | typeof this.lists[index].uploadTask !== 'undefined' && this.lists[index].uploadTask.abort() |
| | | } |
| | | this.lists.splice(index, 1) |
| | | this.$forceUpdate() |
| | | this.$emit('on-remove', index, this.lists, this.index) |
| | | this.showToast('å 餿å') |
| | | }, |
| | | // ç§»é¤æä»¶ï¼éè¿refæå¨å½¢å¼è¿è¡è°ç¨ |
| | | remove(index) { |
| | | if (!this.deleteable) return |
| | | // å¤æç´¢å¼åæ³ |
| | | if (index >= 0 && index < this.lists.length) { |
| | | this.lists.splice(index, 1) |
| | | } |
| | | }, |
| | | // é¢è§å¾ç |
| | | doPreviewImage(url, index) { |
| | | if (!this.previewFullImage) return |
| | | const images = this.lists.map(item => item.url || item.path) |
| | | uni.previewImage({ |
| | | urls: images, |
| | | current: url, |
| | | success: () => { |
| | | this.$emit('on-preview', url, this.lists, this.index) |
| | | }, |
| | | fail: () => { |
| | | this.showToast('é¢è§å¾ç失败') |
| | | } |
| | | }) |
| | | }, |
| | | // æ£æ¥æä»¶åç¼æ¯å¦åæ³ |
| | | checkFileExt(file) { |
| | | // æ¯å¦ä¸ºåæ³åç¼ |
| | | let noArrowExt = false |
| | | // åç¼å |
| | | let fileExt = '' |
| | | const reg = /.+\./ |
| | | |
| | | // #ifdef H5 |
| | | fileExt = file.name.replace(reg, '').toLowerCase() |
| | | // #endif |
| | | // #ifndef H5 |
| | | fileExt = file.path.replace(reg, '').toLowerCase() |
| | | // #endif |
| | | noArrowExt = this.limitType.some(ext => { |
| | | return ext.toLowerCase() === fileExt |
| | | }) |
| | | if (!noArrowExt) this.showToast(`䏿¯æ${fileExt}æ ¼å¼çæä»¶`) |
| | | return noArrowExt |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-image-upload { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | |
| | | &__item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | overflow: hidden; |
| | | margin: 12rpx; |
| | | margin-left: 0; |
| | | background-color: $tn-font-holder-color; |
| | | position: relative; |
| | | border-radius: 10rpx; |
| | | |
| | | &-preview { |
| | | border: 1rpx solid $tn-border-solid-color; |
| | | |
| | | &__delete { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | z-index: 10; |
| | | border-top: 60rpx solid; |
| | | border-left: 60rpx solid transparent; |
| | | border-top-color: $tn-color-red; |
| | | width: 0rpx; |
| | | height: 0rpx; |
| | | |
| | | &--icon { |
| | | position: absolute; |
| | | top: -50rpx; |
| | | right: 6rpx; |
| | | color: #FFFFFF; |
| | | font-size: 24rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | &__progress { |
| | | position: absolute; |
| | | width: auto; |
| | | bottom: 0rpx; |
| | | left: 0rpx; |
| | | right: 0rpx; |
| | | z-index: 9; |
| | | /* #ifdef MP-WEIXIN */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | } |
| | | |
| | | &__error-btn { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: $tn-color-red; |
| | | color: #FFFFFF; |
| | | font-size: 20rpx; |
| | | padding: 8rpx 0; |
| | | text-align: center; |
| | | z-index: 9; |
| | | line-height: 1; |
| | | } |
| | | |
| | | &__image { |
| | | display: block; |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 10rpx; |
| | | } |
| | | } |
| | | |
| | | &-add { |
| | | flex-direction: column; |
| | | color: $tn-content-color; |
| | | font-size: 26rpx; |
| | | |
| | | &--icon { |
| | | font-size: 40rpx; |
| | | } |
| | | |
| | | &__tips { |
| | | margin-top: 20rpx; |
| | | line-height: 40rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__add { |
| | | width: auto; |
| | | display: inline-block; |
| | | |
| | | &--custom { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- æ¯ä»å®å°ç¨åºä½¿ç¨_tGetRect()è·åç»ä»¶çæ ¹å
ç´ å°ºå¯¸ï¼æä»¥å¨å¤é¢å¥ä¸ä¸ª"壳" --> |
| | | <view> |
| | | <view :id="elId" class="tn-index-anchor__wrap" :style="[wrapperStyle]"> |
| | | <view class="tn-index-anchor" :class="[active ? 'tn-index-anchor--active' : '']" :style="[customAnchorStyle]"> |
| | | <view v-if="useSlot"> |
| | | <slot></slot> |
| | | </view> |
| | | <block v-else> |
| | | <text>{{ index }}</text> |
| | | </block> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-index-anchor', |
| | | props: { |
| | | // 使ç¨èªå®ä¹å
容 |
| | | useSlot: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç´¢å¼å符 |
| | | index: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // èªå®ä¹æ ·å¼ |
| | | customStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | customAnchorStyle() { |
| | | return Object.assign(this.anchorStyle, this.customStyle) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | elId: this.$t.uuid(), |
| | | // å
容çé«åº¦ |
| | | height: 0, |
| | | // å
容çtop |
| | | top: 0, |
| | | // æ¯å¦è¢«æ¿æ´» |
| | | active: false, |
| | | // æ ·å¼ï¼ç¶ç»ä»¶å¤é¨æä¾ï¼ |
| | | wrapperStyle: {}, |
| | | anchorStyle: {} |
| | | } |
| | | }, |
| | | created() { |
| | | this.parent = false |
| | | }, |
| | | mounted() { |
| | | this.parent = this.$t.$parent.call(this, 'tn-index-list') |
| | | if (this.parent) { |
| | | this.parent.childrens.push(this) |
| | | this.parent.updateData() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-index-anchor { |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | padding: 8rpx 24rpx; |
| | | color: $tn-font-color; |
| | | font-size: 28rpx; |
| | | font-weight: 500; |
| | | line-height: 1.2; |
| | | background-color: rgb(245, 245, 245); |
| | | |
| | | &--active { |
| | | right: 0; |
| | | left: 0; |
| | | color: $tn-main-color; |
| | | background-color: #FFFFFF; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- æ¯ä»å®å°ç¨åºä½¿ç¨_tGetRect()è·åç»ä»¶çæ ¹å
ç´ å°ºå¯¸ï¼æä»¥å¨å¤é¢å¥ä¸ä¸ª"壳" --> |
| | | <view> |
| | | <view class="tn-index-list-class tn-index-list"> |
| | | <slot></slot> |
| | | |
| | | <!-- ä¾§è¾¹æ --> |
| | | <view |
| | | v-if="showSidebar" |
| | | class="tn-index-list__sidebar" |
| | | @touchstart.stop.prevent="onTouchMove" |
| | | @touchmove.stop.prevent="onTouchMove" |
| | | @touchend.stop.prevent="onTouchStop" |
| | | @touchcancel.stop.prevent="onTouchStop" |
| | | > |
| | | <view |
| | | v-for="(item, index) in indexList" |
| | | :key="index" |
| | | class="tn-index-list__sidebar__item" |
| | | :style="{ |
| | | zIndex: zIndex + 1, |
| | | color: activeAnchorIndex === index ? activeColor : '' |
| | | }" |
| | | > |
| | | {{ item }} |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- éä¸å¼¹åºæ¡ --> |
| | | <view |
| | | v-if="touchMove && indexList[touchMoveIndex]" |
| | | class="tn-index-list__alert" |
| | | :style="{ |
| | | zIndex: selectAlertZIndex |
| | | }" |
| | | > |
| | | <text>{{ indexList[touchMoveIndex] }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // çæ A-Zç忝å表 |
| | | let indexList = function() { |
| | | let indexList = [] |
| | | let charCodeOfA = 'A'.charCodeAt(0) |
| | | for (var i = 0; i < 26; i++) { |
| | | indexList.push(String.fromCharCode(charCodeOfA + i)) |
| | | } |
| | | return indexList |
| | | } |
| | | |
| | | export default { |
| | | name: 'tn-index-list', |
| | | props: { |
| | | // ç´¢å¼å表 |
| | | indexList: { |
| | | type: Array, |
| | | default() { |
| | | return indexList() |
| | | } |
| | | }, |
| | | // æ¯å¦èªå¨å¸é¡¶ |
| | | sticky: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // èªå¨å¸é¡¶æ¶è·ç¦»é¡¶é¨çè·ç¦»ï¼åä½px |
| | | stickyTop: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // èªå®ä¹é¡¶æ çé«åº¦ï¼åä½px |
| | | customBarHeight: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å½åæ»å¨çé«åº¦ |
| | | // ç±äºèªå®ä¹ç»ä»¶æ æ³è·åæ»å¨é«åº¦ï¼æä»¥ä¾èµä¼ å
¥ |
| | | scrollTop: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // éä¸ç´¢å¼æ¶çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // å¸é¡¶æ¶çz-index |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | // éä¸ç´¢å¼åè¡¨å¼¹åºæç¤ºæ¡çz-index |
| | | selectAlertZIndex() { |
| | | return this.$t.zIndex.toast |
| | | }, |
| | | // å¸é¡¶çåç§»é«åº¦ |
| | | stickyOffsetTop() { |
| | | // #ifdef H5 |
| | | return this.stickyTop !== '' ? this.stickyTop : 44 |
| | | // #endif |
| | | // #ifndef H5 |
| | | return this.stickyTop !== '' ? this.stickyTop : 0 |
| | | // #endif |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // å½åæ¿æ´»çå表éç¹çåºå· |
| | | activeAnchorIndex: 0, |
| | | // æ¾ç¤ºä¾§è¾¹ç´¢å¼æ |
| | | showSidebar: true, |
| | | // æ è®°æ¯å¦å¼å§è§¦æ¸ç§»å¨ |
| | | touchMove: false, |
| | | // å½å触æ¸ç§»å¨å°å¯¹åºç´¢å¼çåºå· |
| | | touchMoveIndex: 0, |
| | | // æ»å¨å°å¯¹åºéç¹çåºå· |
| | | scrollToAnchorIndex: 0, |
| | | // ä¾§è¾¹æ çä¿¡æ¯ |
| | | sidebar: { |
| | | height: 0, |
| | | top: 0 |
| | | }, |
| | | // å
容åºåé«åº¦ |
| | | height: 0, |
| | | // å
容åºåtop |
| | | top: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | scrollTop() { |
| | | this.updateData() |
| | | } |
| | | }, |
| | | created() { |
| | | // åªè½å¨createdçå½å¨æå®ä¹childrensï¼å¦æå¨dataå®ä¹ï¼ä¼å 为循ç¯å¼ç¨èæ¥é |
| | | this.childrens = [] |
| | | }, |
| | | methods: { |
| | | // æ´æ°æ°æ® |
| | | updateData() { |
| | | this.timer && clearTimeout(this.timer) |
| | | this.timer = setTimeout(() => { |
| | | this.showSidebar = !!this.childrens.length |
| | | this.getRect().then(() => { |
| | | this.onScroll() |
| | | }) |
| | | }, 0) |
| | | }, |
| | | // è·å对åºçä¿¡æ¯ |
| | | getRect() { |
| | | return Promise.all([ |
| | | this.getAnchorRect(), |
| | | this.getListRect(), |
| | | this.getSidebarRect() |
| | | ]) |
| | | }, |
| | | // è·åå表å
容åå
ç´ ä¿¡æ¯ |
| | | getAnchorRect() { |
| | | return Promise.all(this.childrens.map((child, index) => { |
| | | child._tGetRect('.tn-index-anchor__wrap').then((rect) => { |
| | | Object.assign(child, { |
| | | height: rect.height, |
| | | top: rect.top - this.customBarHeight |
| | | }) |
| | | }) |
| | | })) |
| | | }, |
| | | // è·ååè¡¨ä¿¡æ¯ |
| | | getListRect() { |
| | | return this._tGetRect('.tn-index-list').then(rect => { |
| | | Object.assign(this, { |
| | | height: rect.height, |
| | | top: rect.top + this.scrollTop |
| | | }) |
| | | }) |
| | | }, |
| | | // è·åä¾§è¾¹æ»å¨æ ä¿¡æ¯ |
| | | getSidebarRect() { |
| | | return this._tGetRect('.tn-index-list__sidebar').then(rect => { |
| | | this.sidebar = { |
| | | height: rect.height, |
| | | top: rect.top |
| | | } |
| | | }) |
| | | }, |
| | | // æ»å¨äºä»¶ |
| | | onScroll() { |
| | | const { |
| | | childrens = [] |
| | | } = this |
| | | if (!childrens.length) { |
| | | return |
| | | } |
| | | const { |
| | | sticky, |
| | | stickyOffsetTop, |
| | | zIndex, |
| | | scrollTop, |
| | | activeColor |
| | | } = this |
| | | const active = this.getActiveAnchorIndex() |
| | | this.activeAnchorIndex = active |
| | | if (sticky) { |
| | | let isActiveAnchorSticky = false |
| | | if (active !== -1) { |
| | | isActiveAnchorSticky = childrens[active].top <= 0 |
| | | } |
| | | childrens.forEach((item, index) => { |
| | | if (index === active) { |
| | | let wrapperStyle = '' |
| | | let anchorStyle = { |
| | | color: `${activeColor}` |
| | | } |
| | | if (isActiveAnchorSticky) { |
| | | wrapperStyle = { |
| | | height: `${childrens[index].height}px` |
| | | } |
| | | anchorStyle = { |
| | | position: 'fixed', |
| | | top: `${stickyOffsetTop}px`, |
| | | zIndex: `${zIndex ? zIndex : this.$t.zIndex.indexListSticky}`, |
| | | color: `${activeColor}` |
| | | } |
| | | } |
| | | item.active = true |
| | | item.wrapperStyle = wrapperStyle |
| | | item.anchorStyle = anchorStyle |
| | | } else if (index === active - 1) { |
| | | const currentAnchor = childrens[index] |
| | | const currentOffsetTop = currentAnchor.top |
| | | const targetOffsetTop = index === childrens.length - 1 ? this.top : childrens[index + 1].top |
| | | const parentOffsetHeight = targetOffsetTop - currentOffsetTop |
| | | const translateY = parentOffsetHeight - currentAnchor.height |
| | | const anchorStyle = { |
| | | position: 'relative', |
| | | transform: `translate3d(0, ${translateY}px, 0)`, |
| | | zIndex: `${zIndex ? zIndex : this.$t.zIndex.indexListSticky}`, |
| | | color: `${activeColor}` |
| | | } |
| | | item.active = false |
| | | item.anchorStyle = anchorStyle |
| | | } else { |
| | | item.active = false |
| | | item.wrapperStyle = '' |
| | | item.anchorStyle = '' |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | // 触æ¸ç§»å¨ |
| | | onTouchMove(event) { |
| | | this.touchMove = true |
| | | const sidebarLength = this.childrens.length |
| | | const touch = event.touches[0] |
| | | const itemHeight = this.sidebar.height / sidebarLength |
| | | let clientY = touch.clientY |
| | | let index = Math.floor((clientY - this.sidebar.top) / itemHeight) |
| | | if (index < 0) { |
| | | index = 0 |
| | | } else if (index > sidebarLength - 1) { |
| | | index = sidebarLength - 1 |
| | | } |
| | | this.touchMoveIndex = index |
| | | this.scrollToAnchor(index) |
| | | }, |
| | | // 触æ¸åæ¢ |
| | | onTouchStop() { |
| | | this.touchMove = false |
| | | this.scrollToAnchorIndex = null |
| | | }, |
| | | // è·åå½åçéç¹åºå· |
| | | getActiveAnchorIndex() { |
| | | const { |
| | | childrens, |
| | | sticky |
| | | } = this |
| | | for (let i = this.childrens.length - 1; i >= 0; i--) { |
| | | const preAnchorHeight = i > 0 ? childrens[i - 1].height : 0 |
| | | const reachTop = sticky ? preAnchorHeight : 0 |
| | | if (reachTop >= childrens[i].top) { |
| | | return i |
| | | } |
| | | } |
| | | return -1 |
| | | }, |
| | | // æ»å¨å°å¯¹åºçéç¹ |
| | | scrollToAnchor(index) { |
| | | if (this.scrollToAnchorIndex === index) { |
| | | return |
| | | } |
| | | this.scrollToAnchorIndex = index |
| | | const anchor = this.childrens.find(item => item.index === this.indexList[index]) |
| | | if (anchor) { |
| | | const scrollTop = anchor.top + this.scrollTop |
| | | this.$emit('select', { |
| | | index: anchor.index, |
| | | scrollTop: scrollTop |
| | | }) |
| | | uni.pageScrollTo({ |
| | | duration:0, |
| | | scrollTop: scrollTop |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-index-list { |
| | | position: relative; |
| | | |
| | | &__sidebar { |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: fixed; |
| | | top: 50%; |
| | | right: 0; |
| | | text-align: center; |
| | | transform: translateY(-50%); |
| | | user-select: none; |
| | | z-index: 99; |
| | | |
| | | &__item { |
| | | font-weight: 500; |
| | | padding: 8rpx 18rpx; |
| | | font-size: 22rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | &__alert { |
| | | display: flex; |
| | | flex-direction: row; |
| | | position: fixed; |
| | | width: 120rpx; |
| | | height: 120rpx; |
| | | top: 50%; |
| | | right: 90rpx; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: -60rpx; |
| | | border-radius: 24rpx; |
| | | font-size: 50rpx; |
| | | color: #FFFFFF; |
| | | background-color: $tn-font-sub-color; |
| | | padding: 0; |
| | | z-index: 9999999; |
| | | |
| | | text { |
| | | line-height: 50rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-input-class tn-input" |
| | | :class="{ |
| | | 'tn-input--border': border, |
| | | 'tn-input--error': validateState |
| | | }" |
| | | :style="{ |
| | | padding: `0 ${border ? 20 : 0}rpx`, |
| | | borderColor: borderColor, |
| | | textAlign: inputAlign |
| | | }" |
| | | @tap.stop="inputClick" |
| | | > |
| | | <textarea |
| | | v-if="type === 'textarea'" |
| | | class="tn-input__input tn-input__textarea" |
| | | :style="[inputStyle]" |
| | | :value="defaultValue" |
| | | :placeholder="placeholder" |
| | | :placeholderStyle="placeholderStyle" |
| | | :disabled="disabled || type === 'select'" |
| | | :maxlength="maxLength" |
| | | :fixed="fixed" |
| | | :focus="focus" |
| | | :autoHeight="autoHeight" |
| | | :selectionStart="elSelectionStart" |
| | | :selectionEnd="elSelectionEnd" |
| | | :cursorSpacing="cursorSpacing" |
| | | :showConfirmBar="showConfirmBar" |
| | | @input="handleInput" |
| | | @blur="handleBlur" |
| | | @focus="onFocus" |
| | | @confirm="onConfirm" |
| | | /> |
| | | <input |
| | | v-else |
| | | class="tn-input__input" |
| | | :type="type === 'password' ? 'text' : type" |
| | | :style="[inputStyle]" |
| | | :value="defaultValue" |
| | | :password="type === 'password' && !showPassword" |
| | | :placeholder="placeholder" |
| | | :placeholderStyle="placeholderStyle" |
| | | :disabled="disabled || type === 'select'" |
| | | :maxlength="maxLength" |
| | | :focus="focus" |
| | | :confirmType="confirmType" |
| | | :selectionStart="elSelectionStart" |
| | | :selectionEnd="elSelectionEnd" |
| | | :cursorSpacing="cursorSpacing" |
| | | :showConfirmBar="showConfirmBar" |
| | | @input="handleInput" |
| | | @blur="handleBlur" |
| | | @focus="onFocus" |
| | | @confirm="onConfirm" |
| | | /> |
| | | |
| | | <!-- å³è¾¹çicon --> |
| | | <view class="tn-input__right-icon tn-flex tn-flex-col-center"> |
| | | <!-- æ¸
é¤æé® --> |
| | | <view |
| | | v-if="clearable && value !== '' && focused" |
| | | class="tn-input__right-icon__item tn-input__right-icon__clear" |
| | | @tap="onClear" |
| | | > |
| | | <view class="icon tn-icon-close"></view> |
| | | </view> |
| | | <view |
| | | v-else-if="type === 'text' && !focused && showRightIcon && rightIcon !== ''" |
| | | class="tn-input__right-icon__item tn-input__right-icon__clear" |
| | | > |
| | | <view class="icon" :class="[`tn-icon-${rightIcon}`]"></view> |
| | | </view> |
| | | <!-- æ¾ç¤ºå¯ç æé® --> |
| | | <view |
| | | v-if="passwordIcon && type === 'password'" |
| | | class="tn-input__right-icon__item tn-input__right-icon__clear" |
| | | @tap="showPassword = !showPassword" |
| | | > |
| | | <view v-if="!showPassword" class="tn-icon-eye-hide"></view> |
| | | <view v-else class="icon tn-icon-eye"></view> |
| | | </view> |
| | | <!-- å¯é项ç®å¤´ --> |
| | | <view |
| | | v-if="type === 'select'" |
| | | class="tn-input__right-icon__item tn-input__right-icon__select" |
| | | :class="{ |
| | | 'tn-input__right-icon__select--reverse': selectOpen |
| | | }" |
| | | > |
| | | <view class="icon tn-icon-up-triangle"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Emitter from '../../libs/utils/emitter.js' |
| | | |
| | | export default { |
| | | mixins: [Emitter], |
| | | name: 'tn-input', |
| | | props: { |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // è¾å
¥æ¡çç±»å |
| | | type: { |
| | | type: String, |
| | | default: 'text' |
| | | }, |
| | | // è¾å
¥æ¡æå坹齿¹å¼ |
| | | inputAlign: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // ææ¬æ¡ä¸ºç©ºæ¶æ¾ç¤ºçä¿¡æ¯ |
| | | placeholder: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | placeholderStyle: { |
| | | type: String, |
| | | default: 'color: #AAAAAA' |
| | | }, |
| | | // æ¯å¦ç¦ç¨è¾å
¥æ¡ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¯è¾å
¥æåçæå¤§é¿åº¦ |
| | | maxLength: { |
| | | type: Number, |
| | | default: 255 |
| | | }, |
| | | // è¾å
¥æ¡é«åº¦ |
| | | height: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ ¹æ®å
容èªå¨è°æ´é«åº¦ |
| | | autoHeight: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é®çå³ä¸è§æ¾ç¤ºçæåï¼ä»
å¨textæ¶çæ |
| | | confirmType: { |
| | | type: String, |
| | | default: 'done' |
| | | }, |
| | | // è¾å
¥æ¡èªå®ä¹æ ·å¼ |
| | | customStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¯å¦åºå®è¾å
¥æ¡ |
| | | fixed: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦èªå¨è·åç¦ç¹ |
| | | focus: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å½type为passwordæ¶ï¼æ¯å¦æ¾ç¤ºå³ä¾§å¯ç 徿 |
| | | passwordIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å½type为 inputæè
textareaæ¶æ¯å¦æ¾ç¤ºè¾¹æ¡ |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è¾¹æ¡çé¢è² |
| | | borderColor: { |
| | | type: String, |
| | | default: '#dcdfe6' |
| | | }, |
| | | // å½type为selectæ¶ï¼æè½¬å³ä¾§å¾æ ï¼æ è®°å½æ¶selectæ¯æå¼è¿æ¯å
³é |
| | | selectOpen: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¯æ¸
空 |
| | | clearable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å
æ ä¸é®ççè·ç¦» |
| | | cursorSpacing: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // selectionStartåselectionEndéè¦æé
使ç¨ï¼èªå¨èç¦æ¶çæ |
| | | // å
æ èµ·å§ä½ç½® |
| | | selectionStart: { |
| | | type: Number, |
| | | default: -1 |
| | | }, |
| | | // å
æ ç»æä½ç½® |
| | | selectionEnd: { |
| | | type: Number, |
| | | default: -1 |
| | | }, |
| | | // èªå¨å»é¤ä¸¤ç«¯ç©ºæ ¼ |
| | | trim: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé®ç䏿¹ç宿æé® |
| | | showConfirmBar: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦å¨è¾å
¥æ¡å
æå³è¾¹æ¾ç¤ºå¾æ |
| | | showRightIcon: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æå³è¾¹å¾æ çåç§° |
| | | rightIcon: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | // è¾å
¥æ¡æ ·å¼ |
| | | inputStyle() { |
| | | let style = {} |
| | | // å¦ææ²¡æè®¾ç½®é«åº¦ï¼æ ¹æ®ä¸åçç±»å设置ä¸ä¸ªé»è®¤å¼ |
| | | style.minHeight = this.height ? this.height + 'rpx' : |
| | | this.type === 'textarea' ? this.textareaHeight + 'rpx' : this.inputHeight + 'rpx' |
| | | |
| | | style = Object.assign(style, this.customStyle) |
| | | |
| | | return style |
| | | }, |
| | | // å
æ èµ·å§ä½ç½® |
| | | elSelectionStart() { |
| | | return String(this.selectionStart) |
| | | }, |
| | | // å
æ ç»æä½ç½® |
| | | elSelectionEnd() { |
| | | return String(this.selectionEnd) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // é»è®¤å¼ |
| | | defaultValue: this.value, |
| | | // è¾å
¥æ¡é«åº¦ |
| | | inputHeight: 70, |
| | | // textareaçé«åº¦ |
| | | textareaHeight: 100, |
| | | // æ è®°éªè¯çç¶æ |
| | | validateState: false, |
| | | // æ è®°æ¯å¦è·åå°ç¦ç¹ |
| | | focused: false, |
| | | // æ¯å¦é¢è§å¯ç |
| | | showPassword: false, |
| | | // ç¨äºå¤´æ¡å°ç¨åºï¼å¤æ@inputä¸ï¼ååç弿¯å¦åçäºååï¼å 为头æ¡ä¸æä¸ï¼æä¸é®æ²¡æè¾å
¥å
容ï¼ä¹ä¼è§¦å@inputäºä»¶ |
| | | lastValue: '', |
| | | } |
| | | }, |
| | | watch: { |
| | | value(newVal, oldVal) { |
| | | this.defaultValue = newVal |
| | | // å½å¼åçååæ¶ï¼å¹¶ä¸type为selectæ¶ï¼ä¸ä¼è§¦åinputäºä»¶ |
| | | // 模æinputäºä»¶ |
| | | if (newVal !== oldVal && this.type === 'select') { |
| | | this.handleInput({ |
| | | detail: { |
| | | value: newVal |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // çå¬form-itemååºçé误äºä»¶ï¼å°è¾å
¥æ¡åæçº¢è² |
| | | this.$on("on-form-item-error", this.onFormItemError) |
| | | }, |
| | | methods: { |
| | | /** |
| | | * inputäºä»¶ |
| | | */ |
| | | handleInput(event) { |
| | | let value = event.detail.value |
| | | // æ¯å¦éè¦å»æç©ºæ ¼ |
| | | if (this.trim) value = this.$t.string.trim(value) |
| | | // åçäºä»¶ |
| | | this.$emit('input', value) |
| | | // modelèµå¼ |
| | | this.defaultValue = value |
| | | // è¿ä¸ä¸ªçå½å¨æååéäºä»¶ç»tn-form-itemï¼å¦åthis.$emit('input')æ´æ°äºç¶ç»ä»¶çå¼ï¼ä½æ¯å¾®ä¿¡å°ç¨åºä¸ |
| | | // å°æªæ´æ°å°tn-form-itemï¼å¯¼è´è·åçå¼ä¸ºç©ºï¼ä»èæ ¡éªæ··è®º |
| | | // è¿éä¸è½å»¶æ¶æ¶é´å¤ªçï¼æè
使ç¨this.$nextTickï¼å¦åå¨å¤´æ¡ä¸ï¼ä¼é ææ··ä¹± |
| | | setTimeout(() => { |
| | | // 头æ¡å°ç¨åºç±äºèªèº«bugï¼å¯¼è´ä¸æä¸ï¼æ¯æä¸ä¸ä¸ªé®(å°æªå®æè¾å
¥)ï¼é½ä¼è§¦å䏿¬¡@inputï¼å¯¼è´é误ï¼è¿éè¿è¡å¤æå¤ç |
| | | // #ifdef MP-TOUTIAO |
| | | if (this.$t.string.trim(value) === this.lastValue) return |
| | | this.lastValue = value |
| | | // #endif |
| | | |
| | | // åéå½åçå¼å°form-itemè¿è¡æ ¡éª |
| | | this.dispatch('tn-form-item','on-form-change', value) |
| | | }, 40) |
| | | }, |
| | | /** |
| | | * bluräºä»¶ |
| | | */ |
| | | handleBlur(event) { |
| | | let value = event.detail.value |
| | | |
| | | // ç±äºç¹å»æ¸
é¤å¾æ ä¹ä¼è§¦åbluräºä»¶ï¼å¯¼è´å¾æ æ¶å¤±ä»èæ æ³ç¹å» |
| | | setTimeout(() => { |
| | | this.focused = false |
| | | }, 100) |
| | | |
| | | // åçäºä»¶ |
| | | this.$emit('blur', value) |
| | | // è¿ä¸ä¸ªçå½å¨æååéäºä»¶ç»tn-form-itemï¼å¦åthis.$emit('blur')æ´æ°äºç¶ç»ä»¶çå¼ï¼ä½æ¯å¾®ä¿¡å°ç¨åºä¸ |
| | | // å°æªæ´æ°å°tn-form-itemï¼å¯¼è´è·åçå¼ä¸ºç©ºï¼ä»èæ ¡éªæ··è®º |
| | | // è¿éä¸è½å»¶æ¶æ¶é´å¤ªçï¼æè
使ç¨this.$nextTickï¼å¦åå¨å¤´æ¡ä¸ï¼ä¼é ææ··ä¹± |
| | | setTimeout(() => { |
| | | // 头æ¡å°ç¨åºç±äºèªèº«bugï¼å¯¼è´ä¸æä¸ï¼æ¯æä¸ä¸ä¸ªé®(å°æªå®æè¾å
¥)ï¼é½ä¼è§¦å䏿¬¡@inputï¼å¯¼è´é误ï¼è¿éè¿è¡å¤æå¤ç |
| | | // #ifdef MP-TOUTIAO |
| | | if (this.$t.string.trim(value) === this.lastValue) return |
| | | this.lastValue = value |
| | | // #endif |
| | | |
| | | // åéå½åçå¼å°form-itemè¿è¡æ ¡éª |
| | | this.dispatch('tn-form-item','on-form-blur', value) |
| | | }, 40) |
| | | }, |
| | | // å¤çæ ¡éªé误 |
| | | onFormItemError(status) { |
| | | this.validateState = status |
| | | }, |
| | | // èç¦äºä»¶ |
| | | onFocus(event) { |
| | | this.focused = true |
| | | this.$emit('focus') |
| | | }, |
| | | // ç¹å»ç¡®è®¤æé®äºä»¶ |
| | | onConfirm(event) { |
| | | this.$emit('confirm', event.detail.value) |
| | | }, |
| | | // æ¸
é¤äºä»¶ |
| | | onClear(event) { |
| | | this.$emit('input', '') |
| | | }, |
| | | // ç¹å»äºä»¶ |
| | | inputClick() { |
| | | this.$emit('click') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-input { |
| | | display: flex; |
| | | flex-direction: row; |
| | | position: relative; |
| | | flex: 1; |
| | | |
| | | &__input { |
| | | font-size: 28rpx; |
| | | color: $tn-font-color; |
| | | flex: 1; |
| | | } |
| | | |
| | | &__textarea { |
| | | width: auto; |
| | | font-size: 28rpx; |
| | | color: $tn-font-color; |
| | | padding: 10rpx 0; |
| | | line-height: normal; |
| | | flex: 1; |
| | | } |
| | | |
| | | &--border { |
| | | border-radius: 6rpx; |
| | | border: 2rpx solid $tn-border-solid-color; |
| | | } |
| | | |
| | | &--error { |
| | | border-color: $tn-color-red !important; |
| | | } |
| | | |
| | | &__right-icon { |
| | | line-height: 1; |
| | | .icon { |
| | | color: $tn-font-sub-color; |
| | | } |
| | | |
| | | &__item { |
| | | margin-left: 10rpx; |
| | | } |
| | | |
| | | &__clear { |
| | | .icon { |
| | | font-size: 32rpx; |
| | | } |
| | | } |
| | | |
| | | &__select { |
| | | transition: transform .4s; |
| | | |
| | | .icon { |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | &--reverse { |
| | | transform: rotate(-180deg); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="value" class="tn-keyboard-class tn-keyboard"> |
| | | <tn-popup |
| | | v-model="value" |
| | | mode="bottom" |
| | | :popup="false" |
| | | length="auto" |
| | | :mask="mask" |
| | | :maskCloseable="maskCloseable" |
| | | :safeAreaInsetBottom="safeAreaInsetBottom" |
| | | :zIndex="elZIndex" |
| | | @close="popupClose" |
| | | > |
| | | <view> |
| | | <slot></slot> |
| | | </view> |
| | | |
| | | <!-- æç¤ºä¿¡æ¯ --> |
| | | <view v-if="tooltip" class="tn-keyboard__tooltip"> |
| | | <view |
| | | v-if="cancelBtn" |
| | | class="tn-keyboard__tooltip__item tn-keyboard__tooltip__cancel" |
| | | hover-class="tn-keyboard__tooltip__cancel--hover" |
| | | :hover-stay-time="150" |
| | | @tap="onCancel" |
| | | > |
| | | {{ cancelBtn ? cancelText : ''}} |
| | | </view> |
| | | <view v-if="showTips" class="tn-keyboard__tooltip__item tn-keyboard__tooltip__tips"> |
| | | {{ tips ? tips : mode === 'number' ? 'æ°åé®ç' : mode === 'card' ? '身份è¯é®ç' : '车çå·ç é®ç'}} |
| | | </view> |
| | | <view |
| | | v-if="confirmBtn" |
| | | class="tn-keyboard__tooltip__item tn-keyboard__tooltip__confirm" |
| | | hover-class="tn-keybord__tooltip__confirm--hover" |
| | | :hover-stay-time="150" |
| | | @tap="onConfirm" |
| | | > |
| | | {{ confirmBtn ? confirmText : ''}} |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- é®çå
容 --> |
| | | <block v-if="mode === 'number' || mode === 'card'"> |
| | | <tn-number-keyboard :mode="mode" :dotEnabled="dotEnabled" :randomEnabled="randomEnabled" @change="change" @backspace="backspaceClick"></tn-number-keyboard> |
| | | </block> |
| | | <block v-if="mode === 'car'"> |
| | | <tn-car-keyboard :randomEnabled="randomEnabled" :switchEnMode="switchEnMode" @change="change" @backspace="backspaceClick"></tn-car-keyboard> |
| | | </block> |
| | | </tn-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-keyboard', |
| | | props: { |
| | | // æ§å¶é®çå¼¹åºæ¶å |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // é®çç±»å |
| | | // number - æ°åé®ç card - 身份è¯é®ç car - 车çå·ç |
| | | mode: { |
| | | type: String, |
| | | default: 'number' |
| | | }, |
| | | // å½mode = numberæ¶ï¼æ¯å¦æ¾ç¤º'.'ç¬¦å· |
| | | dotEnabled: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æä¹±é¡ºåº |
| | | randomEnabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å½mode = carï¼è®¾ç½®é®çä¸è±æç¶æ |
| | | switchEnMode: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¾ç¤ºé¡¶é¨å·¥å
·æ¡ |
| | | tooltip: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | showTips: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æç¤ºæå |
| | | tips: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºåæ¶æé® |
| | | cancelBtn: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºç¡®è®¤æé® |
| | | confirmBtn: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // åæ¶æé®æå |
| | | cancelText: { |
| | | type: String, |
| | | default: 'åæ¶' |
| | | }, |
| | | // 确认æé®æå |
| | | confirmText: { |
| | | type: String, |
| | | default: '确认' |
| | | }, |
| | | // æ¯å¦å¼å¯åºé¨å®å
¨åºéé
ï¼å¼å¯çè¯ï¼ä¼å¨iPhoneXæºååºé¨æ·»å ä¸å®çå
è¾¹è· |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¯ä»¥éè¿ç¹å»é®ç½©è¿è¡å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé®ç½© |
| | | mask: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // z-index |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | elZIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.popup |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | change(e) { |
| | | this.$emit('change', e) |
| | | }, |
| | | // å
³éé®ç |
| | | popupClose() { |
| | | // ä¿®æ¹valueçå¼ |
| | | this.$emit('input', false) |
| | | }, |
| | | // è¾å
¥å®æ |
| | | onConfirm() { |
| | | this.popupClose() |
| | | this.$emit('confirm') |
| | | }, |
| | | // è¾å
¥åæ¶ |
| | | onCancel() { |
| | | this.popupClose() |
| | | this.$emit('cancel') |
| | | }, |
| | | // ç¹å»éæ ¼ |
| | | backspaceClick() { |
| | | this.$emit('backspace') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-keyboard { |
| | | position: relative; |
| | | |
| | | &__tooltip { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | |
| | | &__item { |
| | | color: $tn-font-color; |
| | | flex: 0 0 33.3333333333%; |
| | | text-align: center; |
| | | font-size: 28rpx; |
| | | padding: 20rpx 10rpx; |
| | | } |
| | | |
| | | &__cancel { |
| | | text-align: left; |
| | | flex-grow: 1; |
| | | flex-wrap: 0; |
| | | padding-left: 40rpx; |
| | | color: $tn-content-color; |
| | | |
| | | &--hover { |
| | | color: $tn-font-color; |
| | | } |
| | | } |
| | | |
| | | &__confirm { |
| | | text-align: right; |
| | | flex-grow: 1; |
| | | flex-wrap: 0; |
| | | padding-right: 40rpx; |
| | | color: $tn-main-color; |
| | | |
| | | &--hover { |
| | | color: $tn-color-blue; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-landscape-class tn-landscape"> |
| | | <view v-if="showValue" class="tn-landscape__container" :style="[containerStyle]"> |
| | | <slot></slot> |
| | | <view |
| | | v-if="closeBtn" |
| | | class="tn-landscape__icon tn-icon-close-fill" |
| | | :class="[{ |
| | | 'tn-landscape__icon--left-top': closePosition === 'leftTop', |
| | | 'tn-landscape__icon--right-top': closePosition === 'rightTop', |
| | | 'tn-landscape__icon--bottom': closePosition === 'bottom' |
| | | }]" |
| | | :style="[closeBtnStyle]" |
| | | @tap="close" |
| | | ></view> |
| | | </view> |
| | | <view |
| | | v-if="mask" |
| | | class="tn-landscape__mask" |
| | | :class="[{'tn-landscape__mask--show': showValue}]" |
| | | :style="[maskStyle]" |
| | | @tap="closeMask" |
| | | ></view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-landscape', |
| | | props: { |
| | | // æ¾ç¤º |
| | | show: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¾ç¤ºå
³é徿 |
| | | closeBtn: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å
³é徿 é¢è² |
| | | closeColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å
³é徿 大å°ï¼åä½rpx |
| | | closeSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
³é徿 ä½ç½® |
| | | // leftTop -> å·¦ä¸è§ rightTop -> å³ä¸è§ bottom -> åºé¨ |
| | | closePosition: { |
| | | type: String, |
| | | default: 'rightTop' |
| | | }, |
| | | // å
³é徿 topå¼ï¼åä½rpx |
| | | // å½å
³é徿 å¨leftTopæè
rightTopæ¶çæ |
| | | closeTop: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
³é徿 rightå¼ï¼åä½rpx |
| | | // å½å
³é徿 å¨RightTopæ¶çæ |
| | | closeRight: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
³é徿 bottomå¼ï¼åä½rpx |
| | | // å½å
³é徿 å¨bottomæ¶çæ |
| | | closeBottom: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
³é徿 leftå¼ï¼åä½rpx |
| | | // å½å
³é徿 å¨leftTopæ¶çæ |
| | | closeLeft: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¾ç¤ºé®ç½© |
| | | mask: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ç¹å»é®ç½©å¯ä»¥å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // zIndex |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | containerStyle() { |
| | | let style = {} |
| | | style.zIndex = this.zIndex ? this.zIndex : this.$t.zIndex.landsacpe |
| | | return style |
| | | }, |
| | | closeBtnStyle() { |
| | | let style = {} |
| | | if (this.closePosition === 'leftTop') { |
| | | if (this.closeTop) { |
| | | style.top = this.closeTop + 'rpx' |
| | | } |
| | | if (this.closeLeft) { |
| | | style.left = this.closeLeft + 'rpx' |
| | | } |
| | | } else if (this.closePosition === 'rightTop') { |
| | | if (this.closeTop) { |
| | | style.top = this.closeTop + 'rpx' |
| | | } |
| | | if (this.closeRight) { |
| | | style.right = this.closeRight + 'rpx' |
| | | } |
| | | } else if (this.closePosition === 'bottom') { |
| | | if (this.closeBottom) { |
| | | style.bottom = this.closeBottom + 'rpx' |
| | | } |
| | | } |
| | | if (this.closeSize) { |
| | | style.fontSize = this.closeSize + 'rpx' |
| | | } |
| | | if (this.closeColor) { |
| | | style.color = this.closeColor |
| | | } |
| | | return style |
| | | }, |
| | | maskStyle() { |
| | | let style = {} |
| | | style.zIndex = this.zIndex ? this.zIndex - 1 : this.$t.zIndex.landsacpe - 1 |
| | | return style |
| | | } |
| | | }, |
| | | watch: { |
| | | show: { |
| | | handler(val) { |
| | | this.showValue = val |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | showValue: false |
| | | } |
| | | }, |
| | | methods: { |
| | | // å
³éåå±çª |
| | | close() { |
| | | this.showValue = false |
| | | this.$emit('close') |
| | | }, |
| | | // ç¹å»é®ç½©å
³é |
| | | closeMask() { |
| | | if (!this.maskCloseable) return |
| | | this.close() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-landscape { |
| | | width: 100%; |
| | | overflow: hidden; |
| | | |
| | | &__container { |
| | | max-width: 100%; |
| | | position: fixed; |
| | | display: inline-flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | } |
| | | |
| | | &__icon { |
| | | position: absolute; |
| | | text-align: center; |
| | | font-size: 50rpx; |
| | | color: #FFFFFF; |
| | | |
| | | &--left-top { |
| | | top: -40rpx; |
| | | left: 20rpx; |
| | | } |
| | | |
| | | &--right-top { |
| | | top: -40rpx; |
| | | right: 40rpx; |
| | | } |
| | | |
| | | &--bottom { |
| | | left: 50%; |
| | | bottom: -40rpx; |
| | | transform: translateX(-50%); |
| | | } |
| | | } |
| | | |
| | | &__mask { |
| | | position: fixed; |
| | | width: 100%; |
| | | height: 100%; |
| | | background-color: $tn-mask-bg-color; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | opacity: 0; |
| | | transform: scale3d(1, 1, 0); |
| | | transition: all 0.25s ease-in; |
| | | |
| | | &--show { |
| | | opacity: 1 !important; |
| | | transform: scale3d(1, 1, 1); |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-lazy-load-class tn-lazy-load"> |
| | | <view |
| | | class="tn-lazy-load__item" |
| | | :class="[`tn-lazy-load__item--${elIndex}`]" |
| | | :style="[lazyLoadItemStyle]" |
| | | > |
| | | <view class="tn-lazy-load__item__content"> |
| | | <image |
| | | v-if="!error" |
| | | class="tn-lazy-load__item__image" |
| | | :style="[imageStyle]" |
| | | :src="show ? image : loadingImg" |
| | | :mode="imgMode" |
| | | @load="handleImgLoaded" |
| | | @error="handleImgError" |
| | | @tap="handleImgClick" |
| | | ></image> |
| | | <image |
| | | v-else |
| | | class="tn-lazy-load__item__image tn-lazy-load__item__image--error" |
| | | :style="[imageStyle]" |
| | | :src="errorImg" |
| | | :mode="imgMode" |
| | | @load="handleErrorImgLoaded" |
| | | @tap="handleImgClick" |
| | | ></image> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-lazy-load', |
| | | props: { |
| | | // ç»ä»¶æ è¯ |
| | | index: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // å¾
æ¾ç¤ºçå¾çå°å |
| | | image: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å¾çè£åªæ¨¡å¼ |
| | | imgMode: { |
| | | type: String, |
| | | default: 'scaleToFill' |
| | | }, |
| | | // å ä½å¾çè·¯å¾ |
| | | loadingImg: { |
| | | type: String, |
| | | // default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM0QjNBQjkyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM0QjNBQkEyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzRCM0FCNzJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzRCM0FCODJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtRHfPcAAAAzUExURZWVldfX18PDw62trZubm9zc3Li4uKGhoebm5tLS0uHh4c3Nzaenp729vcjIyLKysuvr6141L40AAAcXSURBVHja7NzZlqpGAEBR5lG0//9rIw7IJKJi4or7PGTdtN10wr5SVAEGf/qqArsAiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAg+nmQFMi5Jis+sIniED23jSzIgLTtg2D//iYme/8QBM/9lQ+CAEhbNLM3N9hEHAThX7GPCiBfAxK1b51kD+R7QMLjXg7iCsgWIPUh7pfVozG791oeBPngm48G583uW5GkBvI+SBaM2xXDn1oqum423bX/mgF5FySc2cv93Voug9TdZotsggnkBZB2NzbhrSY5HnoG07jei8dvzsJB/c3W60SALILE46+WCztsbhPR7R2VJq0ukEcT49nyy8QhaKcRa3fYHZD4+ufqOJAcgDz8/59vtw1I3QP5K6JsOG0vm3hce4I8LQp/BaRZGJC3AAn7IKOKXbC+7EdA5vdmmVwOLksgRThqOqiH4XEGsht+peoPUE8U/jJIO5OLH4GEwUslV5G0PTBG5Uiw/Y2jyigO3l9HAHKv9PYb82LloH74dZBoBUgar+l48NsNvtD0fkez9iwrAvIYZDRCl+Xs149Hm/KZmQ+QjUCiO1ei4ru7EsgnQYrkznlQb7thCuRfAzlOAPN72427P4VA/i2Q/DKT/Ls/VR8fvIBsDZIuz7TPF6TCbnk4GJkB2RokejTjuE7/unlgCuSTIO0Cy+Plp6vDfnQlBchy8QtjSHVd3EgmK1bHLm+H6+nXYbz2DuQRSPnqoL7vvq0u70on4zvxgCyWD3b9UyDVdW24PaWaiGTnFZJwPIQAebDpIKheBIm7n124ZthMJipAlkqHO+IZkP1tbfzOJark/A7MgKyvvl60fRqkvXfhuow+t9+q00+0/yyBrK8ZngOtBzldhw2X9tvpNGty0gvkmbPeJ0Cy/r09s/stbmfo0yMWkEdjevgKyOn2t2pxv7UXoibTdCDLje9/Ww1ymqzn87dbp92242ZmMRjI8hASvwKSLq4udqN6ksw8nxXN3tszD9L8Gkg+2mFrQYql5az4tvFj5xOx4VwnSdeBtGdyPwUytxK77pBVlNHdO7OK3rh/eTPUvdutT3fO52tuHMqD4N7llv8pyOQQ//w19YVDfX27+Sfuby9/6nau4pdA8vEdOZuChEH/quHt0Jg+IRJ/5+PrHwKZXfjbDiS73Zo7mu5UkzX7uTsXe0e/7nC3ePf1O69+BUg2XDfZCqSqOu7rGVf8cHBe8zhC2b61dtUHXv0OkGo6ZL4JkpbRYXdUaFevivx2M/1GIOctNh949TtAoumQ+TpIHMX54CJu+8BDd8FkE5BqcZh/59XvAClmTvKfB0nDqIlHo3T70SftyW1eX9dXtgQJqs1f/Q6QaOa/7wmQKtxH8eiGoCRuovODIO3VxOMmruZbHrLyD7z6DSDtGyT7ew1kf9hNn07c986JTovzzem0Id9wUG+Vk/IDr34DSNR7huZJkMFT6vEhqrPx/j5cnlZML8N6/PAzh9Y99Flm5Yde/c9BquDOkvkKkMP58dA4qi9vivE8JOvGz/j8FokfPpr288+pH2ZPOZrLmeGD+7KOh6dqYWJ48ki7yUg0tz0go/fv/LLddfV3sgOLJyaGPY/zrSlh1a36Arkzoue9CyG35ze6E6/dzO2Ga0EGHqdRJIkfn9/8OEjTW8Vq91ZWh39FeehWA7Nu9ft8CpUEk1WWOyDF0OPyEU2Pnzf/bZC0P6IPzmAvu7KauQBVrgKpJ0tG2arHzX8e5Pb3PezNs/PrX+3JMyCLn9XXf37tPFHvt09WfCDDjx+yyn1/p1V11j7GnB/q3leLuVva79S/tzed+db08YpF4uOZtmz/9oXWMq6BCAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiAALELvqt/BBgACqVeUBXxcCkAAAAASUVORK5CYII=' |
| | | }, |
| | | // å 载失败çé误å ä½å¾ |
| | | errorImg: { |
| | | type: String, |
| | | default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODdDMjhENDYyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODdDMjhENDcyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4N0MyOEQ0NDJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4N0MyOEQ0NTJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhLwhikAAAAzUExURZWVldfX162trcPDw5ubm7i4uNzc3Obm5s3NzaGhoeHh4cjIyKenp9LS0r29vbKysuvr67sDMEkAAAlpSURBVHja7NzpYqMgAIVRUVHc8/5PO66R1WAbOzX97q+ZtDEpR0AWTR7kVyWhCAAhgABCAAGEAAIIAQQQAggBBBACCCAEEEAIIIAQQAgggBBAACGAAEIAAYQAQgABhAACCAEEEAIIIAQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAsqeX5QWHKIcs/Ptl03lfL4zDFPWfBGmSpPn+IZzSH5KkCL5B+n+oklwz6Iz//R2QzFOabzhEmiRirAmZt/bl0w/dpMbLqeeo4wEdpC7zR5WAPKziHKtO7ql+ReKvIa9BxgNaL5ZtEkpeAGIVp5jKJa09xVo9vgSSzQcszdYvmOqjQNSQ6pHK6rO1n1Xj32788miwHLaZz1Tl9i/yayDlYJ/60/+lp8GSY7OY1B8E4p55bWmfquFk22GLuUUxi78cX+m+BjL2GLkhMrV+/muS6Sfic0CEp5T1Yu2OQdTzsKV0MJV73KVjroyTffxfuv5Tf3fd6iLT9wz8YdVHgUzF2Is9/Xhi5sYJqP1w/GUpjOiHVbaI0w2L+pg3GZzvtokcgHxWDXHaiy78l3sPke01qphamT5c+dqyeAGSumdL/mkggauTam0e3L/mPEiqtzKDbl0Z1Wn8xOa4ySo8X/7TQIJnY/seEKWf12UmC72CKP9xYjr19RPT7NNA+oMO+R0gwmlotAry+C6I0f59ch8yXVQOr0BKYcXt1IUYRyCt+Ur9HGsrQKI79WY9sY9ARPKlzFOFdb41ioD8b5Bp+mqeeRKAxINkESBFGpOpKhgv9OuYpH8A8l4Qa3qp60Kl2/k+rG2sWafuuyCBafb2j4JkgZUob3nWcmicpkxEgmTLLGejTxnWSWCi8lPmsk6DlIHFJv24ojiYyYoGacwL8zXTLEAVaDI/Ybb3NIgKDSv2oXpmHkvNs+PTpMASEdlk7fOZeRk37fwJ6yGnQarQsGIfqqcvx43rTOXY6jf7uKXdRzdLDRPbjIrx1cIj3Kr4KyBFezzgUGuR5893qkOQ19fR2uVBaU+r16LphJNOiatK7PeBZK/Kb+tUn71rcQjSvARpghfH/yG/D2RetTuI3N5QrMWdP46brP7FmKZ//CGQ9At9SL01DLkzY/Vs8Z97fQZ7gelw7jHqCz+/Wile5J4g3Vc79eb5a6oLSue+Ve83gaSv2jp5PxCzjzwFUm9zw9MllSMil1kS4d2E9SaQ1xNo9wMxx0+nQNLnew/WDHvveMAHYm08mofl3TFI/8pD3Q6kMAv6DIi2jTCwRJUvNdDYrrJum9oHhusCbWALonwxBRk1vXMnEGWuT5wAmfYuVGUYpJ7fUZujCN92hvzwWlrFgxSfANKb10DxIMbShnfrynyZZV30imA7P43ArXXHbvBVkTCIuGy25AdBrHmNeBCpL214QdLp9LZarG3IMWrmW0ehtuO7F2PS09UcgqS3B7FKPhpknrStD0HGF/vQRne37LwLG8EbHT4WxN7/Fg0yD9Yr/3br4nnstA+0Il6QxzdBmg8A6a2/IRbkcK9h/uzV8zywF/oSkOyageCPglRWgcWClHnEzs9q/t/SENVXgFijlsq3VtXdCsRp4qObrLLLgjuzSq3fX89ZZW6AfxNIzF6X9FYgThN/fk093KkvHX/hbWd+DqS/FUhlf+G3gohEXzVs3g9iDluWoaW8fL73QhB34u+tIHIf19nLuF4Q98a09Eynnl56q+ePgEhnX+dbQOp6H5XnJ0ACd8dFgkwf12nTOTcEqd2pom+CFF02TIPw6dKmrLS5qOtBpo8b5quUtrwrSGbuqPkeSJqllTFHO02NPxdMrm+y5LKdWyWXjw4vA5nGEtnjuyCFyHqNYvEolzmASm3zK1Eg5zr13lhqV1tlksnVw8Pkwgri7O07AVKLJkutRYw87bPlRpBpNXE8xGb+fhBlvEGrGPLqViu5sILIx9dAmqF1705sxF4M8+R8P5dOdQwi12fMnATpjJ2JSt/POIvU9wPJEs/jduJAjLvU0yFT0i64Yb1bsVi79dA4pEy3TzoHMq2O7Re4vXm5O9+l290NpE4CU+YRIMNye2iaqbVS2AUnn2fsekthYKReVNutVedA5juttyIXrT38mOds+ps9DWhwL7GWc61/DVKPzVN9UHDarf1icU98IOU8tm6L031Iq63t1tKzj3fe/FCpO4F0/i0Z2+yvA1KeGBjqj1qYx8/zoxpKZ1Yl367I1k+sfcft/QPy9csXy/32qX1qLZsrryG5BGQaRj0vc/b7N54XXq293TCLB5HO42Fy517obW19b+qjl3CHp0fdLJcWvmdy1etESi/uAdJrs1hTaUklHuW8qSDdC3UfXVR5cnD3rAFSSqtFb7z7eapErx7rC739jCXfbK3aWiipjXo8UbmxXPa7QQq9R289j2Gr88N7Ag5AlHPRKc37pNZv0CZtX1tVMG6rm8qW1/KlCgQvcMss933ybwXZz3dReW5yce4ByZtHFIhwT9kmjxg8BzbKDUe1PB9edBJqSN7/KM1LmqyuMZ5BpeTUw1aD/uDI0relPfSHa/Wn8Pxq1BNfxy/h3IdwOJqIKumb9CHvTqMefyY82RoQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAGEAAIIAQQQAgggBBBACCAEEEAIIIAQQAAhgABCACGAAEIAAYQAAggBBBACCAEEEAIIIAQQQAggfyL/BBgA8PgLdH0TBtkAAAAASUVORK5CYII=' |
| | | }, |
| | | // å¾çè¿å
¥å¯è§åºååå¤å°åç´ åï¼åä½rpxï¼å¼å§å è½½å¾ç |
| | | // è´æ°ä¸ºå¾çè¶
åºå±å¹åºé¨å¤å°åç´ å触åæå è½½ï¼æ£æ°ä¸ºå¾çé¡¶é¨è·ç¦»å±å¹åºé¨å¤å°è·ç¦»æ¶è§¦åï¼å¾çè¿æ²¡åºç°å¨å±å¹ä¸ï¼ |
| | | threshold: { |
| | | type: [Number, String], |
| | | default: 100 |
| | | }, |
| | | // æ¯å¦å¼å¯è¿æ¸¡ææ |
| | | isEffect: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å¨ç»è¿æ¸¡æ¶é´ |
| | | duration: { |
| | | type: [String, Number], |
| | | default: 500 |
| | | }, |
| | | // 渡ææçé度æ²çº¿ï¼å个ä¹é´å·®å«ä¸å¤§ï¼å ä¸ºè¿æ¯æ·¡å
¥æ·¡åºï¼ä¸æ¶é´å¾çï¼ä¸æ¯é£äºåå½¢æè
ç§»å¨çæ
åµï¼ä¼ææ¾ |
| | | // linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n); |
| | | effect: { |
| | | type: String, |
| | | default: 'ease-in-out' |
| | | }, |
| | | // å¾çé«åº¦ï¼åä½rpx |
| | | height: { |
| | | type: [String, Number], |
| | | default: 450 |
| | | }, |
| | | // å¾çåè§ |
| | | borderRadius: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | computed: { |
| | | thresholdValue() { |
| | | // å
åç»å¯¹å¼ï¼å 为thresholdå¯è½æ¯è´æ°ï¼æåæ ¹æ®this.thresholdæ¯æ£æ°æè
è´æ°ï¼éæ°è¿å |
| | | let threshold = uni.upx2px(Math.abs(this.threshold)) |
| | | return this.threshold < 0 ? -threshold : threshold |
| | | }, |
| | | lazyLoadItemStyle() { |
| | | let style = {} |
| | | style.opacity = Number(this.opacity) |
| | | if (this.borderRadius) { |
| | | style.borderRadius = this.borderRadius |
| | | } |
| | | // å 为timeå¼éè¦æ¹å,æä»¥ä¸ç´æ¥ç¨durationå¼(ä¸è½æ¹åç¶ç»ä»¶propä¼ è¿æ¥çå¼) |
| | | style.transition = `opacity ${this.time / 1000}s ${this.effect}` |
| | | style.height = this.$t.string.getLengthUnitValue(this.height) |
| | | return style |
| | | }, |
| | | imageStyle() { |
| | | let style = {} |
| | | if (typeof this.height === 'string' && this.height.indexOf('%') === -1) { |
| | | style.height = this.$t.string.getLengthUnitValue(this.height) |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | watch: { |
| | | show(val) { |
| | | // 妿ä¸å¼å¯è¿æ¸¡ææç´æ¥è¿å |
| | | if (!this.effect) return |
| | | this.time = 0 |
| | | // 忥opacity为1(ä¸éæï¼æ¯ä¸ºäºæ¾ç¤ºå ä½å¾)ï¼æ¹æ0(éæï¼æå³ç该å
ç´ æ¾ç¤ºçæ¯èæ¯é¢è²ï¼é»è®¤çç½è²)ï¼åæ¹æ1ï¼æ¯ä¸ºäºè·å¾è¿æ¸¡ææ |
| | | this.opacity = 0 |
| | | setTimeout(() => { |
| | | this.time = this.duration |
| | | this.opacity = 1 |
| | | }, 30) |
| | | }, |
| | | image(val) { |
| | | // ä¿®æ¹å¾çåéç½®é¨ååé |
| | | if (!val) { |
| | | // å¦æä¼ å
¥nullæè
''ï¼æè
undefinedï¼æ 记为éè¯¯ç¶æ |
| | | this.error = true |
| | | } else { |
| | | this.init() |
| | | this.error = false |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | elIndex: this.$t.uuid(), |
| | | // æ¾ç¤ºå¾ç |
| | | show: false, |
| | | // å¾çéæåº¦ |
| | | opacity: 1, |
| | | // å¨ç»æ¶é´ |
| | | time: this.duration, |
| | | // æå è½½ç¶æ |
| | | // loadlazy-æå è½½ä¸ç¶æï¼loading-å¾çæ£å¨å è½½ï¼loaded-å¾çå å è½½å®æ |
| | | loadStatus: '', |
| | | // å¾çå 载失败 |
| | | error: false |
| | | } |
| | | }, |
| | | created() { |
| | | // ç±äºä¸äºç¹æ®åå ï¼ä¸è½å°æ¤åéæ¾å°dataä¸å®ä¹ |
| | | this.observer = {} |
| | | this.observerName = 'lazyLoadContentObserver' |
| | | }, |
| | | mounted() { |
| | | // å¨éè¦ç¨å°æå è½½ç页é¢ï¼å¨è§¦ååºé¨çæ¶å触åtOnLazyLoadReachBottomäºä»¶ï¼ä¿è¯ææå¾çè¿è¡å è½½ |
| | | this.$nextTick(() => { |
| | | uni.$once('tOnLazyLoadReachBottom', () => { |
| | | if (!this.show) this.show = true |
| | | }) |
| | | }) |
| | | // mountedçæ¶åï¼ä¸ä¸å®æè½½äºè¿ä¸ªå
ç´ ï¼å»¶æ¶30msï¼å¦å伿¥éæè
䏿¥éï¼ä½æ¯ä¹æ²¡æææ |
| | | setTimeout(() => { |
| | | this.disconnectObserver(this.observerName) |
| | | const contentObserver = uni.createIntersectionObserver(this) |
| | | contentObserver.relativeToViewport({ |
| | | bottom: this.thresholdValue |
| | | }).observe(`.tn-lazy-load__item--${this.elIndex}`, (res) => { |
| | | if (res.intersectionRatio > 0) { |
| | | // æå è½½ç¶ææ¹å |
| | | this.show = true |
| | | // 妿å¾çå·²ç»å è½½ï¼å»æçå¬ï¼åå°æ§è½æ¶è |
| | | this.disconnectObserver(this.observerName) |
| | | } |
| | | }) |
| | | this[this.observerName] = contentObserver |
| | | }, 50) |
| | | }, |
| | | methods: { |
| | | // åå§å |
| | | init() { |
| | | this.error = false |
| | | this.loadStatus = '' |
| | | }, |
| | | // å¤çå¾çç¹å»äºä»¶ |
| | | handleImgClick() { |
| | | let whichImg = '' |
| | | // 妿show为falseï¼å表示å¾çè¿æ²¡æå¼å§å è½½ï¼ç¹å»çæ¯æå¼å§å ä½å¾ |
| | | if (this.show === false) whichImg = 'lazyImg' |
| | | // 妿error为trueï¼å表示å¾çå 载失败ï¼ç¹å»çæ¯é误å ä½å¾ |
| | | else if (this.error === true) whichImg = 'errorImg' |
| | | // ç¹å»äºæ£å¸¸çå¾ç |
| | | else whichImg = 'realImg' |
| | | |
| | | this.$emit('click', { |
| | | index: this.index, |
| | | whichImg: whichImg |
| | | }) |
| | | }, |
| | | // å¤çå¾çå è½½å®æäºä»¶ï¼éè¿showæ¥åºåæ¯å ä½å¾è§¦åè¿æ¯å è½½çæ£çå¾ç触å |
| | | handleImgLoaded() { |
| | | if (this.loadStatus = '') { |
| | | // å ä½å¾å è½½å®æ |
| | | this.loadStatus = 'lazyed' |
| | | } |
| | | else if (this.loadStatus == 'lazyed') { |
| | | // çæ£çå¾çå è½½å®æ |
| | | this.loadStatus = 'loaded' |
| | | this.$emit('loaded', this.index) |
| | | } |
| | | }, |
| | | // å¤çé误å¾çå è½½å®æ |
| | | handleErrorImgLoaded() { |
| | | this.$emit('error', this.index) |
| | | }, |
| | | // å¤çå¾çå 载失败 |
| | | handleImgError() { |
| | | this.error = true |
| | | }, |
| | | disconnectObserver(observerName) { |
| | | const observer = this[observerName] |
| | | observer && observer.disconnect() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-lazy-load { |
| | | &__item { |
| | | background-color: $tn-bg-gray-color; |
| | | overflow: hidden; |
| | | |
| | | &__image { |
| | | // è§£å³ç¶å®¹å¨ä¼å¤åº3pxçé®é¢ |
| | | display: block; |
| | | width: 100%; |
| | | // éªç³»ç»å¼å¯ç¡¬ä»¶å é |
| | | transform: transition3d(0, 0, 0); |
| | | // 鲿¢å¾çå è½½âéªä¸ä¸â |
| | | will-change: transform; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-line-progress-class tn-line-progress" |
| | | :style="[progressStyle]" |
| | | > |
| | | <view |
| | | class="tn-line-progress--active" |
| | | :class="[ |
| | | $t.color.getBackgroundColorInternalClass(activeColor), |
| | | striped ? stripedAnimation ? 'tn-line-progress__striped tn-line-progress__striped--active' : 'tn-line-progress__striped' : '', |
| | | ]" |
| | | :style="[progressActiveStyle]" |
| | | > |
| | | <slot v-if="$slots.default || $slots.$default"></slot> |
| | | <block v-else-if="showPercent">{{ percent + '%' }}</block> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-line-progress', |
| | | props: { |
| | | // è¿åº¦ï¼ç¾åæ¯ï¼ |
| | | percent: { |
| | | type: Number, |
| | | default: 0, |
| | | validator: val => { |
| | | return val >= 0 && val <= 100 |
| | | } |
| | | }, |
| | | // é«åº¦ |
| | | height: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºä¸ºåè§ |
| | | round: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºæ¡çº¹ |
| | | striped: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¡çº¹æ¯å¦è¿å¨ |
| | | stripedAnimation: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¿æ´»é¨åé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // éæ¿æ´»é¨åé¢è² |
| | | inactiveColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¿åº¦æ¡å
é¨ç¾åæ¯å¼ |
| | | showPercent: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | progressStyle() { |
| | | let style = {} |
| | | style.borderRadius = this.round ? '100rpx' : 0 |
| | | if (this.height) { |
| | | style.height = this.$t.string.getLengthUnitValue(this.height) |
| | | } |
| | | if (this.inactiveColor) { |
| | | style.backgroundColor = this.inactiveColor |
| | | } |
| | | return style |
| | | }, |
| | | progressActiveStyle() { |
| | | let style = {} |
| | | style.width = this.percent + '%' |
| | | if (this.$t.color.getBackgroundColorStyle(this.activeColor)) { |
| | | style.backgroundColor = this.$t.color.getBackgroundColorStyle(this.activeColor) |
| | | } |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-line-progress { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 28rpx; |
| | | overflow: hidden; |
| | | border-radius: 100rpx; |
| | | background-color: $tn-progress-bg-color; |
| | | |
| | | &--active { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-items: flex-end; |
| | | justify-content: space-around; |
| | | width: 0; |
| | | height: 100%; |
| | | font-size: 20rpx; |
| | | color: #FFFFFF; |
| | | background-color: $tn-main-color; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | &__striped { |
| | | background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); |
| | | background-size: 80rpx 80rpx; |
| | | |
| | | &--active { |
| | | animation: progress-striped 2s linear infinite; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @keyframes progress-striped { |
| | | 0% { |
| | | background-position: 0 0; |
| | | } |
| | | 100% { |
| | | background-position: 80rpx 0; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-list-cell-class tn-list-cell" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | fontColorClass, |
| | | cellClass |
| | | ]" |
| | | :hover-class="hover ? 'tn-hover' : ''" |
| | | :hover-stay-time="150" |
| | | :style="[cellStyle]" |
| | | @tap="handleClick" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [ componentsColorMixin ], |
| | | name: 'tn-list-cell', |
| | | props: { |
| | | // å表åºå· |
| | | index: { |
| | | type: [Number, String], |
| | | default: '0' |
| | | }, |
| | | // å
è¾¹è· |
| | | padding: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦æç®å¤´ |
| | | arrow: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | //ç®å¤´æ¯å¦æåç§»è·ç¦» |
| | | arrowRight: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æç¹å»ææ |
| | | hover: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // éèçº¿æ¡ |
| | | unlined: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | //çº¿æ¡æ¯å¦æå·¦åç§»è·ç¦» |
| | | lineLeft: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | //çº¿æ¡æ¯å¦æå³åç§»è·ç¦» |
| | | lineRight: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | //æ¯å¦å åè§ |
| | | radius: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | cellClass() { |
| | | let clazz = '' |
| | | |
| | | if (this.arrow) { |
| | | clazz += ' tn-list-cell--arrow' |
| | | if (!this.arrowRight) { |
| | | clazz += ' tn-list-cell--arrow--none-right' |
| | | } |
| | | } |
| | | |
| | | if (this.unlined) { |
| | | clazz += ' tn-list-cell--unlined' |
| | | } else { |
| | | if (this.lineLeft) { |
| | | clazz += ' tn-list-cell--line-left' |
| | | } |
| | | if (this.lineRight) { |
| | | clazz += ' tn-list-cell--line-right' |
| | | } |
| | | } |
| | | |
| | | if (this.radius) { |
| | | clazz += ' tn-list-cell--radius' |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | cellStyle() { |
| | | let style = {} |
| | | |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | |
| | | if (this.fontSize) { |
| | | style.fontSize = this.fontSize + this.fontUnit |
| | | } |
| | | |
| | | if (this.padding) { |
| | | style.padding = this.padding |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çç¹å»äºä»¶ |
| | | handleClick() { |
| | | this.$emit("click", { |
| | | index: Number(this.index) |
| | | }) |
| | | this.$emit("tap", { |
| | | index: Number(this.index) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-list-cell { |
| | | position: relative; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | background-color: #FFFFFF; |
| | | color: $tn-font-color; |
| | | font-size: 28rpx; |
| | | padding: 26rpx 30rpx; |
| | | |
| | | &--radius { |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &--arrow { |
| | | &::before { |
| | | content: " "; |
| | | position: absolute; |
| | | top: 50%; |
| | | right: 30rpx; |
| | | width: 20rpx; |
| | | height: 20rpx; |
| | | margin-top: -12rpx; |
| | | border-width: 4rpx 4rpx 0 0; |
| | | border-color: $tn-font-holder-color; |
| | | border-style: solid; |
| | | transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); |
| | | } |
| | | |
| | | &--none-right { |
| | | &::before { |
| | | right: 0 !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &::after { |
| | | content: " "; |
| | | position: absolute; |
| | | bottom: 0; |
| | | right: 0; |
| | | left: 0; |
| | | pointer-events: none; |
| | | border-bottom: 1px solid $tn-border-solid-color; |
| | | transform: scaleY(0.5) translateZ(0); |
| | | transform-origin: 0 100%; |
| | | } |
| | | |
| | | &--line-left { |
| | | &::after { |
| | | left: 30rpx !important; |
| | | } |
| | | } |
| | | |
| | | &--line-right { |
| | | &::after { |
| | | right: 30rpx !important; |
| | | } |
| | | } |
| | | |
| | | &--unlined { |
| | | &::after { |
| | | border-bottom: 0 !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-list-view-class tn-list-view" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | viewClass |
| | | ]" |
| | | :style="[viewStyle]" |
| | | > |
| | | <view |
| | | v-if="showTitle" |
| | | class="tn-list-view__title" |
| | | :class="[ |
| | | fontColorClass |
| | | ]" |
| | | :style="[titleStyle]" |
| | | @tap="handleClickTitle" |
| | | >{{ title }}</view> |
| | | |
| | | <view |
| | | v-else |
| | | :class="[{'tn-list-view__title--card': card}]" |
| | | @tap="handleClickTitle" |
| | | > |
| | | <slot name="title"></slot> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-list-view__content tn-border-solid-top tn-border-solid-bottom" |
| | | :class="[contentClass]" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [ componentsColorMixin ], |
| | | name: 'tn-list-view', |
| | | props: { |
| | | // æ é¢ |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å»æè¾¹æ¡ ä¸è¾¹æ¡ top, ä¸è¾¹æ¡ bottom, ææè¾¹æ¡ all |
| | | unlined: { |
| | | type: String, |
| | | default: 'all' |
| | | }, |
| | | // ä¸å¤è¾¹è· |
| | | marginTop: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å
容æ¯å¦æ¾ç¤ºä¸ºå¡çæ¨¡å¼ |
| | | card: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦èªå®ä¹æ é¢ |
| | | customTitle: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | showTitle() { |
| | | return !this.customTitle && this.title |
| | | }, |
| | | viewClass() { |
| | | let clazz = '' |
| | | |
| | | if (this.card) { |
| | | clazz += ' tn-list-view--card' |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | viewStyle() { |
| | | let style = {} |
| | | |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | |
| | | if (this.marginTop) { |
| | | style.marginTop = this.marginTop |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | titleStyle() { |
| | | let style = {} |
| | | |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | if (this.fontSize) { |
| | | style.fontSize = this.fontSize + this.fontUnit |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | contentClass() { |
| | | let clazz = '' |
| | | |
| | | if (this.card) { |
| | | clazz += ' tn-list-view__content--card' |
| | | } |
| | | |
| | | switch(this.unlined) { |
| | | case 'top': |
| | | clazz += ' tn-none-border-top' |
| | | break |
| | | case 'bottom': |
| | | clazz += ' tn-none-border-bottom' |
| | | break |
| | | case 'all': |
| | | clazz += ' tn-none-border' |
| | | break |
| | | } |
| | | |
| | | return clazz |
| | | } |
| | | }, |
| | | data () { |
| | | return { |
| | | kindShowFlag: this.showKind |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çæ é¢ç¹å»äºä»¶ |
| | | handleClickTitle() { |
| | | if (!this.kindList) return |
| | | this.kindShowFlag = !this.kindShowFlag |
| | | this.$emit("clickTitle", {}) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-list-view { |
| | | background-color: #FFFFFF; |
| | | |
| | | &__title { |
| | | width: 100%; |
| | | padding: 30rpx; |
| | | font-size: 30rpx; |
| | | line-height: 30rpx; |
| | | box-sizing: border-box; |
| | | |
| | | &--card { |
| | | // margin: 0rpx 30rpx; |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | width: 100%; |
| | | position: relative; |
| | | border-radius: 0; |
| | | |
| | | &--card { |
| | | // width: auto; |
| | | // overflow: hidden; |
| | | // margin-right: 30rpx; |
| | | // margin-left: 30rpx; |
| | | // border-radius: 20rpx |
| | | } |
| | | } |
| | | |
| | | &--card { |
| | | // padding-bottom: 30rpx; |
| | | border-radius: 20rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-load-more-class tn-load-more"> |
| | | <view |
| | | class="tn-load-more__wrap" |
| | | :class="[backgroundColorClass]" |
| | | :style="[loadStyle]" |
| | | > |
| | | <view class="tn-load-more__line"></view> |
| | | <view |
| | | class="tn-load-more__content" |
| | | :class="[{'tn-load-more__content--more': (status === 'loadmore' || status === 'nomore')}]" |
| | | > |
| | | <view class="tn-load-more__loading"> |
| | | <tn-loading |
| | | class="tn-load-more__loading__icon" |
| | | :mode="loadingIconType" |
| | | :show="status === 'loading' && loadingIcon" |
| | | :color="loadingIconColor" |
| | | ></tn-loading> |
| | | </view> |
| | | <view |
| | | class="tn-load-more__text" |
| | | :class="[fontColorClass, {'tn-load-more__text--dot': (status === 'nomore' && dot)}]" |
| | | :style="[loadTextStyle]" |
| | | >{{ showText }}</view> |
| | | </view> |
| | | <view class="tn-load-more__line"></view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-load-more', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // å è½½ç¶æ |
| | | // loadmore -> å è½½æ´å¤ |
| | | // loading -> å è½½ä¸ |
| | | // nomore -> æ²¡ææ´å¤ |
| | | status: { |
| | | type: String, |
| | | default: 'loadmore' |
| | | }, |
| | | // æ¾ç¤ºå è½½å¾æ |
| | | loadingIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å è½½å¾æ æ ·å¼ï¼åètn-loadingç»ä»¶çå 载类å |
| | | loadingIconType: { |
| | | type: String, |
| | | default: 'circle' |
| | | }, |
| | | // å¨ååå è½½ç¶æä¸ï¼ååçé¢è² |
| | | loadingIconColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¾ç¤ºçæå |
| | | loadText: { |
| | | type: Object, |
| | | default() { |
| | | return { |
| | | loadmore: 'å è½½æ´å¤', |
| | | loading: 'æ£å¨å è½½...', |
| | | nomore: 'æ²¡ææ´å¤äº' |
| | | } |
| | | } |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºç²ç¹ï¼å¨nomoreç¶æä¸çæ |
| | | dot: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // èªå®ä¹ç»ä»¶æ ·å¼ |
| | | customStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | loadStyle() { |
| | | let style = {} |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | // åå¹¶ç¨æ·èªå®ä¹æ ·å¼ |
| | | if (Object.keys(this.customStyle).length > 0) { |
| | | Object.assign(style, this.customStyle) |
| | | } |
| | | return style |
| | | }, |
| | | loadTextStyle() { |
| | | let style = {} |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | if (this.fontSizeStyle) { |
| | | style.fontSize = this.fontSizeStyle |
| | | style.lineHeight = this.$t.string.getLengthUnitValue(this.fontSize + 2, this.fontUnit) |
| | | } |
| | | return style |
| | | }, |
| | | // æ¾ç¤ºçæç¤ºæå |
| | | showText() { |
| | | let text = '' |
| | | if (this.status === 'loadmore') text = this.loadText.loadmore || 'å è½½æ´å¤' |
| | | else if (this.status === 'loading') text = this.loadText.loading || 'æ£å¨å è½½...' |
| | | else if (this.status === 'nomore' && this.dot) text = this.dotText |
| | | else text = this.loadText.nomore || 'æ²¡ææ´å¤äº' |
| | | |
| | | return text |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ç²ç¹ |
| | | dotText: 'â' |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çå è½½æ´å¤äºä»¶ |
| | | loadMore() { |
| | | // åªæå¨ loadmore ç¶æä¸ç¹å»æä¼åéç¹å»äºä»¶ï¼å
容䏿»¡ä¸å±æ¶æ æ³è§¦ååºé¨ä¸æäºä»¶ï¼æä»¥éè¦ç¹å»æ¥è§¦å |
| | | if (this.status === 'loadmore') this.$emit('loadmore') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-load-more { |
| | | |
| | | &__wrap { |
| | | background-color: transparent; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | color: $tn-content-color; |
| | | } |
| | | |
| | | &__line { |
| | | vertical-align: middle; |
| | | border: 1px solid $tn-content-color; |
| | | width: 50rpx; |
| | | transform: scaleY(0.5); |
| | | } |
| | | |
| | | &__content { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 0 12rpx; |
| | | |
| | | &--more { |
| | | position: relative; |
| | | } |
| | | } |
| | | |
| | | &__loading { |
| | | margin-right: 8rpx; |
| | | |
| | | &__icon { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | &__text { |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | line-height: 30rpx; |
| | | |
| | | &--dot { |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | v-if="show" |
| | | class="tn-loading-class tn-loading" |
| | | :class="[ |
| | | `tn-loading-${mode}`, |
| | | animation ? `tn-loading-${mode}--animation` : '' |
| | | ]" |
| | | :style="[loadStyle]" |
| | | ></view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-loading', |
| | | props: { |
| | | // å¨ç»ç±»å |
| | | // circle åå flower è±æµå½¢ç¶ |
| | | mode: { |
| | | type: String, |
| | | default: 'circle' |
| | | }, |
| | | // æ¯å¦æ¾ç¤º |
| | | show: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå è½½å¨ç» |
| | | animation: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ååé¢è² |
| | | color: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 徿 å¤§å° |
| | | size: { |
| | | type: Number, |
| | | default: 34 |
| | | } |
| | | }, |
| | | computed: { |
| | | // å è½½å¨ç»ååçæ ·å¼ |
| | | loadStyle() { |
| | | let style = {} |
| | | style.width = this.size + 'rpx' |
| | | style.height = style.width |
| | | if (this.mode === 'circle') style.borderColor = `#E6E6E6 #E6E6E6 #E6E6E6 ${this.color ? this.color : '#AAAAAA'}` |
| | | |
| | | return style |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-loading-circle { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | vertical-align: middle; |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | background: 0 0; |
| | | border-radius: 50%; |
| | | border: 2px solid; |
| | | border-color: #E6E6E6 #E6E6E6 #E6E6E6 #AAAAAA; |
| | | |
| | | &--animation { |
| | | animation: tn-circle 1s linear infinite; |
| | | -webkit-animation: tn-circle 1s linear infinite; |
| | | } |
| | | } |
| | | |
| | | .tn-loading-flower { |
| | | display: inline-block; |
| | | vertical-align: middle; |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;; |
| | | background-size: 100%; |
| | | |
| | | &--animation { |
| | | animation: tn-flower 1s steps(12) infinite; |
| | | -webkit-animation: tn-flower 1s steps(12) infinite; |
| | | } |
| | | } |
| | | |
| | | @keyframes tn-flower { |
| | | 0% { |
| | | transform: rotate(0deg); |
| | | -webkit-transform: rotate(0deg); |
| | | } |
| | | |
| | | to { |
| | | transform: rotate(360deg); |
| | | -webkit-transform: rotate(360deg); |
| | | } |
| | | } |
| | | |
| | | @keyframes tn-circle { |
| | | 0% { |
| | | transform: rotate(0); |
| | | -webkit-transform: rotate(0); |
| | | } |
| | | |
| | | 100% { |
| | | transform: rotate(360deg); |
| | | -webkit-transform: rotate(360deg); |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="value" class="tn-modal-class tn-modal"> |
| | | <tn-popup |
| | | v-model="value" |
| | | mode="center" |
| | | :popup="false" |
| | | :borderRadius="radius" |
| | | :width="width" |
| | | :zoom="zoom" |
| | | :safeAreaInsetBottom="safeAreaInsetBottom" |
| | | :maskCloseable="maskCloseable" |
| | | :zIndex="zIndex" |
| | | :closeBtn="showCloseBtn" |
| | | @close="close" |
| | | > |
| | | <!-- å
容 --> |
| | | <view |
| | | class="tn-modal__box" |
| | | :class="[ |
| | | backgroundColorClass |
| | | ]" |
| | | :style="[boxStyle]" |
| | | > |
| | | <!-- 䏿¯èªå®ä¹å¼¹æ¡å
容 --> |
| | | <view v-if="!custom"> |
| | | <view class="tn-modal__box__title" v-if="title && title !== ''">{{ title }}</view> |
| | | <view |
| | | class="tn-modal__box__content" |
| | | :class="[ |
| | | fontColorClass, |
| | | contentClass |
| | | ]" |
| | | :style="contentStyle" |
| | | >{{ content }}</view> |
| | | <view v-if="button && button.length" class="tn-modal__box__btn-box" :class="[button.length != 2 ? 'tn-flex-direction-column' : '']"> |
| | | <block v-for="(item, index) in button" :key="index"> |
| | | <tn-button |
| | | width="100%" |
| | | height="68rpx" |
| | | :fontSize="26" |
| | | :backgroundColor="item.backgroundColor || ''" |
| | | :fontColor="item.fontColor || ''" |
| | | :plain="item.plain || false" |
| | | :shape="item.shape || 'round'" |
| | | :class="[ |
| | | button.length > 2 ? 'tn-margin-bottom' : '' |
| | | ]" |
| | | @click="handleClick(index)" |
| | | :style="{ |
| | | width: button.length != 2 ? '80%' : '46%' |
| | | }" |
| | | > |
| | | {{ item.text }} |
| | | </tn-button> |
| | | </block> |
| | | </view> |
| | | </view> |
| | | <view v-else> |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </tn-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [componentsColorMixin], |
| | | name: 'tn-modal', |
| | | props: { |
| | | // æ¾ç¤ºæ§å¶ |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¼¹æ¡å®½åº¦ |
| | | width: { |
| | | type: String, |
| | | default: '84%' |
| | | }, |
| | | // å
è¾¹è· |
| | | padding: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // åè§ |
| | | radius: { |
| | | type: Number, |
| | | default: 12 |
| | | }, |
| | | // æ é¢ |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å
容 |
| | | content: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æé®å
容 è®¾ç½®åæ°ä¸buttonç»ä»¶çåæ°ä¸è´ |
| | | // { |
| | | // text: 'ç¡®å®', |
| | | // backgroundColor: 'red', |
| | | // fontColor: 'white', |
| | | // plain: true, |
| | | // shape: '' |
| | | // } |
| | | button: { |
| | | type: Array, |
| | | default: () => { |
| | | return [] |
| | | } |
| | | }, |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¹å»é®ç½©æ¯å¦å¯ä»¥å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå³ä¸è§å
³éæé® |
| | | showCloseBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¾å¤§å¨ç» |
| | | zoom: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // èªå®ä¹å¼¹æ¡å
容 |
| | | custom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¼¹æ¡çz-index |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | boxStyle() { |
| | | let style = {} |
| | | |
| | | if (this.padding) { |
| | | style.padding = this.padding |
| | | } |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | contentClass() { |
| | | let clazz = '' |
| | | if (this.title) { |
| | | clazz += ' tn-margin-top' |
| | | } else { |
| | | clazz += ' tn-modal__box__content--no-title' |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | contentStyle() { |
| | | let style = {} |
| | | |
| | | if (this.fontSize) { |
| | | style.fontSize = this.fontSize + this.fontUnit |
| | | } |
| | | if (this.fontColorStyle) { |
| | | style.color = this.fontColorStyle |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // å¤çæé®ç¹å»äºä»¶ |
| | | handleClick(index) { |
| | | if (!this.value) return |
| | | this.$emit("click", { |
| | | index: Number(index) |
| | | }) |
| | | }, |
| | | // å¤çå
³éäºä»¶ |
| | | close() { |
| | | this.$emit("cancel") |
| | | this.$emit('input', false) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-modal { |
| | | |
| | | &__box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background-color: #FFFFFF; |
| | | padding: 40rpx 64rpx; |
| | | |
| | | &__title { |
| | | text-align: center; |
| | | font-size: 34rpx; |
| | | color: #333; |
| | | padding-top: 20rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &__content { |
| | | text-align: center; |
| | | padding-bottom: 30rpx; |
| | | color: $tn-font-color; |
| | | font-size: 28rpx; |
| | | |
| | | &--no-title { |
| | | padding-bottom: 0rpx !important; |
| | | } |
| | | } |
| | | |
| | | &__btn-box { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | &__content ~ &__btn-box { |
| | | margin-top: 30rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="tn-custom-nav-bar-class tn-custom-nav-bar" |
| | | :style="[navBarStyle]" |
| | | > |
| | | <view |
| | | class="tn-custom-nav-bar__bar" |
| | | :class="[barClass]" |
| | | :style="[barStyle]" |
| | | > |
| | | <view v-if="isBack"> |
| | | <view v-if="customBack"> |
| | | <view |
| | | :style="{ |
| | | width: customBackStyleInfo.width + 'px', |
| | | height: customBackStyleInfo.height + 'px', |
| | | marginLeft: customBackStyleInfo.left + 'px' |
| | | }" |
| | | > |
| | | <slot name="back"></slot> |
| | | </view> |
| | | </view> |
| | | <view v-else class="tn-custom-nav-bar__bar__action" @tap="handlerBack"> |
| | | <text class="tn-custom-nav-bar__bar__action--nav-back" :class="[`tn-icon-${backIcon}`]"></text> |
| | | <text class="tn-custom-nav-bar__bar__action--nav-back-text" v-if="backTitle">{{ backTitle }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="tn-custom-nav-bar__bar__content" :style="[contentStyle]"> |
| | | <slot></slot> |
| | | </view> |
| | | <view> |
| | | <slot name="right"></slot> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-nav-bar', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // å±çº§ |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å¯¼èªæ çé«åº¦ |
| | | height: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // é«åº¦åä½ |
| | | unit: { |
| | | type: String, |
| | | default: 'px' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºè¿åæé® |
| | | isBack: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // è¿åæé®ç徿 |
| | | backIcon: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // è¿åæé®ææ¾ç¤ºçæå |
| | | backTitle: { |
| | | type: String, |
| | | default: 'è¿å' |
| | | }, |
| | | // éæç¶ææ |
| | | alpha: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦åºå®å¨é¡¶é¨ |
| | | fixed: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºåºé¨é´å½± |
| | | bottomShadow: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦èªå®ä¹è¿åæé® |
| | | customBack: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è¿åååè° |
| | | beforeBack: { |
| | | type: Function, |
| | | default: null |
| | | } |
| | | }, |
| | | computed: { |
| | | navBarStyle() { |
| | | let style = {} |
| | | style.height = this.height === 0 ? this.customBarHeight + this.unit : this.height + this.unit |
| | | if (this.fixed) { |
| | | style.position = 'fixed' |
| | | } |
| | | style.zIndex = this.elZIndex |
| | | |
| | | return style |
| | | }, |
| | | barClass() { |
| | | let clazz = '' |
| | | if (this.backgroundColorClass) { |
| | | clazz += ` ${this.backgroundColorClass}` |
| | | } |
| | | if (this.fontColorClass) { |
| | | clazz += `${this.fontColorClass}` |
| | | } |
| | | if (this.fixed) { |
| | | clazz += ' tn-custom-nav-bar__bar--fixed' |
| | | } |
| | | if (this.alpha) { |
| | | clazz += ' tn-custom-nav-bar__bar--alpha' |
| | | } |
| | | if (this.bottomShadow) { |
| | | clazz += ' tn-custom-nav-bar__bar--bottom-shadow' |
| | | } |
| | | |
| | | return clazz |
| | | }, |
| | | barStyle() { |
| | | let style = {} |
| | | style.height = this.height === 0 ? this.customBarHeight + this.unit : this.height + this.unit |
| | | |
| | | if (this.fixed) { |
| | | style.paddingTop = this.statusBarHeight + 'px' |
| | | } |
| | | |
| | | if(!this.backgroundColorClass) { |
| | | style.backgroundColor = this.backgroundColor !== '' ? this.backgroundColor : '#FFFFFF' |
| | | } |
| | | if (!this.fontColorClass && this.fontColor) { |
| | | style.color= this.fontColor |
| | | } |
| | | |
| | | style.zIndex = this.elZIndex |
| | | |
| | | return style |
| | | }, |
| | | contentStyle() { |
| | | let style = {} |
| | | style.top = this.fixed ? this.statusBarHeight + 'px' : '0px' |
| | | style.height = this.height === 0 ? (this.customBarHeight - this.statusBarHeight) + this.unit : this.height + this.unit |
| | | style.lineHeight = style.height |
| | | |
| | | if (this.isBack) { |
| | | if (this.customBack) { |
| | | const width = (this.customBackStyleInfo.width + this.customBackStyleInfo.left) * 2 |
| | | style.width = `calc(100% - ${width}px)` |
| | | } else { |
| | | style.width = 'calc(100% - 340rpx)' |
| | | } |
| | | } else { |
| | | style.width = '100%' |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | elZIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.navbar |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ç¶ææ çé«åº¦ |
| | | statusBarHeight: 0, |
| | | // èªå®ä¹å¯¼èªæ çé«åº¦ |
| | | customBarHeight: 0, |
| | | // èªå®ä¹è¿åæé®æ¶ï¼è¿å容å¨ç宽é«è¾¹è·ä¿¡æ¯ |
| | | customBackStyleInfo: { |
| | | width: 86, |
| | | height: 32, |
| | | left: 15 |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | // è·åvuexä¸çèªå®ä¹é¡¶æ çé«åº¦ |
| | | this.updateNavBarInfo() |
| | | }, |
| | | created() { |
| | | // è·åè¶åä¿¡æ¯ |
| | | // #ifdef MP-WEIXIN |
| | | let custom = wx.getMenuButtonBoundingClientRect() |
| | | this.customBackStyleInfo.width = custom.width |
| | | this.customBackStyleInfo.height = custom.height |
| | | this.customBackStyleInfo.left = uni.upx2px(750) - custom.right |
| | | // #endif |
| | | }, |
| | | methods: { |
| | | // æ´æ°å¯¼èªæ çé«åº¦ |
| | | async updateNavBarInfo() { |
| | | // è·åvuexä¸çèªå®ä¹é¡¶æ çé«åº¦ |
| | | let customBarHeight = this.vuex_custom_bar_height |
| | | let statusBarHeight = this.vuex_status_bar_height |
| | | // 妿è·å失败åéæ°è·å |
| | | if (!customBarHeight) { |
| | | try { |
| | | const navBarInfo = await this.$t.updateCustomBar() |
| | | customBarHeight = navBarInfo.customBarHeight |
| | | statusBarHeight = navBarInfo.statusBarHeight |
| | | } catch(e) { |
| | | setTimeout(() => { |
| | | this.updateNavBarInfo() |
| | | }, 10) |
| | | return |
| | | } |
| | | } |
| | | |
| | | // æ´æ°vuexä¸çå¯¼èªæ ä¿¡æ¯ |
| | | this && this.$t.vuex('vuex_status_bar_height', statusBarHeight) |
| | | this && this.$t.vuex('vuex_custom_bar_height', customBarHeight) |
| | | |
| | | this.customBarHeight = customBarHeight |
| | | this.statusBarHeight = statusBarHeight |
| | | }, |
| | | // å¤çè¿åäºä»¶ |
| | | async handlerBack() { |
| | | if (this.beforeBack && typeof(this.beforeBack) === 'function') { |
| | | // æ§è¡åè°ï¼åæ¶ä¼ å
¥ç´¢å¼å½ä½åæ° |
| | | // å¨å¾®ä¿¡ï¼æ¯ä»å®çç¯å¢(H5æ£å¸¸)ï¼ä¼å¯¼è´ç¶ç»ä»¶å®ä¹ç彿°ä½ä¸çthisåæåç»ä»¶çthis |
| | | // éè¿bind()æ¹æ³ï¼ç»å®ç¶ç»ä»¶çthisï¼è®©thisçthis为ç¶ç»ä»¶çä¸ä¸æ |
| | | let beforeBack = this.beforeBack.bind(this.$t.$parent.call(this))() |
| | | // 夿æ¯å¦è¿åäºPromise |
| | | if (!!beforeBack && typeof beforeBack.then === 'function') { |
| | | await beforeBack.then(res => { |
| | | // Promiseè¿åæå |
| | | this.navBack() |
| | | }).catch(err => {}) |
| | | } else if (beforeBack === true) { |
| | | this.navBack() |
| | | } |
| | | } else { |
| | | this.navBack() |
| | | } |
| | | }, |
| | | // è¿åä¸ä¸é¡µ |
| | | navBack() { |
| | | |
| | | // éè¿å¤æå½å页é¢ç页颿 ä¿¡æ¯ï¼æ¯å¦æä¸ä¸é¡µè¿è¡è¿åï¼å¦ææ²¡æå跳转å°é¦é¡µ |
| | | const pages = getCurrentPages() |
| | | if (pages && pages.length > 0) { |
| | | const firstPage = pages[0] |
| | | if (pages.length == 1 && (!firstPage.route || firstPage.route != 'pages/index/index')) { |
| | | uni.reLaunch({ |
| | | url: '/pages/index/index' |
| | | }) |
| | | } else { |
| | | uni.navigateBack({ |
| | | delta: 1 |
| | | }) |
| | | } |
| | | } else { |
| | | uni.reLaunch({ |
| | | url: '/pages/index/index' |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-custom-nav-bar { |
| | | display: block; |
| | | position: relative; |
| | | |
| | | &__bar { |
| | | display: flex; |
| | | position: relative; |
| | | align-items: center; |
| | | min-height: 100rpx; |
| | | justify-content: space-between; |
| | | min-height: 0px; |
| | | /* #ifdef MP-WEIXIN */ |
| | | padding-right: 220rpx; |
| | | /* #endif */ |
| | | /* #ifdef MP-ALIPAY */ |
| | | padding-right: 150rpx; |
| | | /* #endif */ |
| | | box-shadow: 0rpx 0rpx 0rpx; |
| | | z-index: 9999; |
| | | |
| | | &--fixed { |
| | | position: fixed; |
| | | width: 100%; |
| | | top: 0; |
| | | } |
| | | |
| | | &--alpha { |
| | | background: transparent !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | &--bottom-shadow { |
| | | box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | &__action { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 100%; |
| | | justify-content: center; |
| | | max-width: 100%; |
| | | |
| | | &--nav-back { |
| | | /* position: absolute; */ |
| | | /* top: 50%; */ |
| | | /* left: 20rpx; */ |
| | | /* margin-top: -15rpx; */ |
| | | // width: 25rpx; |
| | | // height: 25rpx; |
| | | padding: 20rpx; |
| | | font-size: 38rpx; |
| | | line-height: 100%; |
| | | // border-width: 0 0 4rpx 4rpx; |
| | | // border-color: #000000; |
| | | // border-style: solid; |
| | | // transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); |
| | | } |
| | | |
| | | &--nav-back-text { |
| | | padding: 20rpx 20rpx 20rpx 0rpx; |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | position: absolute; |
| | | text-align: center; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | margin: auto; |
| | | font-size: 32rpx; |
| | | cursor: none; |
| | | // pointer-events: none; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | v-if="showNotice" |
| | | class="tn-notice-bar-class tn-notice-bar" |
| | | :style="{ |
| | | borderRadius: radius + 'rpx' |
| | | }" |
| | | > |
| | | <block v-if="mode === 'horizontal' && circular"> |
| | | <tn-row-notice |
| | | :backgroundColor="backgroundColor" |
| | | :fontColor="fontColor" |
| | | :fontSize="fontSize" |
| | | :fontUnit="fontUnit" |
| | | :list="list" |
| | | :show="show" |
| | | :playStatus="playStatus" |
| | | :leftIcon="leftIcon" |
| | | :leftIconName="leftIconName" |
| | | :leftIconSize="leftIconSize" |
| | | :rightIcon="rightIcon" |
| | | :rightIconName="rightIconName" |
| | | :rightIconSize="rightIconSize" |
| | | :closeBtn="closeBtn" |
| | | :autoplay="autoplay" |
| | | :radius="radius" |
| | | :padding="padding" |
| | | :speed="speed" |
| | | @click="click" |
| | | @close="close" |
| | | @clickLeft="clickLeftIcon" |
| | | @clickRight="clickRightIcon" |
| | | ></tn-row-notice> |
| | | </block> |
| | | <block v-if="mode === 'vertical' || (mode === 'horizontal' && !circular)"> |
| | | <tn-column-notice |
| | | :backgroundColor="backgroundColor" |
| | | :fontColor="fontColor" |
| | | :fontSize="fontSize" |
| | | :fontUnit="fontUnit" |
| | | :list="list" |
| | | :show="show" |
| | | :mode="mode" |
| | | :playStatus="playStatus" |
| | | :leftIcon="leftIcon" |
| | | :leftIconName="leftIconName" |
| | | :leftIconSize="leftIconSize" |
| | | :rightIcon="rightIcon" |
| | | :rightIconName="rightIconName" |
| | | :rightIconSize="rightIconSize" |
| | | :closeBtn="closeBtn" |
| | | :autoplay="autoplay" |
| | | :radius="radius" |
| | | :padding="padding" |
| | | :duration="duration" |
| | | @click="click" |
| | | @close="close" |
| | | @clickLeft="clickLeftIcon" |
| | | @clickRight="clickRightIcon" |
| | | @end="end" |
| | | ></tn-column-notice> |
| | | </block> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | name: 'tn-notice-bar', |
| | | mixins: [componentsColorMixin], |
| | | props: { |
| | | // æ¾ç¤ºçå
容 |
| | | list: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // æ¯å¦æ¾ç¤º |
| | | show: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ææ¾ç¶æ |
| | | // play -> ææ¾ paused -> æå |
| | | playStatus: { |
| | | type: String, |
| | | default: 'play' |
| | | }, |
| | | // æ»å¨æ¹å |
| | | // horizontal -> æ°´å¹³æ»å¨ vertical -> åç´æ»å¨ |
| | | mode: { |
| | | type: String, |
| | | default: 'horizontal' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå·¦è¾¹å¾æ |
| | | leftIcon: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å·¦è¾¹å¾æ çåç§° |
| | | leftIconName: { |
| | | type: String, |
| | | default: 'sound' |
| | | }, |
| | | // å·¦è¾¹å¾æ çå¤§å° |
| | | leftIconSize: { |
| | | type: Number, |
| | | default: 34 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå³è¾¹ç徿 |
| | | rightIcon: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å³è¾¹å¾æ çåç§° |
| | | rightIconName: { |
| | | type: String, |
| | | default: 'right' |
| | | }, |
| | | // å³è¾¹å¾æ çå¤§å° |
| | | rightIconSize: { |
| | | type: Number, |
| | | default: 26 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå
³éæé® |
| | | closeBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // åè§ |
| | | radius: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // å
è¾¹è· |
| | | padding: { |
| | | type: String, |
| | | default: '18rpx 24rpx' |
| | | }, |
| | | // èªå¨ææ¾ |
| | | autoplay: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ»å¨å¨æ |
| | | duration: { |
| | | type: Number, |
| | | default: 2000 |
| | | }, |
| | | // æ°´å¹³æ»å¨æ¶çé度ï¼å³æ¯ç§æ»å¨å¤å°rpx |
| | | speed: { |
| | | type: Number, |
| | | default: 160 |
| | | }, |
| | | // æ°´å¹³æ»å¨çæ¶åæ¯å¦éç¨è¡æ¥çæ¨¡å¼ |
| | | circular: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ²¡ææ°æ®æ¶æ¯å¦æ¾ç¤ºéç¥ |
| | | autoHidden: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | computed: { |
| | | // å½è®¾ç½®äºshow为falseï¼æè
autoHidden为trueä¸list为空æ¶ï¼ä¸æ¾ç¤ºéç¥ |
| | | showNotice() { |
| | | if (this.show === false || (this.autoHidden && this.list.length === 0)) return false |
| | | else return true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | // ç¹å»äºéç¥æ |
| | | click(index) { |
| | | this.$emit('click', index) |
| | | }, |
| | | // ç¹å»äºå
³éæé® |
| | | close() { |
| | | this.$emit('close') |
| | | }, |
| | | // ç¹å»äºå·¦è¾¹å¾æ |
| | | clickLeftIcon() { |
| | | this.$emit('clickLeft') |
| | | }, |
| | | // ç¹å»äºå³è¾¹å¾æ |
| | | clickRightIcon() { |
| | | this.$emit('clickRight') |
| | | }, |
| | | // ä¸ä¸ªå¨ææ»å¨ç»æ |
| | | end() { |
| | | this.$emit('end') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-notice-bar { |
| | | overflow: hidden; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-number-box-class tn-number-box"> |
| | | <!-- å --> |
| | | <view |
| | | class="tn-number-box__btn__minus" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | fontColorClass, |
| | | {'tn-number-box__btn--disabled': disabled || inputValue <= min} |
| | | ]" |
| | | :style="{ |
| | | backgroundColor: backgroundColorStyle, |
| | | height: $t.string.getLengthUnitValue(inputHeight), |
| | | color: fontColorStyle, |
| | | fontSize: fontSizeStyle |
| | | }" |
| | | @touchstart.stop.prevent="touchStart('minus')" |
| | | @touchend.stop.prevent="clearTimer" |
| | | > |
| | | <view class="tn-icon-reduce"></view> |
| | | </view> |
| | | |
| | | <!-- è¾å
¥æ¡ --> |
| | | <input |
| | | v-model="inputValue" |
| | | :disabled="disabledInput || disabled" |
| | | :cursor-spacing="getCursorSpacing" |
| | | class="tn-number-box__input" |
| | | :class="[ |
| | | fontColorClass, |
| | | {'tn-number-box__input--disabled': disabledInput || disabled} |
| | | ]" |
| | | :style="{ |
| | | width: $t.string.getLengthUnitValue(inputWidth), |
| | | height: $t.string.getLengthUnitValue(inputHeight), |
| | | color: fontColorStyle, |
| | | fontSize: fontSizeStyle, |
| | | backgroundColor: backgroundColorStyle |
| | | }" |
| | | @blur="blurInput" |
| | | @focus="focusInput" |
| | | /> |
| | | |
| | | <!-- å --> |
| | | <view |
| | | class="tn-number-box__btn__plus" |
| | | :class="[ |
| | | backgroundColorClass, |
| | | fontColorClass, |
| | | {'tn-number-box__btn--disabled': disabled || inputValue >= max} |
| | | ]" |
| | | :style="{ |
| | | backgroundColor: backgroundColorStyle, |
| | | height: $t.string.getLengthUnitValue(inputHeight), |
| | | color: fontColorStyle, |
| | | fontSize: fontSizeStyle |
| | | }" |
| | | @touchstart.stop.prevent="touchStart('plus')" |
| | | @touchend.stop.prevent="clearTimer" |
| | | > |
| | | <view class="tn-icon-add"></view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColor from '../../libs/mixin/components_color.js' |
| | | |
| | | export default { |
| | | mixins: [componentsColor], |
| | | name: 'tn-number-box', |
| | | props: { |
| | | value: { |
| | | type: Number, |
| | | default: 1 |
| | | }, |
| | | // ç´¢å¼ |
| | | index: { |
| | | type: [Number, String], |
| | | default: '' |
| | | }, |
| | | // æå°å¼ |
| | | min: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æå¤§å¼ |
| | | max: { |
| | | type: Number, |
| | | default: 99999 |
| | | }, |
| | | // æ¥è¿å¼ |
| | | step: { |
| | | type: Number, |
| | | default: 1 |
| | | }, |
| | | // ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦ç¦ç¨è¾å
¥ |
| | | disabledInput: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è¾å
¥æ¡ç宽度 |
| | | inputWidth: { |
| | | type: Number, |
| | | default: 88 |
| | | }, |
| | | // è¾å
¥æ¡çé«åº¦ |
| | | inputHeight: { |
| | | type: Number, |
| | | default: 50 |
| | | }, |
| | | // è¾å
¥æ¡åé®çä¹é´çè·ç¦» |
| | | cursorSpacing: { |
| | | type: Number, |
| | | default: 100 |
| | | }, |
| | | // æ¯å¦å¼å¯é¿æè¿è¡è¿ç»éå¢å |
| | | longPress: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é¿æè§¦åé´é |
| | | longPressTime: { |
| | | type: Number, |
| | | default: 250 |
| | | }, |
| | | // æ¯å¦åªè½è¾å
¥æ£æ´æ° |
| | | positiveInteger: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | computed: { |
| | | getCursorSpacing() { |
| | | return Number(uni.upx2px(this.cursorSpacing)) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // è¾å
¥æ¡çå¼ |
| | | inputValue: 1, |
| | | // é¿æå®æ¶å¨ |
| | | longPressTimer: null, |
| | | // æ è®°å¼çæ¹åæ¯æ¥èªå¤é¨è¿æ¯å
é¨ |
| | | changeFromInner: false, |
| | | // å
é¨å®æ¶å¨ |
| | | innerChangeTimer: null |
| | | } |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | // åªævalueçæ¹åæ¯æ¥èªå¤é¨çæ¶åï¼æå»åæ¥inputValueçå¼ï¼å¦åä¼é æå¾ªç¯é误 |
| | | if (!this.changeFromInner) { |
| | | this.updateInputValue() |
| | | // å 为inputValueåååï¼ä¼è§¦åthis.handleChange()ï¼å¨å
¶ä¸changeFromInnerä¼å次被设置为trueï¼ |
| | | // é æå¤é¢ä¿®æ¹å¼ï¼ä¹å¯¼è´è¢«è®¤ä¸ºæ¯å
é¨ä¿®æ¹çæ··ä¹±ï¼è¿éè¿è¡this.$nextTickå»¶æ¶ï¼ä¿è¯å¨è¿è¡å¨æçæåå¤ |
| | | // å°changeFromInner设置为false |
| | | this.$nextTick(() => { |
| | | this.changeFromInner = false |
| | | }) |
| | | } |
| | | }, |
| | | inputValue(newVal, oldVal) { |
| | | // 为äºè®©ç¨æ·è½å¤å 餿æè¾å
¥å¼ï¼éæ°è¾å
¥å
容ï¼å 餿æå¼åï¼å
容为空å符串 |
| | | if (newVal === '') return |
| | | let value = 0 |
| | | // é¦å
夿æ¯å¦æ°å¼ï¼å¹¶ä¸å¨minåmaxä¹é´ï¼å¦æä¸æ¯ï¼ä½¿ç¨åæ¥å¼ |
| | | let isNumber = this.$t.test.number(newVal) |
| | | if (isNumber && newVal >= this.min && newVal <= this.max) value = newVal |
| | | else value = oldVal |
| | | |
| | | // 夿æ¯å¦åªè½è¾å
¥å¤§äºçäº0çæ´æ° |
| | | if (this.positiveInteger) { |
| | | // å°äº0æè
带æå°æ°ç¹ |
| | | if (newVal < 0 || String(newVal).indexOf('.') !== -1) { |
| | | value = Math.floor(newVal) |
| | | // ååç»å®inputçå¼ï¼å¿
é¡»è¦ä½¿ç¨$nextTickä¿®æ¹æ¾ç¤ºçå¼ |
| | | this.$nextTick(() => { |
| | | this.inputValue = value |
| | | }) |
| | | } |
| | | } |
| | | this.handleChange(value, 'change') |
| | | }, |
| | | min() { |
| | | this.updateInputValue() |
| | | }, |
| | | max() { |
| | | this.updateInputValue() |
| | | } |
| | | }, |
| | | created() { |
| | | this.updateInputValue() |
| | | }, |
| | | methods: { |
| | | // å¼å§ç¹å»æé® |
| | | touchStart(func) { |
| | | // å
æ§è¡ä¸éæ¹æ³ï¼å¦åä¼é ææ¾å¼ææ¶ï¼å°±æ§è¡äºclearTimerï¼å¯¼è´æ æ³å®ç°åè½ |
| | | this[func]() |
| | | // å¦ææ²¡æå¼å¯é¿æåè½ï¼ç´æ¥è¿å |
| | | if (!this.longPress) return |
| | | // æ¸
ç©ºé¿æå®æ¶å¨ï¼é²æ¢é夿³¨å |
| | | if (this.longPressTimer) { |
| | | clearInterval(this.longPressTimer) |
| | | this.longPressTimer = null |
| | | } |
| | | this.longPressTimer = setInterval(() => { |
| | | // æ§è¡å åæä½ |
| | | this[func]() |
| | | }, this.longPressTime) |
| | | }, |
| | | // æ¸
é¤å®æ¶å¨ |
| | | clearTimer() { |
| | | this.$nextTick(() => { |
| | | if (this.longPressTimer) { |
| | | clearInterval(this.longPressTimer) |
| | | this.longPressTimer = null |
| | | } |
| | | }) |
| | | }, |
| | | // å |
| | | minus() { |
| | | this.computeValue('minus') |
| | | }, |
| | | // å |
| | | plus() { |
| | | this.computeValue('plus') |
| | | }, |
| | | // å¤çå°æ°ç¸å ååºç°æº¢åºé®é¢ |
| | | calcPlus(num1, num2) { |
| | | let baseNum = 0, baseNum1 = 0, baseNum2 = 0 |
| | | try { |
| | | baseNum1 = num1.toString().split('.')[1].length |
| | | } catch(e) { |
| | | baseNum1 = 0 |
| | | } |
| | | try { |
| | | baseNum2 = num2.toString().split('.')[1].length |
| | | } catch(e) { |
| | | baseNum2 = 0 |
| | | } |
| | | |
| | | baseNum = Math.pow(10, Math.max(baseNum1, baseNum2)) |
| | | // 精度 |
| | | let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2 |
| | | return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(precision) |
| | | }, |
| | | calcMinus(num1, num2) { |
| | | let baseNum = 0, baseNum1 = 0, baseNum2 = 0 |
| | | try { |
| | | baseNum1 = num1.toString().split('.')[1].length |
| | | } catch(e) { |
| | | baseNum1 = 0 |
| | | } |
| | | try { |
| | | baseNum2 = num2.toString().split('.')[1].length |
| | | } catch(e) { |
| | | baseNum2 = 0 |
| | | } |
| | | |
| | | baseNum = Math.pow(10, Math.max(baseNum1, baseNum2)) |
| | | // 精度 |
| | | let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2 |
| | | return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision) |
| | | }, |
| | | // å¤çæä½åçå¼ |
| | | computeValue(type) { |
| | | uni.hideKeyboard() |
| | | if (this.disabled) return |
| | | let value = 0 |
| | | |
| | | if (type === 'minus') { |
| | | // å |
| | | value = this.calcMinus(this.inputValue, this.step) |
| | | } else if (type === 'plus') { |
| | | // å |
| | | value = this.calcPlus(this.inputValue, this.step) |
| | | } |
| | | // 夿æ¯å¦æ¯æå°å¼å°åæä½æå¤§å¼ |
| | | if (value < this.min || value > this.max) return |
| | | |
| | | this.inputValue = value |
| | | this.handleChange(value, type) |
| | | }, |
| | | // å¤çç¨æ·æå¨è¾å
¥ |
| | | blurInput(event) { |
| | | let val = 0, |
| | | value = event.detail.value |
| | | // å¦æä¸ºé0-9æ°åç»æï¼æè
å
¶ç¬¬ä¸ä½æ°å¼ä¸º0ï¼ç´æ¥è®©å
¶çäºminå¼ |
| | | // è¿éä¸ç´æ¥å¤ææ¯å¦æ£æ´æ°ï¼æ¯å ä¸ºç¨æ·ä¼ éçprops minå¼å¯è½ä¸º0 |
| | | if (!/(^\d+$)/.test(value) || value[0] == 0) { |
| | | val = this.min |
| | | } else { |
| | | val = +value |
| | | } |
| | | |
| | | if (val > this.max) { |
| | | val = this.max |
| | | } else if (val < this.min) { |
| | | val = this.min |
| | | } |
| | | this.$nextTick(() => { |
| | | this.inputValue = val |
| | | }) |
| | | this.handleChange(val, 'blur') |
| | | }, |
| | | // è·åç¦ç¹ |
| | | focusInput() { |
| | | this.$emit('focus') |
| | | }, |
| | | // åå§åinputValue |
| | | updateInputValue() { |
| | | let value = this.value |
| | | if (value <= this.min) { |
| | | value = this.min |
| | | } else if (value >= this.max) { |
| | | value = this.max |
| | | } |
| | | |
| | | this.inputValue = Number(value) |
| | | }, |
| | | // å¤ç弿¹åç¶æ |
| | | handleChange(value, type) { |
| | | if (this.disabled) return |
| | | // æ¸
é¤å®æ¶å¨ï¼é²æ¢æ··ä¹± |
| | | if (this.innerChangeTimer) { |
| | | clearTimeout(this.innerChangeTimer) |
| | | this.innerChangeTimer = null |
| | | } |
| | | |
| | | // å
é¨ä¿®æ¹å¼ |
| | | this.changeFromInner = true |
| | | // ä¸å®æ¶é´å
ï¼æ¸
é¤changeFromInneræ è®°ï¼å¦åå
é¨å¼æ¹åå |
| | | // å¤é¨éè¿ç¨åºä¿®æ¹valueå¼ï¼å°ä¼æ æ |
| | | this.innerChangeTimer = setTimeout(() => { |
| | | this.changeFromInner = false |
| | | }, 150) |
| | | this.$emit('input', Number(value)) |
| | | this.$emit(type, { |
| | | value: Number(value), |
| | | index: this.index |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-number-box { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | |
| | | &__btn { |
| | | &__plus,&__minus { |
| | | width: 60rpx; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | background-color: $tn-font-holder-color; |
| | | } |
| | | |
| | | &__plus { |
| | | border-radius: 0 8rpx 8rpx 0; |
| | | } |
| | | |
| | | &__minus { |
| | | border-radius: 8rpx 0 0 8rpx; |
| | | } |
| | | |
| | | &--disabled { |
| | | color: $tn-font-sub-color !important; |
| | | background: $tn-font-holder-color !important; |
| | | } |
| | | } |
| | | |
| | | &__input { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: relative; |
| | | text-align: center; |
| | | box-sizing: border-box; |
| | | padding: 0 4rpx; |
| | | margin: 0 6rpx; |
| | | background-color: $tn-font-holder-color; |
| | | |
| | | &--disabled { |
| | | color: $tn-font-sub-color !important; |
| | | background: $tn-font-holder-color !important; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-number-keyboard-class tn-number-keyboard" @touchmove.stop.prevent="() => {}"> |
| | | <view class="tn-number-keyboard__grids"> |
| | | <view |
| | | v-for="(item, index) in dataList" |
| | | :key="index" |
| | | class="tn-number-keyboard__grids__item" |
| | | :class="{ |
| | | 'tn-bg-gray--light': showGaryBg(index), |
| | | 'tn-border-solid-top': index <= 2, |
| | | 'tn-border-solid-bottom': index < 9, |
| | | 'tn-border-solid-right': (index + 1) % 3 != 0 |
| | | }" |
| | | :hover-class="hoverClass(index)" |
| | | :hover-stay-time="150" |
| | | @tap="keyboardClick(item)" |
| | | > |
| | | <view class="tn-number-keyboard__grids__btn">{{ item }}</view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-number-keyboard__grids__item tn-bg-gray--light" |
| | | hover-class="tn-hover" |
| | | :hover-stay-time="150" |
| | | @touchstart.stop="backspaceClick" |
| | | @touchend="clearTimer" |
| | | > |
| | | <view class="tn-number-keyboard__grids__btn tn-number-keyboard__back"> |
| | | <view class="tn-icon-left-arrow tn-number-keyboard__back__icon"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-number-keyboard', |
| | | props: { |
| | | // é®çç±»å |
| | | // number -> æ°åé®ç card -> 身份è¯é®ç |
| | | mode: { |
| | | type: String, |
| | | default: 'number' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé®çç'.'ç¬¦å· |
| | | dotEnabled: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦ä¸ºä¹±åºé®ç |
| | | randomEnabled: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // é®çæ¾ç¤ºçå
容 |
| | | dataList() { |
| | | let tmp = [] |
| | | if (!this.dotEnabled && this.mode === 'number') { |
| | | if (!this.randomEnabled) { |
| | | return [1, 2, 3, 4, 5, 6, 7, 8, 9, '', 0] |
| | | } else { |
| | | let data = this.$t.array.random([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) |
| | | data.splice(-1, 0, '') |
| | | return data |
| | | } |
| | | } else if (this.dotEnabled && this.mode === 'number') { |
| | | if (!this.randomEnabled) { |
| | | return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0] |
| | | } else { |
| | | let data = this.$t.array.random([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) |
| | | data.splice(-1, 0, this.dot) |
| | | return data |
| | | } |
| | | } else if (this.mode === 'card') { |
| | | if (!this.randomEnabled) { |
| | | return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0] |
| | | } else { |
| | | let data = this.$t.array.random([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) |
| | | data.splice(-1, 0, this.cardX) |
| | | return data |
| | | } |
| | | } |
| | | }, |
| | | // æé®çæ ·å¼ |
| | | keyStyle() { |
| | | return index => { |
| | | let style = {} |
| | | if (this.mode === 'number' && !this.dotEnabled && index === 9) style.flex = '0 0 66.6666666666%' |
| | | return style |
| | | } |
| | | }, |
| | | // æ¯å¦è®©æé®æ¾ç¤ºç°è²ï¼åªå¨æ°åé®çåéä¹±åºä¸å¨ç¹å»æ¶ |
| | | showGaryBg() { |
| | | return index => { |
| | | if (!this.randomEnabled && index === 9 && (this.mode !== 'number' || (this.mode === 'number' && this.dotEnabled))) return true |
| | | else return false |
| | | } |
| | | }, |
| | | // ææåççclass |
| | | hoverClass() { |
| | | return index => { |
| | | if (this.mode === 'number' && !this.dotEnabled && index === 9) return '' |
| | | if (!this.randomEnabled && index === 9 && (this.mode === 'number' && this.dotEnabled || this.mode === 'card')) return 'tn-hover' |
| | | else return 'tn-number-keyboard--hover' |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // éæ ¼é®å
容 |
| | | backspace: 'backspace', |
| | | // ç¹å
容 |
| | | dot: '.', |
| | | // é¿æå¤æ¬¡å é¤äºä»¶çå¬ |
| | | longPressDeleteTimer: null, |
| | | // 身份è¯çXç¬¦å· |
| | | cardX: 'X' |
| | | } |
| | | }, |
| | | methods: { |
| | | // ç¹å»éæ ¼é® |
| | | backspaceClick() { |
| | | this.$emit('backspace') |
| | | this.clearTimer() |
| | | this.longPressDeleteTimer = setInterval(() => { |
| | | this.$emit('backspace') |
| | | }, 250) |
| | | }, |
| | | // è·åé®çæ¾ç¤ºçå
容 |
| | | keyboardClick(value) { |
| | | if (this.mode === 'number' && !this.dotEnabled && value === '') return |
| | | // å
许é®çæ¾ç¤ºç¹æ¨¡å¼å触åéç¹æé®æ¶ï¼å°å
容转æ¢ä¸ºæ°åç±»å |
| | | if (this.dotEnabled && value != this.dot && value != this.cardX) value = Number(value) |
| | | this.$emit('change', value) |
| | | }, |
| | | // æ¸
é¤å®æ¶å¨ |
| | | clearTimer() { |
| | | if (this.longPressDeleteTimer) { |
| | | clearInterval(this.longPressDeleteTimer) |
| | | this.longPressDeleteTimer = null |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tn-number-keyboard { |
| | | position: relative; |
| | | |
| | | &__grids { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | justify-content: flex-end; |
| | | |
| | | &__item { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex: 0 0 33.3333333333%; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 110rpx; |
| | | text-align: center; |
| | | font-size: 50rpx; |
| | | color: $tn-font-color; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | &__back { |
| | | font-size: 38rpx; |
| | | } |
| | | |
| | | &--hover { |
| | | background-color: $tn-font-holder-color; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="value" class="tn-picker-class tn-picker"> |
| | | <tn-popup |
| | | v-model="value" |
| | | mode="bottom" |
| | | :popup="false" |
| | | length="auto" |
| | | :safeAreaInsetBottom="safeAreaInsetBottom" |
| | | :maskCloseable="maskCloseable" |
| | | :zIndex="elZIndex" |
| | | @close="close" |
| | | > |
| | | <view class="tn-picker__content" :style="{ zIndex: elZIndex }"> |
| | | <!-- é¡¶é¨ --> |
| | | <view class="tn-picker__content__header tn-border-solid-bottom" @touchmove.stop.prevent> |
| | | <!-- åæ¶æé® --> |
| | | <view |
| | | class="tn-picker__content__header__btn tn-picker__content__header--cancel" |
| | | :style="{ color: cancelColor }" |
| | | hover-class="tn-hover-class" |
| | | :hover-stay-time="150" |
| | | @tap="getResult('cancel')" |
| | | >{{cancelText}}</view> |
| | | <!-- æ é¢ --> |
| | | <view class="tn-picker__content__header__title">{{ title }}</view> |
| | | <!-- 确认æé® --> |
| | | <view |
| | | class="tn-picker__content__header__btn tn-picker__content__header--confirm" |
| | | :style="{ color: moving ? cancelColor : confirmColor}" |
| | | hover-class="tn-hover-class" |
| | | :hover-stay-time="150" |
| | | @touchmove.stop |
| | | @tap.stop="getResult('confirm')" |
| | | >{{confirmText}}</view> |
| | | </view> |
| | | <!-- ä¸»ä½ --> |
| | | <view class="tn-picker__content__body"> |
| | | <!-- å°åºéæ© --> |
| | | <picker-view |
| | | v-if="mode === 'region'" |
| | | class="tn-picker__content__body__view" |
| | | :value="valueArr" |
| | | @change="change" |
| | | @pickstart="pickStart" |
| | | @pickend="pickEnd" |
| | | > |
| | | <picker-view-column v-if="!reset && params.province"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in provinces" :key="index"> |
| | | <view class="tn-text-ellipsis">{{ item.label }}</view> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.city"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in citys" :key="index"> |
| | | <view class="tn-text-ellipsis">{{ item.label }}</view> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.area"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in areas" :key="index"> |
| | | <view class="tn-text-ellipsis">{{ item.label }}</view> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | <!-- æ¶é´éæ© --> |
| | | <picker-view |
| | | v-else-if="mode === 'time'" |
| | | class="tn-picker__content__body__view" |
| | | :value="valueArr" |
| | | @change="change" |
| | | @pickstart="pickStart" |
| | | @pickend="pickEnd" |
| | | > |
| | | <picker-view-column v-if="!reset && params.year"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in years" :key="index"> |
| | | {{ item }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item__text">å¹´</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.month"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in months" :key="index"> |
| | | {{ formatNumber(item) }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item--text">æ</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.day"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in days" :key="index"> |
| | | {{ formatNumber(item) }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item--text">æ¥</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.hour"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in hours" :key="index"> |
| | | {{ formatNumber(item) }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item--text">æ¶</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.minute"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in minutes" :key="index"> |
| | | {{ formatNumber(item) }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item--text">å</text> |
| | | </view> |
| | | </picker-view-column> |
| | | <picker-view-column v-if="!reset && params.second"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in seconds" :key="index"> |
| | | {{ formatNumber(item) }} |
| | | <text v-if="showTimeTag" class="tn-picker__content__body__item--text">ç§</text> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | <!-- ååéæ© --> |
| | | <picker-view |
| | | v-else-if="mode === 'selector'" |
| | | class="tn-picker__content__body__view" |
| | | :value="valueArr" |
| | | @change="change" |
| | | @pickstart="pickStart" |
| | | @pickend="pickEnd" |
| | | > |
| | | <picker-view-column v-if="!reset"> |
| | | <view class="tn-picker__content__body__item" v-for="(item, index) in range" :key="index"> |
| | | <view class="tn-text-ellipsis">{{ getItemValue(item, 'selector') }}</view> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | <!-- å¤åéæ© --> |
| | | <picker-view |
| | | v-else-if="mode === 'multiSelector'" |
| | | class="tn-picker__content__body__view" |
| | | :value="valueArr" |
| | | @change="change" |
| | | @pickstart="pickStart" |
| | | @pickend="pickEnd" |
| | | > |
| | | <picker-view-column v-if="!reset" v-for="(item, index) in range" :key="index"> |
| | | <view class="tn-picker__content__body__item" v-for="(sub_item, sub_index) in item" :key="sub_index"> |
| | | <view class="tn-text-ellipsis">{{ getItemValue(sub_item, 'multiSelector') }}</view> |
| | | </view> |
| | | </picker-view-column> |
| | | </picker-view> |
| | | </view> |
| | | </view> |
| | | </tn-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import provinces from '../../libs/utils/province.js' |
| | | import citys from '../../libs/utils/city.js' |
| | | import areas from '../../libs/utils/area.js' |
| | | |
| | | export default { |
| | | name: 'tn-picker', |
| | | props: { |
| | | value: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | // 顶鍿 é¢ |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // picker䏿¾ç¤ºçåæ° |
| | | params: { |
| | | type: Object, |
| | | default() { |
| | | return { |
| | | year: true, |
| | | month: true, |
| | | day: true, |
| | | hour: false, |
| | | minute: false, |
| | | second: false, |
| | | province: true, |
| | | city: true, |
| | | area: true, |
| | | timestamp: true |
| | | } |
| | | } |
| | | }, |
| | | // 模å¼éæ©ï¼region-å°åºç±»åï¼time-æ¶é´ç±»åï¼selector-å忍¡å¼ï¼multiSelector-å¤åæ¨¡å¼ |
| | | mode: { |
| | | type: String, |
| | | default: 'time' |
| | | }, |
| | | // å½mode=selectoræè
mode=multiSelectoræ¶ï¼æä¾çæ°ç» |
| | | range: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // å½mode=selectoræè
mode=multiSelectoræ¶ï¼æä¾çé»è®¤é¡¹ä¸æ |
| | | defaultSelector: { |
| | | type: Array, |
| | | default() { |
| | | return [0] |
| | | } |
| | | }, |
| | | // å½rangeæ¯ä¸ä¸ªArray<Object>æ¶ï¼éè¿rangeKeyæ¥æå®Objectä¸keyçå¼ä½ä¸ºæ¾ç¤ºçå
容 |
| | | rangeKey: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¶é´æ¨¡å¼ ï¼æ¯å¦æ¾ç¤ºæ¶é´åçåä½ |
| | | showTimeTag: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å¼å§å¹´ä»½ |
| | | startYear: { |
| | | type: [String, Number], |
| | | default: 1950 |
| | | }, |
| | | // ç»æå¹´ä»½ |
| | | endYear: { |
| | | type: [String, Number], |
| | | default: 2050 |
| | | }, |
| | | // é»è®¤æ¾ç¤ºçæ¶é´ |
| | | // 2021-09-01 || 2021-09-01 13:00:23 || 2021/09/01 |
| | | defaultTime: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // é»è®¤æ¾ç¤ºçå°åº |
| | | // å¯ä¼ 类似["广ä¸ç", "广å·å¸", "天河åº"] |
| | | defaultRegin: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // é»è®¤æ¾ç¤ºçå°åºç¼ç |
| | | // å¯ä¼ 类似["11", "1101", "110101"] |
| | | // 妿defaultReginåareaCodeåæ¶åå¨ï¼ä¼å
使ç¨areaCodeçå¼ |
| | | areaCode: { |
| | | type: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | // åæ¶æé®çæå |
| | | cancelText: { |
| | | type: String, |
| | | default: 'åæ¶' |
| | | }, |
| | | // åæ¶æé®çé¢è² |
| | | cancelColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 确认æé®çæå |
| | | confirmText: { |
| | | type: String, |
| | | default: '确认' |
| | | }, |
| | | // 确认æé®çæ¼ç¤º |
| | | confirmColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å
许éè¿ç¹å»é®ç½©å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | // çå¬åæ°åå |
| | | propsChange() { |
| | | return [this.mode, this.defaultTime, this.startYear, this.endYear, this.defaultRegin, this.areaCode] |
| | | }, |
| | | // çå¬å°åºåçåå |
| | | regionChange() { |
| | | return [this.province, this.city] |
| | | }, |
| | | // çå¬å¹´æåçåå |
| | | yearAndMonth() { |
| | | return [this.year, this.month] |
| | | }, |
| | | elZIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.popup |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | years: [], |
| | | months: [], |
| | | days: [], |
| | | hours: [], |
| | | minutes: [], |
| | | seconds: [], |
| | | year: 0, |
| | | month: 0, |
| | | day: 0, |
| | | hour: 0, |
| | | minute: 0, |
| | | second: 0, |
| | | reset: false, |
| | | startDate: '', |
| | | endDate: '', |
| | | valueArr: [], |
| | | provinces: provinces, |
| | | citys: citys[0], |
| | | areas: areas[0][0], |
| | | province: 0, |
| | | city: 0, |
| | | area: 0, |
| | | // 忝å¦è¿å¨æ»å¨ä¸ï¼å¾®ä¿¡å°ç¨åºå¦æå¨æ»å¨ä¸å°±ç¹ç¡®å®ï¼ç»æå¯è½ä¸åç¡® |
| | | moving: false |
| | | } |
| | | }, |
| | | watch: { |
| | | propsChange() { |
| | | this.reset = true |
| | | setTimeout(() => this.init(), 10) |
| | | }, |
| | | regionChange() { |
| | | // 妿å°åºåçååï¼ä¸ºäºè®©pickerèå¨èµ·æ¥ï¼å¿
é¡»éç½®this.citysåthis.areas |
| | | this.citys = citys[this.province] |
| | | this.areas = areas[this.province][this.city] |
| | | }, |
| | | yearAndMonth() { |
| | | // æä»½çååï¼å®æ¶åæ´æ¥ç天æ°ï¼å 为ä¸åæä»½ï¼å¤©æ°ä¸ä¸æ · |
| | | // ä¸ä¸ªæå¯è½æ30ï¼31天ï¼çè³é°å¹´2æç29天ï¼å¹³å¹´2æ28天 |
| | | if (this.params.year) this.setDays() |
| | | }, |
| | | value(val) { |
| | | // 微信åQQå°ç¨åºç±äºä¸äºå¥æªçåå (æ
忶坹ææå¹³å°ååå§åä¸é)ï¼éè¦éæ°åå§åæè½æ¾ç¤ºæ£ç¡®çå¼ |
| | | if (val) { |
| | | this.reset = true |
| | | setTimeout(() => this.init(), 10) |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | // è®°å½å¼å§æ»å¨ |
| | | pickStart() { |
| | | // #ifdef MP-WEIXIN |
| | | this.moving = true |
| | | // #endif |
| | | }, |
| | | // è®°å½æ»å¨ç»æ |
| | | pickEnd() { |
| | | // #ifdef MP-WEIXIN |
| | | this.moving = false |
| | | // #endif |
| | | }, |
| | | // æ ¹æ®ä¼ éçåè¡¨çæ°æ®è·åæ¾ç¤ºçæ°æ® |
| | | getItemValue(item, mode) { |
| | | // å忍¡å¼æè
å¤å模å¼ä¸çgetItemValueåæ¶è¢«æ§è¡ï¼æ
å¨è¿éåå ä¸å±å¤æ |
| | | if (this.mode === mode) { |
| | | return typeof item === 'object' ? item[this.rangeKey] : item |
| | | } |
| | | }, |
| | | // 徿°ååé¢è¡¥0 |
| | | formatNumber(num) { |
| | | return this.$t.number.formatNumberAddZero(num) |
| | | }, |
| | | // çæéè¿çæ°ç» |
| | | generateArray(start, end) { |
| | | // 转为æ°å¼æ ¼å¼ï¼å¦åç¨æ·ç»end-yearçä¼ éåç¬¦ä¸²å¼æ¶ï¼ä¸é¢çend+1ä¼å¯¼è´åç¬¦ä¸²æ¼æ¥ï¼è䏿¯ç¸å |
| | | start = Number(start) |
| | | end = Number(end) |
| | | end = end > start ? end : start |
| | | // çææ°ç»å¹¶è·åå
¶ä¸ç´¢å¼ç¶åæååºæ¥(è·åå¼å§åç»æä¹é´çæ°æ®) |
| | | return [...Array(end+1).keys()].slice(start) |
| | | }, |
| | | getIndex(arr, val) { |
| | | let index = arr.indexOf(val) |
| | | // 妿index为-1çæ¾ä¸å°å
ç´ |
| | | // ~(-1)=(-1)-1=0 |
| | | return ~index ? index : 0 |
| | | }, |
| | | // æ¥ææ¶é´å¤ç |
| | | initTimeValue() { |
| | | // æ ¼å¼åæ¶é´ï¼å¨IEæµè§å¨(uniä¸å卿¤æ
åµ)ï¼æ æ³è¯å«æ¥æé´ç"-"é´éç¬¦å· |
| | | let fdate = this.defaultTime.replace(/\-/g, '/') |
| | | fdate = fdate && fdate.indexOf('/') == -1 ? `2021/01/01 ${fdate}` : fdate |
| | | let time = null |
| | | if (fdate) time = new Date(fdate) |
| | | else time = new Date() |
| | | // è·åå¹´ææ¥æ¶åç§ |
| | | this.year = time.getFullYear() |
| | | this.month = time.getMonth() + 1 |
| | | this.day = time.getDate() |
| | | this.hour = time.getHours() |
| | | this.minute = time.getMinutes() |
| | | this.second = time.getSeconds() |
| | | }, |
| | | // åå§åæ°æ® |
| | | init() { |
| | | this.valueArr = [] |
| | | this.reset = false |
| | | if (this.mode === 'time') { |
| | | this.initTimeValue() |
| | | if (this.params.year) { |
| | | this.valueArr.push(0) |
| | | this.setYears() |
| | | } |
| | | if (this.params.month) { |
| | | this.valueArr.push(0) |
| | | this.setMonths() |
| | | } |
| | | if (this.params.day) { |
| | | this.valueArr.push(0) |
| | | this.setDays() |
| | | } |
| | | if (this.params.hour) { |
| | | this.valueArr.push(0) |
| | | this.setHours() |
| | | } |
| | | if (this.params.minute) { |
| | | this.valueArr.push(0) |
| | | this.setMinutes() |
| | | } |
| | | if (this.params.second) { |
| | | this.valueArr.push(0) |
| | | this.setSeconds() |
| | | } |
| | | } else if (this.mode === 'region') { |
| | | if (this.params.province) { |
| | | this.valueArr.push(0) |
| | | this.setProvinces() |
| | | } |
| | | if (this.params.city) { |
| | | this.valueArr.push(0) |
| | | this.setCitys() |
| | | } |
| | | if (this.params.area) { |
| | | this.valueArr.push(0) |
| | | this.setAreas() |
| | | } |
| | | } else if (this.mode === 'selector') { |
| | | this.valueArr = this.defaultSelector |
| | | } else if (this.mode === 'multiSelector') { |
| | | this.valueArr = this.defaultSelector |
| | | this.multiSelectorValue = this.defaultSelector |
| | | } |
| | | this.$forceUpdate() |
| | | }, |
| | | // 设置pickeræä¸åçå¼ |
| | | setYears() { |
| | | this.years = this.generateArray(this.startYear, this.endYear) |
| | | // 设置this.valueArræä¸é¡¹çå¼ï¼æ¯ä¸ºäºè®©pickeré¢é䏿ä¸ä¸ªå¼ |
| | | this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year)) |
| | | }, |
| | | setMonths() { |
| | | this.months = this.generateArray(1, 12) |
| | | this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month)) |
| | | }, |
| | | setDays() { |
| | | let totalDays = new Date(this.year, this.month, 0).getDate() |
| | | this.days = this.generateArray(1, totalDays) |
| | | let index = 0 |
| | | // é¿å
夿¬¡è§¦å导è´å¼æ°ç»è®¡ç®é误 |
| | | if (this.params.year && this.params.month) index = 2 |
| | | else if (this.params.month) index = 1 |
| | | else if (this.params.year) index = 1 |
| | | else index = 0 |
| | | |
| | | // 彿份ååæ¶ï¼ä¼å¯¼è´æ¥æç天æ°ä¹ä¼ååï¼å¦æåæ¥éç天æ°å¤§äºåååç天æ°ï¼åé置为åååçæå¤§å¼ |
| | | // æ¯å¦åæ¥éä¸3æ31æ¥ï¼è°æ´ä¸º2æåï¼æ¥æå为æå¤§29ï¼è¿æ¶å¦ædayå¼ç»§ç»ä¸º31æ¾ç¶ä¸åçï¼äºæ¯å°å
¶ç½®ä¸º29(picker-columnä»1å¼å§) |
| | | if (this.day > this.days.length) this.day = this.days.length |
| | | this.valueArr.splice(index, 1, this.getIndex(this.days, this.day)) |
| | | }, |
| | | setHours() { |
| | | this.hours = this.generateArray(0, 23) |
| | | this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour)) |
| | | }, |
| | | setMinutes() { |
| | | this.minutes = this.generateArray(0, 59) |
| | | this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute)) |
| | | }, |
| | | setSeconds() { |
| | | this.seconds = this.generateArray(0, 59) |
| | | this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second)) |
| | | }, |
| | | setProvinces() { |
| | | if (!this.params.province) return |
| | | let tmp = '' |
| | | let useCode = false |
| | | // 妿忶é
ç½®äºdefaultRegionåareaCodeï¼ä¼å
使ç¨areaCodeåæ° |
| | | if (this.areaCode.length) { |
| | | tmp = this.areaCode[0] |
| | | useCode = true |
| | | } else if (this.defaultRegin.length) { |
| | | tmp = this.defaultRegin[0] |
| | | } else { |
| | | tmp = 0 |
| | | } |
| | | // éåç份æ°ç» |
| | | provinces.map((v, k) => { |
| | | if (useCode ? v.value == tmp : v.label == tmp) { |
| | | this.province = k |
| | | return |
| | | } |
| | | }) |
| | | this.provinces = provinces |
| | | this.valueArr.splice(0, 1, this.province) |
| | | }, |
| | | setCitys() { |
| | | if (!this.params.city) return |
| | | let tmp = '' |
| | | let useCode = false |
| | | // 妿忶é
ç½®äºdefaultRegionåareaCodeï¼ä¼å
使ç¨areaCodeåæ° |
| | | if (this.areaCode.length) { |
| | | tmp = this.areaCode[1] |
| | | useCode = true |
| | | } else if (this.defaultRegin.length) { |
| | | tmp = this.defaultRegin[1] |
| | | } else { |
| | | tmp = 0 |
| | | } |
| | | // éåç份æ°ç» |
| | | citys[this.province].map((v, k) => { |
| | | if (useCode ? v.value == tmp : v.label == tmp) { |
| | | this.city = k |
| | | return |
| | | } |
| | | }) |
| | | this.citys = citys[this.province] |
| | | this.valueArr.splice(1, 1, this.city) |
| | | }, |
| | | setAreas() { |
| | | if (!this.params.area) return |
| | | let tmp = '' |
| | | let useCode = false |
| | | // 妿忶é
ç½®äºdefaultRegionåareaCodeï¼ä¼å
使ç¨areaCodeåæ° |
| | | if (this.areaCode.length) { |
| | | tmp = this.areaCode[2] |
| | | useCode = true |
| | | } else if (this.defaultRegin.length) { |
| | | tmp = this.defaultRegin[2] |
| | | } else { |
| | | tmp = 0 |
| | | } |
| | | // éåç份æ°ç» |
| | | areas[this.province][this.city].map((v, k) => { |
| | | if (useCode ? v.value == tmp : v.label == tmp) { |
| | | this.area = k |
| | | return |
| | | } |
| | | }) |
| | | this.areas = areas[this.province][this.city] |
| | | this.valueArr.splice(2, 1, this.area) |
| | | }, |
| | | close() { |
| | | this.$emit('input', false) |
| | | }, |
| | | // çå¬ç¨æ·ä¿®æ¹äºpickeråé项 |
| | | change(event) { |
| | | this.valueArr = event.detail.value |
| | | let i = 0 |
| | | if (this.mode === 'time') { |
| | | // 使ç¨i++æ¯å 为ä¸ç¥éæ°ç»çé¿åº¦ |
| | | if (this.params.year) this.year = this.years[this.valueArr[i++]] |
| | | if (this.params.month) this.month = this.months[this.valueArr[i++]] |
| | | if (this.params.day) this.day = this.days[this.valueArr[i++]] |
| | | if (this.params.hour) this.hour = this.hours[this.valueArr[i++]] |
| | | if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]] |
| | | if (this.params.second) this.second = this.seconds[this.valueArr[i++]] |
| | | } else if (this.mode === 'region') { |
| | | // æ è®°ç叿¯å¦åçäºåå |
| | | let provinceChange = false, |
| | | cityChange = false |
| | | if (this.params.province) { |
| | | let value = this.valueArr[i++] |
| | | if (this.province != value) { |
| | | // 妿ç份åçäºååï¼åéç½®å¸åºçç´¢å¼ä¸º0 |
| | | this.city = 0 |
| | | this.area = 0 |
| | | provinceChange = true |
| | | } |
| | | this.province = value |
| | | } |
| | | if (this.params.city && !provinceChange) { |
| | | let value = this.valueArr[i++] |
| | | if (this.city != value) { |
| | | // 妿å¸åçäºååï¼åéç½®åºçç´¢å¼ä¸º0 |
| | | this.area = 0 |
| | | cityChange = true |
| | | } |
| | | this.city = value |
| | | } |
| | | if (this.params.area && !provinceChange && !cityChange) this.area = this.valueArr[i++] |
| | | |
| | | // 妿æçå¸è¿è¡äºæ¹åï¼éæ°è®¾ç½®å表çå¼ |
| | | if (provinceChange || cityChange) { |
| | | this.valueArr = [this.province, this.city, this.area] |
| | | } |
| | | } else if (this.mode === 'multiSelector') { |
| | | let index = null |
| | | // 对æ¯åå两个æ°ç»ï¼å¯»æ¾åæ´çæ¯åªä¸åï¼å¦ææä¸ä¸ªå
ç´ ä¸åï¼å³å¯å¤å®è¯¥ååçäºåå |
| | | this.defaultSelector.map((v, idx) => { |
| | | if (v != event.detail.value[idx]) index = idx |
| | | }) |
| | | // 为äºè®©ç¨æ·å¯¹å¤åååæ¶ï¼å¨æè®¾ç½®å
¶ä»å |
| | | if (index != null) { |
| | | this.$emit('columnchange', { |
| | | column: index, |
| | | index: event.detail.value[index] |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | // ç¨æ·ç¹å»ç¡®å®æé® |
| | | getResult(event = null) { |
| | | // #ifdef MP-WEIXIN |
| | | if (this.moving) return |
| | | // #endif |
| | | let result = {} |
| | | // åªè¿åç¨æ·éè¦çæ°æ® |
| | | if (this.mode === 'time') { |
| | | if (this.params.year) result.year = this.formatNumber(this.year || 0) |
| | | if (this.params.month) result.month = this.formatNumber(this.month || 0) |
| | | if (this.params.day) result.day = this.formatNumber(this.day || 0) |
| | | if (this.params.hour) result.hour = this.formatNumber(this.hour || 0) |
| | | if (this.params.minute) result.minute = this.formatNumber(this.minute || 0) |
| | | if (this.params.second) result.second = this.formatNumber(this.second || 0) |
| | | if (this.params.timestamp) result.timestamp = this.getTimestamp() |
| | | } else if (this.mode === 'region') { |
| | | if (this.params.province) result.province = provinces[this.province] |
| | | if (this.params.city) result.city = citys[this.province][this.city] |
| | | if (this.params.area) result.area = areas[this.province][this.city][this.area] |
| | | } else if (this.mode === 'multiSelector') { |
| | | result = this.valueArr |
| | | } else if (this.mode === 'selector') { |
| | | result = this.valueArr |
| | | } |
| | | |
| | | if (event) this.$emit(event, result) |
| | | this.close() |
| | | }, |
| | | // è·åæ¶é´æ³ |
| | | getTimestamp() { |
| | | // yyyy-mm-dd为å®ååæ³ï¼ä¸æ¯æiOSï¼éè¦ä½¿ç¨"/"åéï¼æè½äºè
å
¼å®¹ |
| | | let time = this.year + '/' + this.month + '/' + this.day + ' ' + this.hour + ':' + this.minute + ':' + this.second; |
| | | return new Date(time).getTime() / 1000; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-picker { |
| | | &__content { |
| | | position: relative; |
| | | |
| | | &__header { |
| | | position: relative; |
| | | display: flex; |
| | | flex-direction: row; |
| | | width: 100%; |
| | | height: 90rpx; |
| | | padding: 0 40rpx; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | box-sizing: border-box; |
| | | font-size: 30rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &__btn { |
| | | padding: 16rpx; |
| | | box-sizing: border-box; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | } |
| | | |
| | | &__title { |
| | | color: $tn-font-color; |
| | | } |
| | | |
| | | &--cancel { |
| | | color: $tn-font-sub-color; |
| | | } |
| | | |
| | | &--confirm { |
| | | color: $tn-main-color; |
| | | } |
| | | } |
| | | |
| | | &__body { |
| | | width: 100%; |
| | | height: 500rpx; |
| | | overflow: hidden; |
| | | background-color: #FFFFFF; |
| | | |
| | | &__view { |
| | | height: 100%; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | &__item { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | color: $tn-font-color; |
| | | padding: 0 8rpx; |
| | | |
| | | &--text { |
| | | font-size: 24rpx; |
| | | padding-left: 8rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | v-if="visibleSync" |
| | | class="tn-popup-class tn-popup" |
| | | :style="[customStyle, popupStyle, { zIndex: elZIndex - 1}]" |
| | | hover-stop-propagation |
| | | > |
| | | <!-- mask --> |
| | | <view |
| | | class="tn-popup__mask" |
| | | :class="[{'tn-popup__mask--show': showPopup && mask}]" |
| | | :style="{zIndex: elZIndex - 2}" |
| | | @tap="maskClick" |
| | | @touchmove.stop.prevent = "() => {}" |
| | | hover-stop-propagation |
| | | ></view> |
| | | <!-- å¼¹æ¡å
容 --> |
| | | <view |
| | | class="tn-popup__content" |
| | | :class="[ |
| | | mode !== 'center' ? backgroundColorClass : '', |
| | | safeAreaInsetBottom ? 'tn-safe-area-inset-bottom' : '', |
| | | 'tn-popup--' + mode, |
| | | showPopup ? 'tn-popup__content--visible' : '', |
| | | zoom && mode === 'center' ? 'tn-popup__content__center--animation-zoom' : '' |
| | | ]" |
| | | :style="[contentStyle]" |
| | | @tap="modeCenterClose" |
| | | @touchmove.stop.prevent |
| | | @tap.stop.prevent |
| | | > |
| | | <!-- å±
䏿¶åçå
容 --> |
| | | <view |
| | | v-if="mode === 'center'" |
| | | class="tn-popup__content__center_box" |
| | | :class="[backgroundColorClass]" |
| | | :style="[centerStyle]" |
| | | @touchmove.stop.prevent |
| | | @tap.stop.prevent |
| | | > |
| | | <!-- å
³éæé® --> |
| | | <view |
| | | v-if="closeBtn" |
| | | class="tn-popup__close" |
| | | :class="[`tn-icon-${closeBtnIcon}`, `tn-popup__close--${closeBtnPosition}`]" |
| | | :style="[closeBtnStyle, {zIndex: elZIndex}]" |
| | | @tap="close" |
| | | ></view> |
| | | <scroll-view class="tn-popup__content__scroll-view"> |
| | | <slot></slot> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | <!-- é¤å±
ä¸å¤çå
¶ä»æ
åµ --> |
| | | <scroll-view v-else class="tn-popup__content__scroll-view"> |
| | | <slot></slot> |
| | | </scroll-view> |
| | | <!-- å
³éæé® --> |
| | | <view |
| | | v-if="mode !== 'center' && closeBtn" |
| | | class="tn-popup__close" |
| | | :class="[`tn-popup__close--${closeBtnPosition}`]" |
| | | :style="{zIndex: elZIndex}" |
| | | @tap="close" |
| | | > |
| | | <view :class="[`tn-icon-${closeBtnIcon}`]" :style="[closeBtnStyle]"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import componentsColorMixin from '../../libs/mixin/components_color.js' |
| | | export default { |
| | | mixins: [componentsColorMixin], |
| | | name: 'tn-popup', |
| | | props: { |
| | | value: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å¼¹åºæ¹å |
| | | // left/right/top/bottom/center |
| | | mode: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºé®ç½© |
| | | mask: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ½å±ç宽度ï¼mode=left/rightï¼,é«åº¦ï¼mode=top/bottomï¼ |
| | | length: { |
| | | type: [Number, String], |
| | | default: 'auto' |
| | | }, |
| | | // 宽度ï¼åªå¯¹å·¦ï¼å³ï¼ä¸é¨å¼¹åºæ¶èµ·ä½ç¨ï¼åä½rpxï¼æè
"auto" |
| | | // æè
ç¾åæ¯"50%"ï¼è¡¨ç¤ºç±å
容æå¼é«åº¦æè
宽度ï¼ä¼å
级é«äºlengthåæ° |
| | | width: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // é«åº¦ï¼åªå¯¹ä¸ï¼ä¸ï¼ä¸é¨å¼¹åºæ¶èµ·ä½ç¨ï¼åä½rpxï¼æè
"auto" |
| | | // æè
ç¾åæ¯"50%"ï¼è¡¨ç¤ºç±å
容æå¼é«åº¦æè
宽度ï¼ä¼å
级é«äºlengthåæ° |
| | | height: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦å¼å¯å¨ç»ï¼åªå¨mode=centerææ |
| | | zoom: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // æ¯å¦å¼å¯åºé¨å®å
¨åºéé
ï¼å¼å¯çè¯ï¼ä¼å¨iPhoneXæºååºé¨æ·»å ä¸å®çå
è¾¹è· |
| | | safeAreaInsetBottom: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // æ¯å¦å¯ä»¥éè¿ç¹å»é®ç½©è¿è¡å
³é |
| | | maskCloseable: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ç¨æ·èªå®ä¹æ ·å¼ |
| | | customStyle: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | // æ¾ç¤ºåè§çå¤§å° |
| | | borderRadius: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // zIndex |
| | | zIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºå
³éæé® |
| | | closeBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å
³éæé®ç徿 |
| | | closeBtnIcon: { |
| | | type: String, |
| | | default: 'close' |
| | | }, |
| | | // å
³éæé®æ¾ç¤ºçä½ç½® |
| | | // top-left/top-right/bottom-left/bottom-right |
| | | closeBtnPosition: { |
| | | type: String, |
| | | default: 'top-right' |
| | | }, |
| | | // å
³éæé®å¾æ é¢è² |
| | | closeIconColor: { |
| | | type: String, |
| | | default: '#AAAAAA' |
| | | }, |
| | | // å
³éæé®å¾æ çå¤§å° |
| | | closeIconSize: { |
| | | type: Number, |
| | | default: 30 |
| | | }, |
| | | // ç»ä¸ä¸ªè´çmargin-topï¼å¾ä¸åç§»ï¼é¿å
åé®çéåçæ
åµï¼ä»
å¨mode=centeræ¶ææ |
| | | negativeTop: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // marginTopï¼å¨mode = top,left,rightæ¶çæï¼é¿å
ç¨æ·ä½¿ç¨äºèªå®ä¹å¯¼èªæ ï¼ç»ä»¶æå¯¼èªæ 鮿¡äº |
| | | marginTop: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // æ¤ä¸ºå
é¨åæ°ï¼ä¸å¨ææ¡£å¯¹å¤ä½¿ç¨ï¼ä¸ºäºè§£å³Pickeråkeyboardçèåäºå¼¹çªçç»ä»¶ |
| | | // 对v-modelååç»å®å¤å±è°ç¨é ææ¥éä¸è½ä¿®æ¹propså¼çé®é¢ |
| | | popup: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | }, |
| | | computed: { |
| | | // å¤ç使ç¨äºèªå®ä¹å¯¼èªæ æ¶è¢«é®æ¡çé®é¢ |
| | | popupStyle() { |
| | | let style = {} |
| | | if ((this.mode === 'top' || this.mode === 'left' || this.mode === 'right') && this.marginTop) { |
| | | style.marginTop = this.$t.string.getLengthUnitValue(this.marginTop, 'px') |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | // æ ¹æ®modeçä½ç½®ï¼è®¾å®å
¶å¼¹çªç宽度(mode = left|right)ï¼æè
é«åº¦(mode = top|bottom) |
| | | contentStyle() { |
| | | let style = {} |
| | | // 妿æ¯å·¦è¾¹æè
ä¸è¾¹å¼¹åºæ¶ï¼éè¦ç»translate设置为è´å¼ï¼ç¨äºéè |
| | | if (this.mode === 'left' || this.mode === 'right') { |
| | | style = { |
| | | width: this.width ? this.$t.string.getLengthUnitValue(this.width) : this.$t.string.getLengthUnitValue(this.length), |
| | | height: '100%', |
| | | transform: `translate3D(${this.mode === 'left' ? '-100%' : '100%'}, 0px, 0px)` |
| | | } |
| | | } else if (this.mode === 'top' || this.mode === 'bottom') { |
| | | style = { |
| | | width: '100%', |
| | | height: this.height ? this.$t.string.getLengthUnitValue(this.height) : this.$t.string.getLengthUnitValue(this.length), |
| | | transform: `translate3D(0px, ${this.mode === 'top' ? '-100%': '100%'}, 0px)` |
| | | } |
| | | } |
| | | style.zIndex = this.elZIndex |
| | | // å¦æè®¾ç½®äºåè§çå¼ï¼æ·»å å¼¹çªçåè§ |
| | | if (this.borderRadius) { |
| | | switch(this.mode) { |
| | | case 'left': |
| | | style.borderRadius = `0 ${this.borderRadius}rpx ${this.borderRadius}rpx 0` |
| | | break |
| | | case 'top': |
| | | style.borderRadius = `0 0 ${this.borderRadius}rpx ${this.borderRadius}rpx` |
| | | break |
| | | case 'right': |
| | | style.borderRadius = `${this.borderRadius}rpx 0 0 ${this.borderRadius}rpx` |
| | | break |
| | | case 'bottom': |
| | | style.borderRadius = `${this.borderRadius}rpx ${this.borderRadius}rpx 0 0` |
| | | break |
| | | } |
| | | style.overflow = 'hidden' |
| | | } |
| | | |
| | | if (this.backgroundColorStyle && this.mode !== 'center') { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | // ä¸é¨å¼¹çªçæ ·å¼ |
| | | centerStyle() { |
| | | let style = {} |
| | | style.width = this.width ? this.$t.string.getLengthUnitValue(this.width) : this.$t.string.getLengthUnitValue(this.length) |
| | | // ä¸é¨å¼¹åºç模å¼ï¼å¦ææ²¡æè®¾ç½®é«åº¦ï¼å°±ç¨autoå¼ï¼ç±å
容æå¼ |
| | | style.height = this.height ? this.$t.string.getLengthUnitValue(this.height) : 'auto' |
| | | style.zIndex = this.elZIndex |
| | | if (this.negativeTop) { |
| | | style.marginTop = `-${this.$t.string.getLengthUnitValue(this.negativeTop)}` |
| | | } |
| | | if (this.borderRadius) { |
| | | style.borderRadius = `${this.borderRadius}rpx` |
| | | style.overflow='hidden' |
| | | } |
| | | if (this.backgroundColorStyle) { |
| | | style.backgroundColor = this.backgroundColorStyle |
| | | } |
| | | return style |
| | | }, |
| | | // å
³éæé®æ ·å¼ |
| | | closeBtnStyle() { |
| | | let style = {} |
| | | if (this.closeIconColor) { |
| | | style.color = this.closeIconColor |
| | | } |
| | | if (this.closeIconSize) { |
| | | style.fontSize = this.closeIconSize + 'rpx' |
| | | } |
| | | |
| | | return style |
| | | }, |
| | | elZIndex() { |
| | | return this.zIndex ? this.zIndex : this.$t.zIndex.popup |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | timer: null, |
| | | visibleSync: false, |
| | | showPopup: false, |
| | | closeFromInner: false |
| | | } |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | if (val) { |
| | | // console.log(this.visibleSync); |
| | | if (this.visibleSync) { |
| | | this.visibleSync = false |
| | | return |
| | | } |
| | | this.open() |
| | | } else if (!this.closeFromInner) { |
| | | this.close() |
| | | } |
| | | this.closeFromInner = false |
| | | } |
| | | }, |
| | | mounted() { |
| | | // ç»ä»¶æ¸²æå®ææ¶ï¼æ£æ¥valueæ¯å¦ä¸ºtrueï¼å¦ææ¯ï¼å¼¹åºpopup |
| | | this.value && this.open() |
| | | }, |
| | | methods: { |
| | | // ç¹å»é®ç½© |
| | | maskClick() { |
| | | if (!this.maskCloseable) return |
| | | this.close() |
| | | }, |
| | | open() { |
| | | this.change('visibleSync', 'showPopup', true) |
| | | }, |
| | | // å
³éå¼¹æ¡ |
| | | close() { |
| | | // æ è®°å
³éæ¯å
é¨åççï¼å¦åä¿®æ¹äºvalueå¼ï¼å¯¼è´watchä¸å¯¹valueæ£æµï¼å¯¼è´åæ§è¡ä¸éclose |
| | | // é æ@closeäºä»¶è§¦å两次 |
| | | this.closeFromInner = true |
| | | this.change('showPopup', 'visibleSync', false) |
| | | }, |
| | | // ä¸é¨å¼¹åºæ¶ï¼éè¦.tn-drawer-contentå°å
容å±
ä¸ï¼æ¤å
ç´ ä¼éºæ»¡å±å¹ï¼ç¹å»éè¦å
³éå¼¹çª |
| | | // 让å
¶åªå¨mode=centeræ¶èµ·ä½ç¨ |
| | | modeCenterClose() { |
| | | if (this.mode != 'center' || !this.maskCloseable) return |
| | | this.close() |
| | | }, |
| | | // å
³éæ¶å
éè¿å¨ç»éèå¼¹çªåé®ç½©ï¼åç§»é¤æ´ä¸ªç»ä»¶ |
| | | // æå¼æ¶ï¼å
渲æç»ä»¶ï¼å»¶æ¶ä¸å®æ¶é´å让é®ç½©åå¼¹çªçå¨ç»èµ·ä½ç¨ |
| | | change(param1, param2, status) { |
| | | // 妿this.popup为falseï¼æå³ç为pickerï¼actionsheetçç»ä»¶è°ç¨äºpopupç»ä»¶ |
| | | if (this.popup === true) { |
| | | this.$emit('input', status) |
| | | } |
| | | this[param1] = status |
| | | if (status) { |
| | | // #ifdef H5 || MP |
| | | this.timer = setTimeout(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | clearTimeout(this.timer) |
| | | }, 10) |
| | | // #endif |
| | | // #ifndef H5 || MP |
| | | this.$nextTick(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | }) |
| | | // #endif |
| | | } else { |
| | | this.timer = setTimeout(() => { |
| | | this[param2] = status |
| | | this.$emit(status ? 'open' : 'close') |
| | | clearTimeout(this.timer) |
| | | }, 250) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-popup { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | overflow: hidden; |
| | | |
| | | &__content { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: absolute; |
| | | transition: all 0.25s linear; |
| | | |
| | | &--visible { |
| | | transform: translate3D(0px, 0px, 0px) !important; |
| | | &.tn-popup--center { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | &__center_box { |
| | | min-width: 100rpx; |
| | | min-height: 100rpx; |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: relative; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &__scroll-view { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | &__center--animation-zoom { |
| | | transform: scale(1.15); |
| | | } |
| | | } |
| | | |
| | | &__scroll_view { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | &--left { |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &--right { |
| | | top: 0; |
| | | bottom: 0; |
| | | right: 0; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &--top { |
| | | left: 0; |
| | | right: 0; |
| | | top: 0; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &--bottom { |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &--center { |
| | | display: flex; |
| | | flex-direction: column; |
| | | bottom: 0; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | justify-content: center; |
| | | align-items: center; |
| | | opacity: 0; |
| | | } |
| | | |
| | | &__close { |
| | | position: absolute; |
| | | |
| | | &--top-left { |
| | | top: 30rpx; |
| | | left: 30rpx; |
| | | } |
| | | |
| | | &--top-right { |
| | | top: 30rpx; |
| | | right: 30rpx; |
| | | } |
| | | |
| | | &--bottom-left { |
| | | bottom: 30rpx; |
| | | left: 30rpx; |
| | | } |
| | | |
| | | &--bottom-right { |
| | | bottom: 30rpx; |
| | | right: 30rpx; |
| | | } |
| | | } |
| | | |
| | | &__mask { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | border: 0; |
| | | background-color: $tn-mask-bg-color; |
| | | transition: 0.25s linear; |
| | | transition-property: opacity; |
| | | opacity: 0; |
| | | |
| | | &--show { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-radio-group-class tn-radio-group"> |
| | | <slot></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Emitter from '../../libs/utils/emitter.js' |
| | | |
| | | export default { |
| | | mixins: [ Emitter ], |
| | | name: 'tn-radio-group', |
| | | props: { |
| | | // åéç»çå¼ï¼ä¼éä¸å¼ç¸åçé项 |
| | | value: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // æ¯å¦ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¦ç¨ç¹å»æ ç¾è¿è¡éæ© |
| | | disabledLabel: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // éæ©æ¡çå½¢ç¶ square æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: 'circle' |
| | | }, |
| | | // é䏿¶çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '#01BEFF' |
| | | }, |
| | | // ç»ä»¶å¤§å° |
| | | size: { |
| | | type: Number, |
| | | default: 34 |
| | | }, |
| | | // æ¯ä¸ªradioå ç宽度 |
| | | width: { |
| | | type: String, |
| | | default: 'auto' |
| | | }, |
| | | // æ¯å¦æ¢è¡ |
| | | wrap: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 徿 å¤§å° |
| | | iconSize: { |
| | | type: Number, |
| | | default: 20 |
| | | } |
| | | }, |
| | | computed: { |
| | | // è¿écomputedçåéï¼é½æ¯åç»ä»¶tn-radioéè¦ç¨å°çï¼ç±äºå¤´æ¡å°ç¨åºçå
¼å®¹æ§å·®å¼ï¼åç»ä»¶æ æ³å®æ¶çå¬ç¶ç»ä»¶åæ°çåå |
| | | // æä»¥éè¦æå¨éç¥åç»ä»¶ï¼è¿éè¿åä¸ä¸ªparentDataåéï¼ä¾watchçå¬ï¼å¨å
¶ä¸å»éç¥æ¯ä¸ä¸ªåç»ä»¶éæ°ä»ç¶ç»ä»¶(tn-radio-group) |
| | | // æåç¶ç»ä»¶æ°çåååçåæ° |
| | | parentData() { |
| | | return [this.value, this.disabled, this.activeColor, this.size, this.disabledLabel, this.shape, this.iconSize, this.width, this.wrap] |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | watch: { |
| | | // å½ç¶ç»ä»¶ä¸çåç»ä»¶éè¦å
±äº«çåæ°åçäºååï¼æå¨éç¥åç»ä»¶ |
| | | parentData() { |
| | | if (this.children.length) { |
| | | this.children.map(child => { |
| | | // 夿åç»ä»¶(tn-radio)妿æupdateParentDataæ¹æ³çè¯ï¼åç»ä»¶éæ°ä»ç¶ç»ä»¶æåäºææ°çå¼ |
| | | typeof(child.updateParentData) === 'function' && child.updateParentData() |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // 妿å°childrenå®ä¹å¨dataä¸ï¼å¨å¾®ä¿¡å°ç¨åºä¼é æå¾ªç¯å¼ç¨èæ¥é |
| | | this.children = [] |
| | | }, |
| | | methods: { |
| | | // æ¹æ¹æ³ç±åç»ä»¶tn-radioè°ç¨ï¼å½ä¸ä¸ªtn-radio被éä¸çæ¶åï¼ç»ç¶ç»ä»¶è®¾ç½®valueå¼ï¼éç¥å
¶ä»tn-radioç»ä»¶ï¼ |
| | | setValue(value) { |
| | | // éè¿åç»ä»¶ä¼ éè¿æ¥çvalueå¼(æ¤è¢«éä¸çåç»ä»¶å
é¨å·²å°parentValue设置çäºvalueçå¼)ï¼å°å
¶ä»tn-radio设置æªéä¸çç¶æ |
| | | this.children.map(child => { |
| | | if (child.parentData.value !== value) child.parentData.value = '' |
| | | }) |
| | | // éè¿emitäºä»¶ï¼è®¾ç½®ç¶ç»ä»¶éè¿v-modelååç»å®çå¼ |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | // çå¾
ä¸ä¸ä¸ªå¨æåæ§è¡ï¼å 为this.$emit('input')ä½ç¨äºç¶ç»ä»¶ï¼ååé¦å°åç»ä»¶å
é¨ï¼éè¦æ¶é´ |
| | | // ç±äºå¤´æ¡å°ç¨åºæ§è¡è¿éï¼æ
éè¦ç¨å 忝«ç§çå»¶æ¶ |
| | | setTimeout(() => { |
| | | // å°å½åçå¼åéå° tn-form-item è¿è¡æ ¡éª |
| | | this.dispatch('tn-form-item', 'on-form-change', value); |
| | | }, 60) |
| | | |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-radio-group { |
| | | /* #ifndef MP || APP-NVUE */ |
| | | display: inline-flex; |
| | | flex-wrap: wrap; |
| | | /* #endif */ |
| | | &::after { |
| | | content: " "; |
| | | display: table; |
| | | clear: both; |
| | | } |
| | | } |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="tn-radio-class tn-radio" :style="[radioStyle]"> |
| | | <view |
| | | class="tn-radio__icon-wrap" |
| | | :class="[iconClass]" |
| | | :style=[iconStyle] |
| | | @tap="toggle" |
| | | > |
| | | <view class="tn-icon-success tn-radio__icon-wrap__icon"></view> |
| | | </view> |
| | | |
| | | <view |
| | | class="tn-radio__label" |
| | | :style="{ |
| | | fontSize: labelSize ? labelSize + 'rpx' : '' |
| | | }" |
| | | @tap="onClickLabel" |
| | | > |
| | | <slot></slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'tn-radio', |
| | | props: { |
| | | // radioåç§° |
| | | name: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // æ¯å¦ç¦ç¨ |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç¦ç¨ç¹å»æ ç¾è¿è¡éæ© |
| | | disabledLabel: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // éæ©æ¡çå½¢ç¶ square æ¹å½¢ circle åå½¢ |
| | | shape: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // é䏿¶çé¢è² |
| | | activeColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // ç»ä»¶å°ºå¯¸ |
| | | size: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // 徿 å¤§å° |
| | | iconSize: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | // labelåä½å¤§å° |
| | | labelSize: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | // ç¦ç¨ï¼ç¶ç»ä»¶ä¼è¦çåç»ä»¶çç¶æ |
| | | isDisabled() { |
| | | return this.disabled ? this.disabled : (this.parentData.disabled ? this.parentData.disabled : false) |
| | | }, |
| | | // ç¦ç¨labelç¹å»ï¼ç¶ç»ä»¶ä¼è¦çåç»ä»¶çç¶æ |
| | | isDisabledLabel() { |
| | | return this.disabledLabel ? this.disabledLabel : (this.parentData.disabledLabel ? this.parentData.disabledLabel : false) |
| | | }, |
| | | // ç»ä»¶å°ºå¯¸ |
| | | elSize() { |
| | | return this.size ? this.size : (this.parentData.size ? this.parentData.size : 34) |
| | | }, |
| | | // ç»ä»¶é䏿¶çé¢è² |
| | | elActiveColor() { |
| | | return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#01BEFF') |
| | | }, |
| | | // ç»ä»¶å½¢ç¶ |
| | | elShape() { |
| | | return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle') |
| | | }, |
| | | iconClass() { |
| | | let clazz = '' |
| | | clazz += (' tn-radio__icon-wrap--' + this.elShape) |
| | | |
| | | if (this.parentData.value === this.name) clazz += ' tn-radio__icon-wrap--checked' |
| | | if (this.isDisabled) clazz += ' tn-radio__icon-wrap--disabled' |
| | | if (this.parentData.value === this.name && this.isDisabled) clazz += ' tn-radio__icon-wrap--disabled--checked' |
| | | |
| | | return clazz |
| | | }, |
| | | iconStyle() { |
| | | // å½åradioçnameçäºparentçvalueæè®¤ä¸ºæ¶éä¸ |
| | | let style = {} |
| | | if (this.elActiveColor && this.parentData.value === this.name && !this.isDisabled) { |
| | | style.borderColor = this.elActiveColor |
| | | style.backgroundColor = this.elActiveColor |
| | | } |
| | | |
| | | style.color = this.parentData.value === this.name ? '#FFFFFF' : 'transparent' |
| | | |
| | | style.width = this.elSize + 'rpx' |
| | | style.height = style.width |
| | | |
| | | style.fontSize = (this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 20)) + 'rpx' |
| | | |
| | | return style |
| | | }, |
| | | radioStyle() { |
| | | let style = {} |
| | | if (this.parent && this.parentData.width) { |
| | | // #ifdef MP |
| | | // åå®¶å°ç¨åºå 为å®ä»¬ç¹æ®çç¼è¯ç»æï¼ä½¿ç¨floatå¸å± |
| | | style.float = 'left'; |
| | | // #endif |
| | | // #ifndef MP |
| | | // H5åAPP使ç¨flexå¸å± |
| | | style.flex = `0 0 ${this.parentData.width}`; |
| | | // #endif |
| | | } |
| | | if(this.parent && this.parentData.wrap) { |
| | | style.width = '100%'; |
| | | // #ifndef MP |
| | | // H5åAPP使ç¨flexå¸å±ï¼å°å®½åº¦è®¾ç½®100%ï¼å³å¯èªå¨æ¢è¡ |
| | | style.flex = '0 0 100%'; |
| | | // #endif |
| | | } |
| | | |
| | | return style |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // ç¶ç»ä»¶çé»è®¤å¼ï¼å 为头æ¡å°ç¨åºä¸æ¯æå¨computedä¸ä½¿ç¨this.parent.xxxçå½¢å¼ |
| | | // æ
åªè½ä½¿ç¨å¦æ¤æ¹æ³ |
| | | parentData: { |
| | | value: null, |
| | | disabled: null, |
| | | disabledLabel: null, |
| | | shape: null, |
| | | activeColor: null, |
| | | size: null, |
| | | width: null, |
| | | wrap: null, |
| | | iconSize: null, |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // æ¯ä»å®å°ç¨åºä¸æ¯æprovide/injectï¼æä»¥ä½¿ç¨è¿ä¸ªæ¹æ³è·åæ´ä¸ªç¶ç»ä»¶ï¼å¨createdå®ä¹ï¼é¿å
循ç¯å¼ç¨ |
| | | this.updateParentData() |
| | | this.parent.children.push(this) |
| | | }, |
| | | methods: { |
| | | updateParentData() { |
| | | this.getParentData('tn-radio-group') |
| | | }, |
| | | onClickLabel() { |
| | | if (!this.isDisabledLabel && !this.isDisabled) { |
| | | this.setRadioCheckedStatus() |
| | | } |
| | | }, |
| | | toggle() { |
| | | if (!this.isDisabled) { |
| | | this.setRadioCheckedStatus() |
| | | } |
| | | }, |
| | | emitEvent() { |
| | | // tn-radioçnameä¸çäºç¶ç»ä»¶çv-modelç弿¶(æå³çæªéä¸)ï¼æååºäºä»¶ï¼é¿å
夿¬¡ç¹å»è§¦åäºä»¶ |
| | | if (this.parentData.value !== this.name) this.$emit('change', this.name) |
| | | }, |
| | | // æ¹åéä¸çç¶æ |
| | | // æ´æ¹æ¬ç»ä»¶çparentData.valueçå¼ä¸ºæ¬ç»ä»¶çnameå¼ï¼åæ¶éè¿ç¶ç»ä»¶éåææçradioå®ä¾ |
| | | // å°æ¬ç»ä»¶å¤çå
¶ä»radioçparentData.valueé½è®¾ç½®ä¸ºç©º |
| | | setRadioCheckedStatus() { |
| | | this.emitEvent() |
| | | if (this.parent) { |
| | | this.parent.setValue(this.name) |
| | | this.parentData.value = this.name |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | .tn-radio { |
| | | /* #ifndef APP-NVUE */ |
| | | display: inline-flex; |
| | | /* #endif */ |
| | | align-items: center; |
| | | overflow: hidden; |
| | | user-select: none; |
| | | line-height: 1.8; |
| | | |
| | | &__icon-wrap { |
| | | color: $tn-font-color; |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex: none; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-sizing: border-box; |
| | | width: 42rpx; |
| | | height: 42rpx; |
| | | color: transparent; |
| | | text-align: center; |
| | | transition-property: color, border-color, background-color; |
| | | font-size: 20rpx; |
| | | border: 1rpx solid $tn-font-sub-color; |
| | | transition-duration: 0.2s; |
| | | |
| | | /* #ifdef MP-TOUTIAO */ |
| | | // 头æ¡å°ç¨åºå
¼å®¹æ§é®é¢ï¼éè¦è®¾ç½®è¡é«ä¸º0ï¼å¦å徿 åä¸ |
| | | &__icon { |
| | | line-height: 0; |
| | | } |
| | | /* #endif */ |
| | | |
| | | &--circle { |
| | | border-radius: 100%; |
| | | } |
| | | |
| | | &--square { |
| | | border-radius: 6rpx; |
| | | } |
| | | |
| | | &--checked { |
| | | color: #FFFFFF; |
| | | background-color: $tn-main-color; |
| | | border-color: $tn-main-color; |
| | | } |
| | | |
| | | &--disabled { |
| | | background-color: $tn-font-holder-color; |
| | | border-color: $tn-font-sub-color; |
| | | } |
| | | |
| | | &--disabled--checked { |
| | | color: $tn-font-sub-color !important; |
| | | } |
| | | } |
| | | |
| | | &__label { |
| | | word-wrap: break-word; |
| | | margin-left: 10rpx; |
| | | margin-right: 24rpx; |
| | | color: $tn-font-color; |
| | | font-size: 30rpx; |
| | | |
| | | &--disabled { |
| | | color: $tn-font-sub-color; |
| | | } |
| | | } |
| | | } |
| | | </style> |
代码管理/PDA/tuniao-ui/components/tn-rate/tn-rate.vue
代码管理/PDA/tuniao-ui/components/tn-read-more/tn-read-more.vue
代码管理/PDA/tuniao-ui/components/tn-row-notice/tn-row-notice.vue
代码管理/PDA/tuniao-ui/components/tn-scroll-list/tn-scroll-list.vue
代码管理/PDA/tuniao-ui/components/tn-scroll-view/tn-scroll-view.vue
代码管理/PDA/tuniao-ui/components/tn-select/tn-select.vue
代码管理/PDA/tuniao-ui/components/tn-sign-board/tn-sign-board.vue
代码管理/PDA/tuniao-ui/components/tn-skeleton/tn-skeleton.vue
代码管理/PDA/tuniao-ui/components/tn-slider/tn-slider.vue
代码管理/PDA/tuniao-ui/components/tn-stack-swiper/index-h5.wxs
代码管理/PDA/tuniao-ui/components/tn-stack-swiper/index.wxs
代码管理/PDA/tuniao-ui/components/tn-stack-swiper/tn-stack-swiper.vue
代码管理/PDA/tuniao-ui/components/tn-steps/tn-steps.vue
代码管理/PDA/tuniao-ui/components/tn-sticky/tn-sticky.vue
代码管理/PDA/tuniao-ui/components/tn-subsection/tn-subsection.vue
代码管理/PDA/tuniao-ui/components/tn-swipe-action-item/index.wxs
代码管理/PDA/tuniao-ui/components/tn-swipe-action-item/tn-swipe-action-item.vue
代码管理/PDA/tuniao-ui/components/tn-swipe-action/tn-swipe-action.vue
代码管理/PDA/tuniao-ui/components/tn-swiper/tn-swiper.vue
代码管理/PDA/tuniao-ui/components/tn-switch/tn-switch.vue
代码管理/PDA/tuniao-ui/components/tn-tabbar/tn-tabbar.vue
代码管理/PDA/tuniao-ui/components/tn-table/tn-table.vue
代码管理/PDA/tuniao-ui/components/tn-tabs-swiper/tn-tabs-swiper.vue
代码管理/PDA/tuniao-ui/components/tn-tabs/tn-tabs.vue
代码管理/PDA/tuniao-ui/components/tn-tag/tn-tag.vue
代码管理/PDA/tuniao-ui/components/tn-td/tn-td.vue
代码管理/PDA/tuniao-ui/components/tn-time-line-item/tn-time-line-item.vue
代码管理/PDA/tuniao-ui/components/tn-time-line-item/tn-time-line-item.vue_bk
代码管理/PDA/tuniao-ui/components/tn-time-line/tn-time-line.vue
代码管理/PDA/tuniao-ui/components/tn-time-line/tn-time-line.vue_bk
代码管理/PDA/tuniao-ui/components/tn-tips/tn-tips.vue
代码管理/PDA/tuniao-ui/components/tn-toast/tn-toast.vue
代码管理/PDA/tuniao-ui/components/tn-tr/tn-tr.vue
代码管理/PDA/tuniao-ui/components/tn-tree-node/tn-tree-node.vue
代码管理/PDA/tuniao-ui/components/tn-tree-view/tn-tree-view.vue
代码管理/PDA/tuniao-ui/components/tn-verification-code-input/tn-verification-code-input.vue
代码管理/PDA/tuniao-ui/components/tn-verification-code/tn-verification-code.vue
代码管理/PDA/tuniao-ui/components/tn-waterfall/tn-waterfall.vue
代码管理/PDA/tuniao-ui/iconfont.css
代码管理/PDA/tuniao-ui/index.js
代码管理/PDA/tuniao-ui/index.scss
代码管理/PDA/tuniao-ui/libs/config/color.js
代码管理/PDA/tuniao-ui/libs/config/zIndex.js
代码管理/PDA/tuniao-ui/libs/css/color.scss
代码管理/PDA/tuniao-ui/libs/css/main.scss
代码管理/PDA/tuniao-ui/libs/css/style.h5.scss
代码管理/PDA/tuniao-ui/libs/css/style.mp.scss
代码管理/PDA/tuniao-ui/libs/function/$parent.js
代码管理/PDA/tuniao-ui/libs/function/array.js
代码管理/PDA/tuniao-ui/libs/function/color.js
代码管理/PDA/tuniao-ui/libs/function/colorUtils.js
代码管理/PDA/tuniao-ui/libs/function/deepClone.js
代码管理/PDA/tuniao-ui/libs/function/message.js
代码管理/PDA/tuniao-ui/libs/function/messageUtils.js
代码管理/PDA/tuniao-ui/libs/function/number.js
代码管理/PDA/tuniao-ui/libs/function/string.js
代码管理/PDA/tuniao-ui/libs/function/test.js
代码管理/PDA/tuniao-ui/libs/function/updateCustomBarInfo.js
代码管理/PDA/tuniao-ui/libs/function/uuid.js
代码管理/PDA/tuniao-ui/libs/mixin/components_color.js
代码管理/PDA/tuniao-ui/libs/mixin/mixin.js
代码管理/PDA/tuniao-ui/libs/mixin/mpShare.js
代码管理/PDA/tuniao-ui/libs/mixin/touch.js
代码管理/PDA/tuniao-ui/libs/utils/area.js
代码管理/PDA/tuniao-ui/libs/utils/async-validator.js
代码管理/PDA/tuniao-ui/libs/utils/calendar.js
代码管理/PDA/tuniao-ui/libs/utils/city.js
代码管理/PDA/tuniao-ui/libs/utils/emitter.js
代码管理/PDA/tuniao-ui/libs/utils/province.js
代码管理/PDA/tuniao-ui/theme.scss
代码管理/PDA/uni.scss
代码管理/PDA/unpackage/cache/apk/__UNI__3B0DA10_cm.apk
代码管理/PDA/unpackage/cache/apk/__UNI__4120374_cm.apk
代码管理/PDA/unpackage/cache/apk/__UNI__F8536D6_cm.apk
代码管理/PDA/unpackage/cache/apk/apkurl
代码管理/PDA/unpackage/cache/certdata
代码管理/PDA/unpackage/cache/cloudcertificate/certini
代码管理/PDA/unpackage/cache/cloudcertificate/package.keystore
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappchooselocation.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniapperror.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappes6.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappopenlocation.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniapppicker.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappquill.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappquillimageresize.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappscan.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappsuccess.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/__uniappview.html
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/app-config-service.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/app-config.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/app-service.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/app-view.js
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/center-selected.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/center.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/favicon.ico
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/index-selected.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/index.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/login_bottom_bg.jpg
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/login_top2.jpg
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/login_top3.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/logo.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/myIcon/1.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/myIcon/2.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/static/myIcon/qiu.png
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/view.css
代码管理/PDA/unpackage/cache/wgt/__UNI__3B0DA10/view.umd.min.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappchooselocation.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniapperror.png
代码管理/PDA/unpackage/dist/build/app-plus/__uniappes6.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappopenlocation.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniapppicker.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappquill.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappquillimageresize.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappscan.js
代码管理/PDA/unpackage/dist/build/app-plus/__uniappsuccess.png
代码管理/PDA/unpackage/dist/build/app-plus/__uniappview.html
代码管理/PDA/unpackage/dist/build/app-plus/app-config-service.js
代码管理/PDA/unpackage/dist/build/app-plus/app-config.js
代码管理/PDA/unpackage/dist/build/app-plus/app-service.js
代码管理/PDA/unpackage/dist/build/app-plus/app-view.js
代码管理/PDA/unpackage/dist/build/app-plus/static/center-selected.png
代码管理/PDA/unpackage/dist/build/app-plus/static/center.png
代码管理/PDA/unpackage/dist/build/app-plus/static/favicon.ico
代码管理/PDA/unpackage/dist/build/app-plus/static/index-selected.png
代码管理/PDA/unpackage/dist/build/app-plus/static/index.png
代码管理/PDA/unpackage/dist/build/app-plus/static/login_bottom_bg.jpg
代码管理/PDA/unpackage/dist/build/app-plus/static/login_top2.jpg
代码管理/PDA/unpackage/dist/build/app-plus/static/login_top3.png
代码管理/PDA/unpackage/dist/build/app-plus/static/logo.png
代码管理/PDA/unpackage/dist/build/app-plus/static/myIcon/1.png
代码管理/PDA/unpackage/dist/build/app-plus/static/myIcon/2.png
代码管理/PDA/unpackage/dist/build/app-plus/static/myIcon/qiu.png
代码管理/PDA/unpackage/dist/build/app-plus/view.css
代码管理/PDA/unpackage/dist/build/app-plus/view.umd.min.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappchooselocation.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniapperror.png
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappes6.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappopenlocation.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniapppicker.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappquill.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappquillimageresize.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappscan.js
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappsuccess.png
代码管理/PDA/unpackage/dist/dev/app-plus/__uniappview.html
代码管理/PDA/unpackage/dist/dev/app-plus/app-config-service.js
代码管理/PDA/unpackage/dist/dev/app-plus/app-config.js
代码管理/PDA/unpackage/dist/dev/app-plus/app-service.js
代码管理/PDA/unpackage/dist/dev/app-plus/app-view.js
代码管理/PDA/unpackage/dist/dev/app-plus/static/center-selected.png
代码管理/PDA/unpackage/dist/dev/app-plus/static/center.png
代码管理/PDA/unpackage/dist/dev/app-plus/static/favicon.ico
代码管理/PDA/unpackage/dist/dev/app-plus/static/index-selected.png
代码管理/PDA/unpackage/dist/dev/app-plus/static/index.png
代码管理/PDA/unpackage/dist/dev/app-plus/static/login_bottom_bg.jpg
代码管理/PDA/unpackage/dist/dev/app-plus/static/login_top2.jpg
代码管理/PDA/unpackage/dist/dev/app-plus/static/login_top3.png
代码管理/PDA/unpackage/dist/dev/app-plus/static/logo.png
代码管理/PDA/unpackage/dist/dev/app-plus/view.css
代码管理/PDA/unpackage/dist/dev/app-plus/view.umd.min.js
代码管理/PDA/unpackage/release/apk/__UNI__3B0DA10__20240304182646.apk
代码管理/PDA/unpackage/release/apk/__UNI__3B0DA10__20240312142901.apk
代码管理/PDA/unpackage/uni_modules/uni-icons/changelog.md
代码管理/PDA/unpackage/uni_modules/uni-icons/components/uni-icons/icons.js
代码管理/PDA/unpackage/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
代码管理/PDA/unpackage/uni_modules/uni-icons/components/uni-icons/uni.ttf
代码管理/PDA/unpackage/uni_modules/uni-icons/readme.md
代码管理/PDA/uview-ui/LICENSE
代码管理/PDA/uview-ui/README.md
代码管理/PDA/uview-ui/components/u-action-sheet/u-action-sheet.vue
代码管理/PDA/uview-ui/components/u-alert-tips/u-alert-tips.vue
代码管理/PDA/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue
代码管理/PDA/uview-ui/components/u-avatar-cropper/weCropper.js
代码管理/PDA/uview-ui/components/u-avatar/u-avatar.vue
代码管理/PDA/uview-ui/components/u-back-top/u-back-top.vue
代码管理/PDA/uview-ui/components/u-badge/u-badge.vue
代码管理/PDA/uview-ui/components/u-button/u-button.vue
代码管理/PDA/uview-ui/components/u-calendar/u-calendar.vue
代码管理/PDA/uview-ui/components/u-car-keyboard/u-car-keyboard.vue
代码管理/PDA/uview-ui/components/u-card/u-card.vue
代码管理/PDA/uview-ui/components/u-cell-group/u-cell-group.vue
代码管理/PDA/uview-ui/components/u-cell-item/u-cell-item.vue
代码管理/PDA/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
代码管理/PDA/uview-ui/components/u-checkbox/u-checkbox.vue
代码管理/PDA/uview-ui/components/u-circle-progress/u-circle-progress.vue
代码管理/PDA/uview-ui/components/u-col/u-col.vue
代码管理/PDA/uview-ui/components/u-collapse-item/u-collapse-item.vue
代码管理/PDA/uview-ui/components/u-collapse/u-collapse.vue
代码管理/PDA/uview-ui/components/u-column-notice/u-column-notice.vue
代码管理/PDA/uview-ui/components/u-count-down/u-count-down.vue
代码管理/PDA/uview-ui/components/u-count-to/u-count-to.vue
代码管理/PDA/uview-ui/components/u-divider/u-divider.vue
代码管理/PDA/uview-ui/components/u-dropdown-item/u-dropdown-item.vue
代码管理/PDA/uview-ui/components/u-dropdown/u-dropdown.vue
代码管理/PDA/uview-ui/components/u-empty/u-empty.vue
代码管理/PDA/uview-ui/components/u-field/u-field.vue
代码管理/PDA/uview-ui/components/u-form-item/u-form-item.vue
代码管理/PDA/uview-ui/components/u-form/u-form.vue
代码管理/PDA/uview-ui/components/u-full-screen/u-full-screen.vue
代码管理/PDA/uview-ui/components/u-gap/u-gap.vue
代码管理/PDA/uview-ui/components/u-grid-item/u-grid-item.vue
代码管理/PDA/uview-ui/components/u-grid/u-grid.vue
代码管理/PDA/uview-ui/components/u-icon/u-icon.vue
代码管理/PDA/uview-ui/components/u-image/u-image.vue
代码管理/PDA/uview-ui/components/u-index-anchor/u-index-anchor.vue
代码管理/PDA/uview-ui/components/u-index-list/u-index-list.vue
代码管理/PDA/uview-ui/components/u-input/u-input.vue
代码管理/PDA/uview-ui/components/u-keyboard/u-keyboard.vue
代码管理/PDA/uview-ui/components/u-lazy-load/u-lazy-load.vue
代码管理/PDA/uview-ui/components/u-line-progress/u-line-progress.vue
代码管理/PDA/uview-ui/components/u-line/u-line.vue
代码管理/PDA/uview-ui/components/u-link/u-link.vue
代码管理/PDA/uview-ui/components/u-loading-page/u-loading-page.vue
代码管理/PDA/uview-ui/components/u-loading/u-loading.vue
代码管理/PDA/uview-ui/components/u-loadmore/u-loadmore.vue
代码管理/PDA/uview-ui/components/u-mask/u-mask.vue
代码管理/PDA/uview-ui/components/u-message-input/u-message-input.vue
代码管理/PDA/uview-ui/components/u-modal/u-modal.vue
代码管理/PDA/uview-ui/components/u-navbar/u-navbar.vue
代码管理/PDA/uview-ui/components/u-no-network/u-no-network.vue
代码管理/PDA/uview-ui/components/u-notice-bar/u-notice-bar.vue
代码管理/PDA/uview-ui/components/u-number-box/u-number-box.vue
代码管理/PDA/uview-ui/components/u-number-keyboard/u-number-keyboard.vue
代码管理/PDA/uview-ui/components/u-parse/libs/CssHandler.js
代码管理/PDA/uview-ui/components/u-parse/libs/MpHtmlParser.js
代码管理/PDA/uview-ui/components/u-parse/libs/config.js
代码管理/PDA/uview-ui/components/u-parse/libs/handler.wxs
代码管理/PDA/uview-ui/components/u-parse/libs/trees.vue
代码管理/PDA/uview-ui/components/u-parse/u-parse.vue
代码管理/PDA/uview-ui/components/u-picker/u-picker.vue
代码管理/PDA/uview-ui/components/u-popup/u-popup.vue
代码管理/PDA/uview-ui/components/u-radio-group/u-radio-group.vue
代码管理/PDA/uview-ui/components/u-radio/u-radio.vue
代码管理/PDA/uview-ui/components/u-rate/u-rate.vue
代码管理/PDA/uview-ui/components/u-read-more/u-read-more.vue
代码管理/PDA/uview-ui/components/u-row-notice/u-row-notice.vue
代码管理/PDA/uview-ui/components/u-row/u-row.vue
代码管理/PDA/uview-ui/components/u-search/u-search.vue
代码管理/PDA/uview-ui/components/u-section/u-section.vue
代码管理/PDA/uview-ui/components/u-select/u-select.vue
代码管理/PDA/uview-ui/components/u-skeleton/u-skeleton.vue
代码管理/PDA/uview-ui/components/u-slider/u-slider.vue
代码管理/PDA/uview-ui/components/u-steps/u-steps.vue
代码管理/PDA/uview-ui/components/u-sticky/u-sticky.vue
代码管理/PDA/uview-ui/components/u-subsection/u-subsection.vue
代码管理/PDA/uview-ui/components/u-swipe-action/u-swipe-action.vue
代码管理/PDA/uview-ui/components/u-swiper/u-swiper.vue
代码管理/PDA/uview-ui/components/u-switch/u-switch.vue
代码管理/PDA/uview-ui/components/u-tabbar/u-tabbar.vue
代码管理/PDA/uview-ui/components/u-table/u-table.vue
代码管理/PDA/uview-ui/components/u-tabs-swiper/u-tabs-swiper.vue
代码管理/PDA/uview-ui/components/u-tabs/u-tabs.vue
代码管理/PDA/uview-ui/components/u-tag/u-tag.vue
代码管理/PDA/uview-ui/components/u-td/u-td.vue
代码管理/PDA/uview-ui/components/u-th/u-th.vue
代码管理/PDA/uview-ui/components/u-time-line-item/u-time-line-item.vue
代码管理/PDA/uview-ui/components/u-time-line/u-time-line.vue
代码管理/PDA/uview-ui/components/u-toast/u-toast.vue
代码管理/PDA/uview-ui/components/u-top-tips/u-top-tips.vue
代码管理/PDA/uview-ui/components/u-tr/u-tr.vue
代码管理/PDA/uview-ui/components/u-upload/u-upload.vue
代码管理/PDA/uview-ui/components/u-verification-code/u-verification-code.vue
代码管理/PDA/uview-ui/components/u-waterfall/u-waterfall.vue
代码管理/PDA/uview-ui/iconfont.css
代码管理/PDA/uview-ui/index.js
代码管理/PDA/uview-ui/index.scss
代码管理/PDA/uview-ui/libs/config/config.js
代码管理/PDA/uview-ui/libs/config/zIndex.js
代码管理/PDA/uview-ui/libs/css/color.scss
代码管理/PDA/uview-ui/libs/css/common.scss
代码管理/PDA/uview-ui/libs/css/style.components.scss
代码管理/PDA/uview-ui/libs/css/style.h5.scss
代码管理/PDA/uview-ui/libs/css/style.mp.scss
代码管理/PDA/uview-ui/libs/css/style.nvue.scss
代码管理/PDA/uview-ui/libs/css/style.vue.scss
代码管理/PDA/uview-ui/libs/function/$parent.js
代码管理/PDA/uview-ui/libs/function/addUnit.js
代码管理/PDA/uview-ui/libs/function/bem.js
代码管理/PDA/uview-ui/libs/function/color.js
代码管理/PDA/uview-ui/libs/function/colorGradient.js
代码管理/PDA/uview-ui/libs/function/debounce.js
代码管理/PDA/uview-ui/libs/function/deepClone.js
代码管理/PDA/uview-ui/libs/function/deepMerge.js
代码管理/PDA/uview-ui/libs/function/getParent.js
代码管理/PDA/uview-ui/libs/function/guid.js
代码管理/PDA/uview-ui/libs/function/md5.js
代码管理/PDA/uview-ui/libs/function/queryParams.js
代码管理/PDA/uview-ui/libs/function/random.js
代码管理/PDA/uview-ui/libs/function/randomArray.js
代码管理/PDA/uview-ui/libs/function/route.js
代码管理/PDA/uview-ui/libs/function/sys.js
代码管理/PDA/uview-ui/libs/function/test.js
代码管理/PDA/uview-ui/libs/function/throttle.js
代码管理/PDA/uview-ui/libs/function/timeFormat.js
代码管理/PDA/uview-ui/libs/function/timeFrom.js
代码管理/PDA/uview-ui/libs/function/toast.js
代码管理/PDA/uview-ui/libs/function/trim.js
代码管理/PDA/uview-ui/libs/function/type2icon.js
代码管理/PDA/uview-ui/libs/mixin/mixin.js
代码管理/PDA/uview-ui/libs/mixin/mpShare.js
代码管理/PDA/uview-ui/libs/request/index.js
代码管理/PDA/uview-ui/libs/store/index.js
代码管理/PDA/uview-ui/libs/util/area.js
代码管理/PDA/uview-ui/libs/util/async-validator.js
代码管理/PDA/uview-ui/libs/util/city.js
代码管理/PDA/uview-ui/libs/util/emitter.js
代码管理/PDA/uview-ui/libs/util/province.js
代码管理/PDA/uview-ui/theme.scss
代码管理/PDA/vue.config.js |