commit 43d87c344c10ccf8329208977aead42512159d4b Author: xpz2018 <107107461@qq.com> Date: Mon Jan 10 18:03:10 2022 +0800 项目初始化 diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a81528 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# zhitongbao-mini + diff --git a/api/axios.js b/api/axios.js new file mode 100644 index 0000000..9ad71fc --- /dev/null +++ b/api/axios.js @@ -0,0 +1,60 @@ +const axios = (function () { + class Axios { + constructor() { + this.defaults = { baseUrl: "" } + this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() } + } + + wxRequest(c) { + return new Promise((resolve, reject) => { + c = this.interceptors.request.func(c) + c.url = c.url.startsWith("http") ? c.url : c.baseUrl + c.url + c.success = (res) => { + resolve(this.interceptors.response.func(res)) + } + // c.enableHttpDNS = true, + // c.httpDNSServiceId = 'wxa410372c837a5f26', + c.fail = (res) => { + reject(this.interceptors.response.func(res)) + } + wx.request(c) + }) + } + } + + Array.prototype.forEach.call(["options", "get", "head", "post", "put", "delete", "trace", "connect"], function (m) { + Axios.prototype[m] = function (url, data, config) { + return this.wxRequest( + merge( this.defaults, { url: url, method: m, data: data }, config || {} ) + ) + } + } + ) + + class InterceptorManager { + constructor() { + this.func = function (data) { + return data + } + } + use(fn) { + this.func = fn + } + } + + function merge(axiosDefaultConfig, data, config) { + let cloneAxios = deepClone(axiosDefaultConfig) + let cloneData = deepClone(data) + let cloneConfig = deepClone(config) + return Object.assign(cloneAxios, cloneData, cloneConfig) + } + + // 深拷贝 + function deepClone(obj) { + let _obj = JSON.stringify(obj), objClone = JSON.parse(_obj) + return objClone + } + return new Axios() +})() + +export default axios \ No newline at end of file diff --git a/api/chain.js b/api/chain.js new file mode 100644 index 0000000..3b7aa1a --- /dev/null +++ b/api/chain.js @@ -0,0 +1,18 @@ +import { mGet, mPost } from "./request" +const app = getApp() +const urls = ['https://api-client-ztb-dev.qniao.cn', 'https://api-client-ztb-test.qniao.cn', 'https://api-client-ztb.qniao.cn'] + +const hconfig = { baseUrl: urls[app.evn] } +// *********************************************************账户业务*********************************************************** +const getUserInfo = (params) => mGet(`/ztb-supply-chain-service/get/user/base-info`, params, hconfig) +const getStoreInfo = (params) => mGet(`/ztb-supply-chain-service/scrap-paper/store/get/by/current-user`, params, hconfig) +const getChainList = (params) => mGet(`/ztb-supply-chain-service/list/scrap-paper/supply-chain/by/store-id`, params, hconfig) +const getIntentById = (shareEventId) => mGet(`/ztb-supply-chain-service/verify/share-event`, {shareEventId}, hconfig) + +export { + hconfig, + getUserInfo, + getStoreInfo, + getChainList, + getIntentById +} \ No newline at end of file diff --git a/api/request.js b/api/request.js new file mode 100644 index 0000000..48c2f7f --- /dev/null +++ b/api/request.js @@ -0,0 +1,208 @@ +/** + * Copyright © 2020-present LiuDanYang. All rights Reserved. + */ + +import axios from "./axios" +const event = require('../utils/event') +const util = require('../utils/util') +const app = getApp() +/** + * axios defaults 配置 + */ +axios.defaults = { + timeout: 60000 +} + +/** + * 全局 请求拦截器, 支持添加多个拦截器 + * 例如: 配置token、添加一些默认的参数 + * `return config` 继续发送请求 + */ +axios.interceptors.request.use( + config => { + config.header = { + ...config.header, + 'X-APP-ID': app.xAppId, + appversion: app.version + } + return config + }, + error => { + // 做一些请求错误 + console.error(error) + return Promise.reject(error) + } +) + +/** + * 全局 响应拦截器, 支持添加多个拦截器 + * 例如: 根据状态码选择性拦截、过滤转换数据 + * @param {Object} res 请求返回的数据 + * @return {Promise} + */ +axios.interceptors.response.use( + async (res) => { + const { data, statusCode: status } = res + try { + return await handleResponse({ data, status }) + } catch (err) { + return Promise.reject(err) + } + }, + (err) => { + // 做一些请求错误 + return Promise.reject(err) + } +) + +/** + * 处理 HTTP 状态码 + * @param data {Object} 请求返回的数据 + * @param status {String} HTTP状态码 + * @returns {Promise|*} + */ +function handleResponse({ data, status }) { + if(!data){ + return Promise.reject('服务器错误') + } + const STATUS = { + "200"() { + if (data.code === 0) { + return Promise.resolve(data) + } + if (data.code === 401 && app.globalData.token) { + app.globalData.token = null + app.userInfo = null + wx.removeStorageSync('Authorization') + event.emit('EventMessage', { what: 888, desc: 'Logout' }) + let pages = getCurrentPages() //当前页面栈 + let prevPage = pages[pages.length - 1] //当前页面 + if (prevPage.route != 'pages/login/index') { + wx.showModal({ + title: '温馨提示', + content: '登录信息已经过期,请重新登录', + showCancel: false, + success: function (res) { + if (res.confirm) { + wx.reLaunch({ url: '/pages/login/index' }) + } + } + }) + } + var message = '' + if (data.message) { + message = data.message + } + return Promise.reject(message) + } + var message = '数据错误' + if (data.message) { + message = data.message + } + return Promise.reject(message) + }, + "400"() { + return Promise.reject('请求错误') + }, + "401"() { + return Promise.reject('请求未授权') + }, + "403"() { + return Promise.reject('拒绝请求') + }, + "404"() { + return Promise.reject('URL错误') + }, + "500"() { + return Promise.reject('服务器错误') + } + } + // 有状态码但不在这个封装的配置里,就直接返回错误 + return STATUS[status] ? STATUS[status]() : Promise.reject('请求错误') +} + +export default axios + +/** + * get 请求方式 + * @param url {String} 接口地址 + * @param params {Object} 接口参数 + * @returns {AxiosPromise} + * @constructor + */ +export function mGet(url, params, config) { + return new Promise((resolve, reject) => { + axios.get(url, params, config).then((res) => { + resolve(res) + }).catch(err => { + reject(err) + }) + }) +} + +/** + * post 请求方式 + * @param url {String} 接口地址 + * @param data {Object} 接口参数 + * @returns {AxiosPromise} + * @constructor + */ +export function mPost(url, data, config) { + return new Promise((resolve, reject) => { + axios.post(url, data, config).then((res) => { + resolve(res) + }).catch((err) => { + reject(err) + }) + }) +} + +/** + * put 请求方式-用于修改全部数据 + * @param url {String} 接口地址 + * @param data {Object} 接口参数 + * @returns {AxiosPromise} + * @constructor + */ +export function mPut(url, data, config) { + return new Promise((resolve, reject) => { + axios.put(url, data, config).then((res) => { + resolve(res) + }).catch((err) => { + reject(err) + }) + }) +} + +/** + * patch 请求方式-用于修改单项或多项数据 + * @param url {String} 接口地址 + * @param data {Object} 接口参数 + * @returns {AxiosPromise} + * @constructor + */ +export function mPatch(url, data, config) { + return new Promise((resolve, reject) => { + axios.patch(url, data, config).then((res) => { + resolve(res) + }).catch((err) => { + reject(err) + }) + }) +} + +/** + * delete 请求方式 + * @param url {String} 接口地址 + * @param params {Object} 接口参数 + * @returns {AxiosPromise} + */ +export function mDelete(url, params, config) { + return new Promise((resolve, reject) => { + axios.delete(url, params, config).then((res) => { + resolve(res) + }).catch((err) => { + reject(err) + }) + }) +} \ No newline at end of file diff --git a/api/user.js b/api/user.js new file mode 100644 index 0000000..daa1e8e --- /dev/null +++ b/api/user.js @@ -0,0 +1,104 @@ +import { mPost } from "./request" +import { zconfig } from "./ztb" +import { hconfig } from "./chain" +const util = require('../utils/util') +const app = getApp() +const urls = ['https://api-client-uec-dev.qniao.cn', 'https://api-client-uec-test.qniao.cn', 'https://api-client-uec.qniao.cn'] + +const config = { + baseUrl: urls[app.evn] +} +const wechatApplet = (params) => mPost('/uec/authorize/by-oauth2', params, config) + +// ********************** 通过微信的方式登录****************************** +// 通过微信的方式登录,onGotPhoneNumber中统一处理/uec/authorize/by-wechat-applet-mobile +function gotPhoneNumber(form, resolve, reject) { + wx.request({ + header: { 'X-APP-ID': app.xAppId }, + url: config.baseUrl + '/uec/authorize/by-wechat-applet-mobile', + data: form, + method: 'POST', + success: function (result) { + // 绑定手机号码,进行登录 + wx.hideLoading() + if (result.data.code != 0) { + util.showToast('登录失败,请稍后再试') + reject('登录失败,请稍后再试') + return + } + result.data.tmpAuthToken = form.tmpAuthToken + resolve(result.data) + }, + fail: function (res) { + wx.hideLoading() + util.showToast('登录失败,请稍后再试') + reject('登录失败,请稍后再试') + } + }) +} + +function phoneWechat(form) { + let promise = new Promise(function (resolve, reject) { + if (!form.encryptedData) { + util.showToast('授权被拒绝,登录失败') + reject('授权被拒绝,登录失败') + return + } + wx.showLoading({ title: '登录中', mask: true }) + // 没有获取到openId,获取之后进行登录 + wx.login({ + success: res => { + // 获取openId + wx.request({ + header: { 'X-APP-ID': app.xAppId }, + url: config.baseUrl + '/uec/authorize/by-oauth2', + data: { authCode: res.code, authMethod: 'WeChatMiniProgram' }, + method: 'POST', + success: function (result) { + if (result.data.code == 0) { + if(result.data.data.tmpAuthToken){ + form.tmpAuthToken = result.data.data.tmpAuthToken + // 获取手机号码 + gotPhoneNumber(form, resolve, reject) + } else if(result.data.data.token){ + wx.hideLoading() + resolve(result.data) + } + } else if (result.data.code == 200101 && result.data.data.tmpAuthToken) { + form.tmpAuthToken = result.data.data.tmpAuthToken + gotPhoneNumber(form, resolve, reject) + } else { + wx.hideLoading() + util.showToast('登录失败,请稍后再试') + reject('登录失败,请稍后再试') + } + }, + fail: function (res) { + wx.hideLoading() + util.showToast('登录失败,请稍后再试') + reject('登录失败,请稍后再试') + } + }) + }, + fail: function (res) { + wx.hideLoading() + util.showToast('登录失败,请稍后再试') + reject('登录失败,请稍后再试') + } + }) + }) + return promise +} + +function finalizeToken(){ + config.header = null + zconfig.header = null + hconfig.header = null +} + +export { + config, + finalizeToken, + wechatApplet, + phoneWechat, +} \ No newline at end of file diff --git a/api/ztb.js b/api/ztb.js new file mode 100644 index 0000000..4022f6f --- /dev/null +++ b/api/ztb.js @@ -0,0 +1,18 @@ +import { mGet, mPost } from "./request" +const app = getApp() +const urls = ['https://api-client-ztb-dev.qniao.cn', 'https://api-client-ztb-test.qniao.cn', 'https://api-client-ztb.qniao.cn'] + +const zconfig = { baseUrl: urls[app.evn] } +// ***************************************************************账户业务*********************************************************** +const loginToken = (params) => mPost(`/ztb-user-enterprise-service/authorize/get/product-line-token/by/login-token`, params, zconfig) +const getStationList = (params) => mGet(`/ztb-user-enterprise-service/get/recently-distance/packing-factory-list`, params, zconfig) +const getStationInfo = (params) => mGet(`/ztb-user-enterprise-service/get/packing-factory-detail`, params, zconfig) +const getPaperList = (params) => mGet(`/recycle-service/get/all-paper-category`, params, zconfig) + +export { + zconfig, + loginToken, + getStationList, + getStationInfo, + getPaperList +} \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..b73ac07 --- /dev/null +++ b/app.js @@ -0,0 +1,76 @@ +App({ + //----------------------------------------------globalData-------------------------------------- + evn: 1,//0:开发环境,1:测试环境,2:生产环境 + version: 152, + xAppId: '503258978847965400', + nowLocation: null, + nowCity: null, + globalData: { + token: null, + kg: 0 + }, + onShow: function(options) { + if (wx.canIUse('getUpdateManager')) { + const updateManager = wx.getUpdateManager() + updateManager.onCheckForUpdate(function (res) { + // 请求完新版本信息的回调 + if (res.hasUpdate) { + updateManager.onUpdateReady(function () { + // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 + updateManager.applyUpdate() + }) + updateManager.onUpdateFailed(function () { + // 新版本下载失败 + wx.showModal({ title: '已有新版本', content: '请您删除小程序,重新搜索进入' }) + }) + } + }) + } else { + wx.showModal({ title: '溫馨提示', content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' }) + } + if(this.globalData.Custom){ + return + } + // this.onShareMessage() + wx.getSystemInfo({ + success: e => { + this.globalData.isIos = this.checkIos(e) + this.globalData.dev = e.platform == 'devtools' + + let custom = wx.getMenuButtonBoundingClientRect() + this.globalData.Custom = custom + // 顶部操作栏高度 + this.globalData.CustomBar = custom.bottom + custom.top - e.statusBarHeight + (this.globalData.isIos ? 4 : 0) + let windowHeight = e.windowHeight * (750 / e.windowWidth) + this.globalData.customHeight = this.globalData.CustomBar * (750 / e.windowWidth) + let safeBottom = e.windowHeight - e.safeArea.bottom + if(safeBottom > e.windowHeight){ + safeBottom = 34 + } + if(this.globalData.isIos){ + this.globalData.safeBottom = safeBottom * (750 / e.windowWidth) + } else { + this.globalData.safeBottom = 0 + } + // 状态栏高度 + this.globalData.StatusBar = e.statusBarHeight * (750 / e.windowWidth) + let statusBarHeight = this.globalData.CustomBar * (750 / e.windowWidth) + this.globalData.statusBarHeight = statusBarHeight + this.globalData.windowHeight = windowHeight + // fragmentHeight:指的是整个页面statusBarHeight以下的高度 + this.globalData.fragmentHeight = windowHeight - statusBarHeight + this.globalData.safeFragmentHeight = windowHeight - statusBarHeight - this.globalData.safeBottom + this.globalData.windowWidth = e.windowWidth + } + }) + }, + checkIos: function (e) { + if ('ios' === e.platform) { + return true + } + if (e.system.startsWith('iOS')) { + return true + } + return false + } +}) \ No newline at end of file diff --git a/app.json b/app.json new file mode 100644 index 0000000..e37e418 --- /dev/null +++ b/app.json @@ -0,0 +1,30 @@ +{ + "pages": [ + "pages/login/index", + "pages/merchant/index", + "pages/station/index", + "pages/process/station-create/index", + "pages/process/order-appointment/index", + "pages/process/order-list/index", + "pages/process/order-info/index", + "pages/process/station-info/index", + "pages/process/store-info/index", + "pages/home/city-select/index", + "pages/html/agreement/index" + ], + "permission": { + "scope.userLocation": { + "desc": "您的位置信息将用于获取您所在城市的最新纸厂和打包站信息。" + } + }, + "window": { + "navigationBarBackgroundColor": "#FFFFFF", + "navigationBarTitleText": "", + "navigationStyle": "custom", + "navigationBarTextStyle": "black" + }, + "usingComponents": { + "cu-custom": "/colorui/components/cu-custom" + }, + "sitemapLocation": "sitemap.json" +} \ No newline at end of file diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..322dba8 --- /dev/null +++ b/app.wxss @@ -0,0 +1,76 @@ +@import "colorui/main.wxss"; +@import "colorui/icon.wxss"; +@import 'components/common/index.wxss'; + +/**app.wxss**/ +.scrollPage { + height: 100vh; +} + +.flex-center { + align-items: center; + justify-content: center; +} + +.flex-column { + -webkit-box-orient: vertical; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.flex-justify { + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.weui_goback { + font-size: 28rpx; + width: 1em; + height: 2em; + -webkit-mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E") no-repeat 50% 50%; + mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E") no-repeat 50% 50%; + -webkit-mask-size: cover; + mask-size: cover; + background-color: currentColor +} + +.weui_goback:active { + opacity: .5 +} + +.solid-bottom, +.solid-bottom::after { + border-bottom: 1rpx solid #f3f3ff; +} + +.wux-close { + width: 100%; + text-align: end; + display: inline-block; + padding-bottom: 24rpx; +} + +.wux-landscape{ + width: 100%; + max-width: 750rpx; +} + +.wux-landscape__popup { + background-color: transparent!important +} + +.wux-landscape__popup-body { + padding: 0!important +} +.wux-landscape__inner { + line-height: 1.5; + color: rgba(0,0,0,.65) +} +.wux-landscape__inner > image { + width: 100%; + max-width: 100% +} \ No newline at end of file diff --git a/assets/icon/address.png b/assets/icon/address.png new file mode 100644 index 0000000..faa2412 Binary files /dev/null and b/assets/icon/address.png differ diff --git a/assets/icon/home-blue.png b/assets/icon/home-blue.png new file mode 100644 index 0000000..6f52f91 Binary files /dev/null and b/assets/icon/home-blue.png differ diff --git a/assets/icon/home-gray.png b/assets/icon/home-gray.png new file mode 100644 index 0000000..221f47c Binary files /dev/null and b/assets/icon/home-gray.png differ diff --git a/assets/icon/mall-blue.png b/assets/icon/mall-blue.png new file mode 100644 index 0000000..b6a2072 Binary files /dev/null and b/assets/icon/mall-blue.png differ diff --git a/assets/icon/mall-gray.png b/assets/icon/mall-gray.png new file mode 100644 index 0000000..b45d0ed Binary files /dev/null and b/assets/icon/mall-gray.png differ diff --git a/assets/icon/phone.png b/assets/icon/phone.png new file mode 100644 index 0000000..80b435f Binary files /dev/null and b/assets/icon/phone.png differ diff --git a/assets/icon/storage-blue.png b/assets/icon/storage-blue.png new file mode 100644 index 0000000..7323cfd Binary files /dev/null and b/assets/icon/storage-blue.png differ diff --git a/assets/icon/storage-gray.png b/assets/icon/storage-gray.png new file mode 100644 index 0000000..bc8f671 Binary files /dev/null and b/assets/icon/storage-gray.png differ diff --git a/assets/icon/store-blue.png b/assets/icon/store-blue.png new file mode 100644 index 0000000..ce68dc0 Binary files /dev/null and b/assets/icon/store-blue.png differ diff --git a/assets/icon/store-gray.png b/assets/icon/store-gray.png new file mode 100644 index 0000000..85a1c5e Binary files /dev/null and b/assets/icon/store-gray.png differ diff --git a/assets/image/def_image.png b/assets/image/def_image.png new file mode 100644 index 0000000..d1e6bfe Binary files /dev/null and b/assets/image/def_image.png differ diff --git a/assets/image/icon-dbz-label.png b/assets/image/icon-dbz-label.png new file mode 100644 index 0000000..7da6dbe Binary files /dev/null and b/assets/image/icon-dbz-label.png differ diff --git a/assets/image/icon-search.png b/assets/image/icon-search.png new file mode 100644 index 0000000..2bff1fd Binary files /dev/null and b/assets/image/icon-search.png differ diff --git a/assets/image/icon_logo.png b/assets/image/icon_logo.png new file mode 100644 index 0000000..01a6ef6 Binary files /dev/null and b/assets/image/icon_logo.png differ diff --git a/assets/image/list_empty.png b/assets/image/list_empty.png new file mode 100644 index 0000000..1b8e9ac Binary files /dev/null and b/assets/image/list_empty.png differ diff --git a/assets/image/order-check-icon.png b/assets/image/order-check-icon.png new file mode 100644 index 0000000..9d037a5 Binary files /dev/null and b/assets/image/order-check-icon.png differ diff --git a/assets/image/proxy-icon.png b/assets/image/proxy-icon.png new file mode 100644 index 0000000..b45b7d3 Binary files /dev/null and b/assets/image/proxy-icon.png differ diff --git a/assets/image/reconciliation-icon.png b/assets/image/reconciliation-icon.png new file mode 100644 index 0000000..3ddd907 Binary files /dev/null and b/assets/image/reconciliation-icon.png differ diff --git a/assets/image/supplier-icon.png b/assets/image/supplier-icon.png new file mode 100644 index 0000000..85d74b1 Binary files /dev/null and b/assets/image/supplier-icon.png differ diff --git a/assets/image/toggle-icon.png b/assets/image/toggle-icon.png new file mode 100644 index 0000000..90fc1f6 Binary files /dev/null and b/assets/image/toggle-icon.png differ diff --git a/assets/image/ygImg.png b/assets/image/ygImg.png new file mode 100644 index 0000000..cdb5133 Binary files /dev/null and b/assets/image/ygImg.png differ diff --git a/assets/raw/ding.mp3 b/assets/raw/ding.mp3 new file mode 100644 index 0000000..19dc907 Binary files /dev/null and b/assets/raw/ding.mp3 differ diff --git a/colorui/components/cu-custom.js b/colorui/components/cu-custom.js new file mode 100644 index 0000000..a8f619e --- /dev/null +++ b/colorui/components/cu-custom.js @@ -0,0 +1,100 @@ +const event = require('../../utils/event') +const app = getApp() + +Component({ + /** + * 组件的一些选项 + */ + options: { + addGlobalClass: true, + multipleSlots: true + }, + /** + * 组件的对外属性 + */ + properties: { + bgColor: { + type: String, + default: '' + }, + isCustom: { + type: [Boolean, String], + default: false + }, + isBack: { + type: [Boolean, String], + default: false + }, + shadow: { + type: Boolean, + default: false + }, + intercept: { + type: Boolean, + default: false + }, + bgImage: { + type: String, + default: '' + } + }, + /** + * 组件的初始数据 + */ + data: { + StatusBar: app.globalData.StatusBar, + CustomBar: app.globalData.CustomBar, + Custom: app.globalData.Custom + }, + lifetimes: { + // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 + attached: function () { + if(app.globalData.Custom){ + this.setData({ + StatusBar: app.globalData.StatusBar || 40, + CustomBar: app.globalData.CustomBar || (app.globalData.isIos ? 64 : 60), + Custom: app.globalData.Custom + }) + } else { + event.on('InitMessage', this, this.onEvent) + } + }, + detached: function(){ + if(!app.globalData.Custom){ + event.remove('InitMessage', this) + } + } + }, + /** + * 组件的方法列表 + */ + methods: { + backspace() { + if (this.data.intercept) { + this.triggerEvent('customevent', null) + return + } + if (getCurrentPages().length == 1) { + this.toHome() + } else { + wx.navigateBack() + } + }, + onEvent: function(message){ + if (message.what == 8) { + this.setData({ + StatusBar: app.globalData.StatusBar || 40, + CustomBar: app.globalData.CustomBar || (app.globalData.isIos ? 64 : 80), + Custom: app.globalData.Custom + }) + } + }, + toHome() { + if (app.userInfo && app.userInfo.userId) { + wx.redirectTo({ url: '/pages/index/index' }) + } else { + wx.reLaunch({ url: '/pages/login/index' }) + } + } + } +}) \ No newline at end of file diff --git a/colorui/components/cu-custom.json b/colorui/components/cu-custom.json new file mode 100644 index 0000000..e8cfaaf --- /dev/null +++ b/colorui/components/cu-custom.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/colorui/components/cu-custom.wxml b/colorui/components/cu-custom.wxml new file mode 100644 index 0000000..e2f4ac0 --- /dev/null +++ b/colorui/components/cu-custom.wxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/colorui/components/cu-custom.wxss b/colorui/components/cu-custom.wxss new file mode 100644 index 0000000..82e835e --- /dev/null +++ b/colorui/components/cu-custom.wxss @@ -0,0 +1,5 @@ +/* colorui/components/cu-custom.wxss */ +.shadow{ + box-shadow: 0 0rpx 0rpx rgba(0, 0, 0, 0.04) +} + \ No newline at end of file diff --git a/colorui/icon.wxss b/colorui/icon.wxss new file mode 100644 index 0000000..e19a7bb --- /dev/null +++ b/colorui/icon.wxss @@ -0,0 +1,1226 @@ +@keyframes cuIcon-spin { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.iconfont-spin { + -webkit-animation: cuIcon-spin 2s infinite linear; + animation: cuIcon-spin 2s infinite linear; + display: inline-block; +} + +.iconfont-pulse { + -webkit-animation: cuIcon-spin 1s infinite steps(8); + animation: cuIcon-spin 1s infinite steps(8); + display: inline-block; +} + +[class*="cuIcon-"] { + font-family: "cuIcon"; + font-size: inherit; + font-style: normal; +} + +@font-face { + font-family: "cuIcon"; + src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831'); + /* IE9*/ + src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), + url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'), + /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#iconfont') format('svg'); + /* iOS 4.1- */ +} + +.cuIcon-appreciate:before { + content: "\e644"; +} + +.cuIcon-check:before { + content: "\e645"; +} + +.cuIcon-close:before { + content: "\e646"; +} + +.cuIcon-edit:before { + content: "\e649"; +} + +.cuIcon-emoji:before { + content: "\e64a"; +} + +.cuIcon-favorfill:before { + content: "\e64b"; +} + +.cuIcon-favor:before { + content: "\e64c"; +} + +.cuIcon-loading:before { + content: "\e64f"; +} + +.cuIcon-locationfill:before { + content: "\e650"; +} + +.cuIcon-location:before { + content: "\e651"; +} + +.cuIcon-phone:before { + content: "\e652"; +} + +.cuIcon-roundcheckfill:before { + content: "\e656"; +} + +.cuIcon-roundcheck:before { + content: "\e657"; +} + +.cuIcon-roundclosefill:before { + content: "\e658"; +} + +.cuIcon-roundclose:before { + content: "\e659"; +} + +.cuIcon-roundrightfill:before { + content: "\e65a"; +} + +.cuIcon-roundright:before { + content: "\e65b"; +} + +.cuIcon-search:before { + content: "\e65c"; +} + +.cuIcon-taxi:before { + content: "\e65d"; +} + +.cuIcon-timefill:before { + content: "\e65e"; +} + +.cuIcon-time:before { + content: "\e65f"; +} + +.cuIcon-unfold:before { + content: "\e661"; +} + +.cuIcon-warnfill:before { + content: "\e662"; +} + +.cuIcon-warn:before { + content: "\e663"; +} + +.cuIcon-camerafill:before { + content: "\e664"; +} + +.cuIcon-camera:before { + content: "\e665"; +} + +.cuIcon-commentfill:before { + content: "\e666"; +} + +.cuIcon-comment:before { + content: "\e667"; +} + +.cuIcon-likefill:before { + content: "\e668"; +} + +.cuIcon-like:before { + content: "\e669"; +} + +.cuIcon-notificationfill:before { + content: "\e66a"; +} + +.cuIcon-notification:before { + content: "\e66b"; +} + +.cuIcon-order:before { + content: "\e66c"; +} + +.cuIcon-samefill:before { + content: "\e66d"; +} + +.cuIcon-same:before { + content: "\e66e"; +} + +.cuIcon-deliver:before { + content: "\e671"; +} + +.cuIcon-evaluate:before { + content: "\e672"; +} + +.cuIcon-pay:before { + content: "\e673"; +} + +.cuIcon-send:before { + content: "\e675"; +} + +.cuIcon-shop:before { + content: "\e676"; +} + +.cuIcon-ticket:before { + content: "\e677"; +} + +.cuIcon-back:before { + content: "\e679"; +} + +.cuIcon-cascades:before { + content: "\e67c"; +} + +.cuIcon-discover:before { + content: "\e67e"; +} + +.cuIcon-list:before { + content: "\e682"; +} + +.cuIcon-more:before { + content: "\e684"; +} + +.cuIcon-scan:before { + content: "\e689"; +} + +.cuIcon-settings:before { + content: "\e68a"; +} + +.cuIcon-questionfill:before { + content: "\e690"; +} + +.cuIcon-question:before { + content: "\e691"; +} + +.cuIcon-shopfill:before { + content: "\e697"; +} + +.cuIcon-form:before { + content: "\e699"; +} + +.cuIcon-pic:before { + content: "\e69b"; +} + +.cuIcon-filter:before { + content: "\e69c"; +} + +.cuIcon-footprint:before { + content: "\e69d"; +} + +.cuIcon-top:before { + content: "\e69e"; +} + +.cuIcon-pulldown:before { + content: "\e69f"; +} + +.cuIcon-pullup:before { + content: "\e6a0"; +} + +.cuIcon-right:before { + content: "\e6a3"; +} + +.cuIcon-refresh:before { + content: "\e6a4"; +} + +.cuIcon-moreandroid:before { + content: "\e6a5"; +} + +.cuIcon-deletefill:before { + content: "\e6a6"; +} + +.cuIcon-refund:before { + content: "\e6ac"; +} + +.cuIcon-cart:before { + content: "\e6af"; +} + +.cuIcon-qrcode:before { + content: "\e6b0"; +} + +.cuIcon-remind:before { + content: "\e6b2"; +} + +.cuIcon-delete:before { + content: "\e6b4"; +} + +.cuIcon-profile:before { + content: "\e6b7"; +} + +.cuIcon-home:before { + content: "\e6b8"; +} + +.cuIcon-cartfill:before { + content: "\e6b9"; +} + +.cuIcon-discoverfill:before { + content: "\e6ba"; +} + +.cuIcon-homefill:before { + content: "\e6bb"; +} + +.cuIcon-message:before { + content: "\e6bc"; +} + +.cuIcon-addressbook:before { + content: "\e6bd"; +} + +.cuIcon-link:before { + content: "\e6bf"; +} + +.cuIcon-lock:before { + content: "\e6c0"; +} + +.cuIcon-unlock:before { + content: "\e6c2"; +} + +.cuIcon-vip:before { + content: "\e6c3"; +} + +.cuIcon-weibo:before { + content: "\e6c4"; +} + +.cuIcon-activity:before { + content: "\e6c5"; +} + +.cuIcon-friendaddfill:before { + content: "\e6c9"; +} + +.cuIcon-friendadd:before { + content: "\e6ca"; +} + +.cuIcon-friendfamous:before { + content: "\e6cb"; +} + +.cuIcon-friend:before { + content: "\e6cc"; +} + +.cuIcon-goods:before { + content: "\e6cd"; +} + +.cuIcon-selection:before { + content: "\e6ce"; +} + +.cuIcon-explore:before { + content: "\e6d2"; +} + +.cuIcon-present:before { + content: "\e6d3"; +} + +.cuIcon-squarecheckfill:before { + content: "\e6d4"; +} + +.cuIcon-square:before { + content: "\e6d5"; +} + +.cuIcon-squarecheck:before { + content: "\e6d6"; +} + +.cuIcon-round:before { + content: "\e6d7"; +} + +.cuIcon-roundaddfill:before { + content: "\e6d8"; +} + +.cuIcon-roundadd:before { + content: "\e6d9"; +} + +.cuIcon-add:before { + content: "\e6da"; +} + +.cuIcon-notificationforbidfill:before { + content: "\e6db"; +} + +.cuIcon-explorefill:before { + content: "\e6dd"; +} + +.cuIcon-fold:before { + content: "\e6de"; +} + +.cuIcon-game:before { + content: "\e6df"; +} + +.cuIcon-redpacket:before { + content: "\e6e0"; +} + +.cuIcon-selectionfill:before { + content: "\e6e1"; +} + +.cuIcon-similar:before { + content: "\e6e2"; +} + +.cuIcon-appreciatefill:before { + content: "\e6e3"; +} + +.cuIcon-infofill:before { + content: "\e6e4"; +} + +.cuIcon-info:before { + content: "\e6e5"; +} + +.cuIcon-forwardfill:before { + content: "\e6ea"; +} + +.cuIcon-forward:before { + content: "\e6eb"; +} + +.cuIcon-rechargefill:before { + content: "\e6ec"; +} + +.cuIcon-recharge:before { + content: "\e6ed"; +} + +.cuIcon-vipcard:before { + content: "\e6ee"; +} + +.cuIcon-voice:before { + content: "\e6ef"; +} + +.cuIcon-voicefill:before { + content: "\e6f0"; +} + +.cuIcon-friendfavor:before { + content: "\e6f1"; +} + +.cuIcon-wifi:before { + content: "\e6f2"; +} + +.cuIcon-share:before { + content: "\e6f3"; +} + +.cuIcon-wefill:before { + content: "\e6f4"; +} + +.cuIcon-we:before { + content: "\e6f5"; +} + +.cuIcon-lightauto:before { + content: "\e6f6"; +} + +.cuIcon-lightforbid:before { + content: "\e6f7"; +} + +.cuIcon-lightfill:before { + content: "\e6f8"; +} + +.cuIcon-camerarotate:before { + content: "\e6f9"; +} + +.cuIcon-light:before { + content: "\e6fa"; +} + +.cuIcon-barcode:before { + content: "\e6fb"; +} + +.cuIcon-flashlightclose:before { + content: "\e6fc"; +} + +.cuIcon-flashlightopen:before { + content: "\e6fd"; +} + +.cuIcon-searchlist:before { + content: "\e6fe"; +} + +.cuIcon-service:before { + content: "\e6ff"; +} + +.cuIcon-sort:before { + content: "\e700"; +} + +.cuIcon-down:before { + content: "\e703"; +} + +.cuIcon-mobile:before { + content: "\e704"; +} + +.cuIcon-mobilefill:before { + content: "\e705"; +} + +.cuIcon-copy:before { + content: "\e706"; +} + +.cuIcon-countdownfill:before { + content: "\e707"; +} + +.cuIcon-countdown:before { + content: "\e708"; +} + +.cuIcon-noticefill:before { + content: "\e709"; +} + +.cuIcon-notice:before { + content: "\e70a"; +} + +.cuIcon-upstagefill:before { + content: "\e70e"; +} + +.cuIcon-upstage:before { + content: "\e70f"; +} + +.cuIcon-babyfill:before { + content: "\e710"; +} + +.cuIcon-baby:before { + content: "\e711"; +} + +.cuIcon-brandfill:before { + content: "\e712"; +} + +.cuIcon-brand:before { + content: "\e713"; +} + +.cuIcon-choicenessfill:before { + content: "\e714"; +} + +.cuIcon-choiceness:before { + content: "\e715"; +} + +.cuIcon-clothesfill:before { + content: "\e716"; +} + +.cuIcon-clothes:before { + content: "\e717"; +} + +.cuIcon-creativefill:before { + content: "\e718"; +} + +.cuIcon-creative:before { + content: "\e719"; +} + +.cuIcon-female:before { + content: "\e71a"; +} + +.cuIcon-keyboard:before { + content: "\e71b"; +} + +.cuIcon-male:before { + content: "\e71c"; +} + +.cuIcon-newfill:before { + content: "\e71d"; +} + +.cuIcon-new:before { + content: "\e71e"; +} + +.cuIcon-pullleft:before { + content: "\e71f"; +} + +.cuIcon-pullright:before { + content: "\e720"; +} + +.cuIcon-rankfill:before { + content: "\e721"; +} + +.cuIcon-rank:before { + content: "\e722"; +} + +.cuIcon-bad:before { + content: "\e723"; +} + +.cuIcon-cameraadd:before { + content: "\e724"; +} + +.cuIcon-focus:before { + content: "\e725"; +} + +.cuIcon-friendfill:before { + content: "\e726"; +} + +.cuIcon-cameraaddfill:before { + content: "\e727"; +} + +.cuIcon-apps:before { + content: "\e729"; +} + +.cuIcon-paintfill:before { + content: "\e72a"; +} + +.cuIcon-paint:before { + content: "\e72b"; +} + +.cuIcon-picfill:before { + content: "\e72c"; +} + +.cuIcon-refresharrow:before { + content: "\e72d"; +} + +.cuIcon-colorlens:before { + content: "\e6e6"; +} + +.cuIcon-markfill:before { + content: "\e730"; +} + +.cuIcon-mark:before { + content: "\e731"; +} + +.cuIcon-presentfill:before { + content: "\e732"; +} + +.cuIcon-repeal:before { + content: "\e733"; +} + +.cuIcon-album:before { + content: "\e734"; +} + +.cuIcon-peoplefill:before { + content: "\e735"; +} + +.cuIcon-people:before { + content: "\e736"; +} + +.cuIcon-servicefill:before { + content: "\e737"; +} + +.cuIcon-repair:before { + content: "\e738"; +} + +.cuIcon-file:before { + content: "\e739"; +} + +.cuIcon-repairfill:before { + content: "\e73a"; +} + +.cuIcon-taoxiaopu:before { + content: "\e73b"; +} + +.cuIcon-weixin:before { + content: "\e612"; +} + +.cuIcon-attentionfill:before { + content: "\e73c"; +} + +.cuIcon-attention:before { + content: "\e73d"; +} + +.cuIcon-commandfill:before { + content: "\e73e"; +} + +.cuIcon-command:before { + content: "\e73f"; +} + +.cuIcon-communityfill:before { + content: "\e740"; +} + +.cuIcon-community:before { + content: "\e741"; +} + +.cuIcon-read:before { + content: "\e742"; +} + +.cuIcon-calendar:before { + content: "\e74a"; +} + +.cuIcon-cut:before { + content: "\e74b"; +} + +.cuIcon-magic:before { + content: "\e74c"; +} + +.cuIcon-backwardfill:before { + content: "\e74d"; +} + +.cuIcon-playfill:before { + content: "\e74f"; +} + +.cuIcon-stop:before { + content: "\e750"; +} + +.cuIcon-tagfill:before { + content: "\e751"; +} + +.cuIcon-tag:before { + content: "\e752"; +} + +.cuIcon-group:before { + content: "\e753"; +} + +.cuIcon-all:before { + content: "\e755"; +} + +.cuIcon-backdelete:before { + content: "\e756"; +} + +.cuIcon-hotfill:before { + content: "\e757"; +} + +.cuIcon-hot:before { + content: "\e758"; +} + +.cuIcon-post:before { + content: "\e759"; +} + +.cuIcon-radiobox:before { + content: "\e75b"; +} + +.cuIcon-rounddown:before { + content: "\e75c"; +} + +.cuIcon-upload:before { + content: "\e75d"; +} + +.cuIcon-writefill:before { + content: "\e760"; +} + +.cuIcon-write:before { + content: "\e761"; +} + +.cuIcon-radioboxfill:before { + content: "\e763"; +} + +.cuIcon-punch:before { + content: "\e764"; +} + +.cuIcon-shake:before { + content: "\e765"; +} + +.cuIcon-move:before { + content: "\e768"; +} + +.cuIcon-safe:before { + content: "\e769"; +} + +.cuIcon-activityfill:before { + content: "\e775"; +} + +.cuIcon-crownfill:before { + content: "\e776"; +} + +.cuIcon-crown:before { + content: "\e777"; +} + +.cuIcon-goodsfill:before { + content: "\e778"; +} + +.cuIcon-messagefill:before { + content: "\e779"; +} + +.cuIcon-profilefill:before { + content: "\e77a"; +} + +.cuIcon-sound:before { + content: "\e77b"; +} + +.cuIcon-sponsorfill:before { + content: "\e77c"; +} + +.cuIcon-sponsor:before { + content: "\e77d"; +} + +.cuIcon-upblock:before { + content: "\e77e"; +} + +.cuIcon-weblock:before { + content: "\e77f"; +} + +.cuIcon-weunblock:before { + content: "\e780"; +} + +.cuIcon-my:before { + content: "\e78b"; +} + +.cuIcon-myfill:before { + content: "\e78c"; +} + +.cuIcon-emojifill:before { + content: "\e78d"; +} + +.cuIcon-emojiflashfill:before { + content: "\e78e"; +} + +.cuIcon-flashbuyfill:before { + content: "\e78f"; +} + +.cuIcon-text:before { + content: "\e791"; +} + +.cuIcon-goodsfavor:before { + content: "\e794"; +} + +.cuIcon-musicfill:before { + content: "\e795"; +} + +.cuIcon-musicforbidfill:before { + content: "\e796"; +} + +.cuIcon-card:before { + content: "\e624"; +} + +.cuIcon-triangledownfill:before { + content: "\e79b"; +} + +.cuIcon-triangleupfill:before { + content: "\e79c"; +} + +.cuIcon-roundleftfill-copy:before { + content: "\e79e"; +} + +.cuIcon-font:before { + content: "\e76a"; +} + +.cuIcon-title:before { + content: "\e82f"; +} + +.cuIcon-recordfill:before { + content: "\e7a4"; +} + +.cuIcon-record:before { + content: "\e7a6"; +} + +.cuIcon-cardboardfill:before { + content: "\e7a9"; +} + +.cuIcon-cardboard:before { + content: "\e7aa"; +} + +.cuIcon-formfill:before { + content: "\e7ab"; +} + +.cuIcon-coin:before { + content: "\e7ac"; +} + +.cuIcon-cardboardforbid:before { + content: "\e7af"; +} + +.cuIcon-circlefill:before { + content: "\e7b0"; +} + +.cuIcon-circle:before { + content: "\e7b1"; +} + +.cuIcon-attentionforbid:before { + content: "\e7b2"; +} + +.cuIcon-attentionforbidfill:before { + content: "\e7b3"; +} + +.cuIcon-attentionfavorfill:before { + content: "\e7b4"; +} + +.cuIcon-attentionfavor:before { + content: "\e7b5"; +} + +.cuIcon-titles:before { + content: "\e701"; +} + +.cuIcon-icloading:before { + content: "\e67a"; +} + +.cuIcon-full:before { + content: "\e7bc"; +} + +.cuIcon-mail:before { + content: "\e7bd"; +} + +.cuIcon-peoplelist:before { + content: "\e7be"; +} + +.cuIcon-goodsnewfill:before { + content: "\e7bf"; +} + +.cuIcon-goodsnew:before { + content: "\e7c0"; +} + +.cuIcon-medalfill:before { + content: "\e7c1"; +} + +.cuIcon-medal:before { + content: "\e7c2"; +} + +.cuIcon-newsfill:before { + content: "\e7c3"; +} + +.cuIcon-newshotfill:before { + content: "\e7c4"; +} + +.cuIcon-newshot:before { + content: "\e7c5"; +} + +.cuIcon-news:before { + content: "\e7c6"; +} + +.cuIcon-videofill:before { + content: "\e7c7"; +} + +.cuIcon-video:before { + content: "\e7c8"; +} + +.cuIcon-exit:before { + content: "\e7cb"; +} + +.cuIcon-skinfill:before { + content: "\e7cc"; +} + +.cuIcon-skin:before { + content: "\e7cd"; +} + +.cuIcon-moneybagfill:before { + content: "\e7ce"; +} + +.cuIcon-usefullfill:before { + content: "\e7cf"; +} + +.cuIcon-usefull:before { + content: "\e7d0"; +} + +.cuIcon-moneybag:before { + content: "\e7d1"; +} + +.cuIcon-redpacket_fill:before { + content: "\e7d3"; +} + +.cuIcon-subscription:before { + content: "\e7d4"; +} + +.cuIcon-loading1:before { + content: "\e633"; +} + +.cuIcon-github:before { + content: "\e692"; +} + +.cuIcon-global:before { + content: "\e7eb"; +} + +.cuIcon-settingsfill:before { + content: "\e6ab"; +} + +.cuIcon-back_android:before { + content: "\e7ed"; +} + +.cuIcon-expressman:before { + content: "\e7ef"; +} + +.cuIcon-evaluate_fill:before { + content: "\e7f0"; +} + +.cuIcon-group_fill:before { + content: "\e7f5"; +} + +.cuIcon-play_forward_fill:before { + content: "\e7f6"; +} + +.cuIcon-deliver_fill:before { + content: "\e7f7"; +} + +.cuIcon-notice_forbid_fill:before { + content: "\e7f8"; +} + +.cuIcon-fork:before { + content: "\e60c"; +} + +.cuIcon-pick:before { + content: "\e7fa"; +} + +.cuIcon-wenzi:before { + content: "\e6a7"; +} + +.cuIcon-ellipse:before { + content: "\e600"; +} + +.cuIcon-qr_code:before { + content: "\e61b"; +} + +.cuIcon-dianhua:before { + content: "\e64d"; +} + +.cuIcon-icon:before { + content: "\e602"; +} + +.cuIcon-loading2:before { + content: "\e7f1"; +} + +.cuIcon-btn:before { + content: "\e601"; +} diff --git a/colorui/main.wxss b/colorui/main.wxss new file mode 100644 index 0000000..5e4959c --- /dev/null +++ b/colorui/main.wxss @@ -0,0 +1,1129 @@ +/* + ColorUi for MP-weixin v2.1.4 | by 文晓港 2019年4月25日19:15:42 + 仅供学习交流,如作它用所承受的法律责任一概与作者无关 + 使用ColorUi开发扩展与插件时,请注明基于ColorUi开发 + + (QQ交流群:240787041) +*/ + +/* ================== + 初始化 + ==================== */ + +page { + /* Color 可以自定义相关配色 *//* var属性兼容性 --> https://www.caniuse.com/#feat=css-variables *//* 标准色 */ + --red: #e54d42; + --orange: #f37b1d; + --yellow: #fbbd08; + --olive: #8dc63f; + --green: #39b54a; + --cyan: #1cbbb4; + --blue: #008AFF; + --purple: #6739b6; + --mauve: #9c26b0; + --pink: #e03997; + --brown: #a5673f; + --grey: #8799a3; + --black: #333; + --darkGray: #666; + --gray: #aaa; + --ghostWhite: #f1f1f1; + --white: #fff; + /* 浅色 */ + --redLight: #fadbd9; + --orangeLight: #fde6d2; + --yellowLight: #fef2ce; + --oliveLight: #e8f4d9; + --greenLight: #d7f0db; + --cyanLight: #d2f1f0; + --blueLight: #cce6ff; + --purpleLight: #e1d7f0; + --mauveLight: #ebd4ef; + --pinkLight: #f9d7ea; + --brownLight: #ede1d9; + --greyLight: #e7ebed; + /* 渐变色 */ + --gradualRed: linear-gradient(45deg, #f43f3b, #ec008c); + --gradualOrange: linear-gradient(45deg, #ff9700, #ed1c24); + --gradualGreen: linear-gradient(45deg, #39b54a, #8dc63f); + --gradualPurple: linear-gradient(45deg, #9000ff, #5e00ff); + --gradualPink: linear-gradient(45deg, #ec008c, #6739b6); + --gradualBlue: linear-gradient(45deg, #009ee0, #009ee0); + /* 阴影透明色 */ + --ShadowSize: 6rpx 6rpx 8rpx; + --redShadow: rgba(204, 69, 59, 0.2); + --orangeShadow: rgba(217, 109, 26, 0.2); + --yellowShadow: rgba(224, 170, 7, 0.2); + --oliveShadow: rgba(124, 173, 55, 0.2); + --greenShadow: rgba(48, 156, 63, 0.2); + --cyanShadow: rgba(28, 187, 180, 0.2); + --blueShadow: rgba(0, 102, 204, 0.2); + --purpleShadow: rgba(88, 48, 156, 0.2); + --mauveShadow: rgba(133, 33, 150, 0.2); + --pinkShadow: rgba(199, 50, 134, 0.2); + --brownShadow: rgba(140, 88, 53, 0.2); + --greyShadow: rgba(114, 130, 138, 0.2); + --grayShadow: rgba(114, 130, 138, 0.2); + --blackShadow: rgba(26, 26, 26, 0.2); + background-color: var(--ghostWhite); + font-size: 28rpx; + color: var(--black); + font-family: Helvetica Neue, Helvetica, sans-serif; +} + +view, scroll-view, swiper, button, input, textarea, label, navigator, image { + box-sizing: border-box; +} + +.round { + border-radius: 5000rpx; +} + +.radius { + border-radius: 6rpx; +} + +.bg-white{ + background-color: white; +} + +.bg-blue{ + background: linear-gradient(127deg, rgba(0,122,255) 0%, rgba(13,100,227) 100%); +} + +/* ================== + 头像 + ==================== */ + +.cu-avatar { + font-variant: small-caps; + margin: 0; + padding: 0; + display: inline-flex; + text-align: center; + justify-content: center; + align-items: center; + background-color: #ccc; + color: var(--white); + white-space: nowrap; + position: relative; + width: 64rpx; + height: 64rpx; + background-size: cover; + background-position: center; + vertical-align: middle; + font-size: 1.5em; +} + +.cu-avatar.sm { + width: 48rpx; + height: 48rpx; + font-size: 1em; +} + +.cu-avatar.lg { + width: 96rpx; + height: 96rpx; + font-size: 2em; +} + +.cu-avatar.slg { + width: 60rpx; + height: 60rpx; + font-size: 2em; +} + +.cu-avatar.xl { + width: 128rpx; + height: 128rpx; + font-size: 2.5em; +} + +.cu-avatar .avatar-text { + font-size: 0.4em; +} + +.cu-avatar-group { + direction: rtl; + unicode-bidi: bidi-override; + padding: 0 10rpx 0 40rpx; + display: inline-block; +} + +.cu-avatar-group .cu-avatar { + margin-left: -30rpx; + border: 4rpx solid var(--ghostWhite); + vertical-align: middle; +} + +.cu-avatar-group .cu-avatar.sm { + margin-left: -20rpx; + border: 1rpx solid var(--ghostWhite); +} + +/* ================== + 操作条 + ==================== */ + +.cu-bar { + display: flex; + position: relative; + align-items: center; + min-height: 100rpx; + justify-content: space-between; +} + +.cu-bar .action { + display: flex; + align-items: center; + height: 100%; + justify-content: center; + max-width: 100%; +} + +.cu-bar .action.border-title { + position: relative; + top: -10rpx; +} + +.cu-bar .action.border-title text[class*="bg-"]:last-child { + position: absolute; + bottom: -0.5rem; + min-width: 2rem; + height: 6rpx; + left: 0; +} + +.cu-bar .action.sub-title { + position: relative; + top: -0.2rem; +} + +.cu-bar .action.sub-title text { + position: relative; + z-index: 1; +} + +.cu-bar .action.sub-title text[class*="bg-"]:last-child { + position: absolute; + display: inline-block; + bottom: -0.2rem; + border-radius: 6rpx; + width: 100%; + height: 0.6rem; + left: 0.6rem; + opacity: 0.3; + z-index: 0; +} + +.cu-bar .action.sub-title text[class*="text-"]:last-child { + position: absolute; + display: inline-block; + bottom: -0.7rem; + left: 0.5rem; + opacity: 0.2; + z-index: 0; + text-align: right; + font-weight: 900; + font-size: 36rpx; +} + +.cu-bar.justify-center .action.border-title text:last-child, +.cu-bar.justify-center .action.sub-title text:last-child { + left: 0; + right: 0; + margin: auto; + text-align: center; +} + +.cu-bar .action:first-child { + margin-left: 30rpx; + font-size: 30rpx; +} + +.cu-bar .action text.text-cut { + text-align: left; + width: 100%; +} + +.cu-bar .cu-avatar:first-child { + margin-left: 20rpx; +} + +.cu-bar .action:first-child>text[class*="cuIcon-"] { + margin-left: -0.3em; + /* margin-right: 0.3em; */ +} + +.cu-bar .action:last-child { + margin-right: 30rpx; +} + +.cu-bar .action>text[class*="cuIcon-"], .cu-bar .action>view[class*="cuIcon-"] { + font-size: 36rpx; +} + +.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] { + margin-left: 0.5em; +} + +.cu-bar .content { + position: absolute; + text-align: center; + width: calc(100% - 340rpx); + left: 0; + right: 0; + bottom: 0; + top: 0; + margin: auto; + height: 60rpx; + font-size: 32rpx; + line-height: 60rpx; + cursor: none; + pointer-events: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.cu-bar.ios .content { + bottom: 7px; + height: 30px; + font-size: 32rpx; + line-height: 30px; +} + +.cu-bar.btn-group { + justify-content: space-around; +} + +.cu-bar.btn-group button { + padding: 20rpx 32rpx; +} + +.cu-bar.btn-group button { + flex: 1; + margin: 0 20rpx; + max-width: 50%; +} + +.cu-bar .search-form { + background-color: #f5f5f5; + line-height: 64rpx; + height: 64rpx; + font-size: 24rpx; + color: var(--black); + flex: 1; + display: flex; + align-items: center; + margin: 0 24rpx; +} + +.cu-bar .search-form+.action { + margin-right: 20rpx; +} + +.cu-bar .search-form input { + flex: 1; + padding-right: 30rpx; + height: 72rpx; + line-height: 72rpx; + font-size: 30rpx; + background-color: transparent; +} + +.cu-bar .search-form [class*="cuIcon-"] { + margin: 0 0.5em 0 0.8em; +} + +.cu-bar .search-form [class*="cuIcon-"]::before { + top: 0rpx; +} + +.cu-bar.fixed, .nav.fixed { + position: fixed; + width: 100%; + top: 0; + z-index: 19; + box-shadow: 0 0rpx 2rpx rgba(0, 0, 0, 0.1); +} + +.cu-bar.foot { + position: fixed; + width: 100%; + bottom: 0; + z-index: 9; + /* box-shadow: 0 -1rpx 6rpx rgba(0, 0, 0, 0.1); */ +} + +.cu-custom { + display: block; + position: relative; +} + +.cu-custom .cu-bar .content { + width: calc(100% - 440rpx); +} + +.cu-custom .cu-bar .content image { + height: 60rpx; + width: 240rpx; +} + +.cu-custom .cu-bar { + padding-right: 190rpx; + z-index: 99; + /* box-shadow: 0rpx 0rpx 0rpx; */ +} + +.cu-custom .cu-bar .border-custom { + position: relative; + background: rgba(0, 0, 0, 0.15); + border-radius: 1000rpx; + height: 30px; +} + +.cu-custom .cu-bar .border-custom::after { + content: " "; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + border-radius: inherit; + transform: scale(0.5); + transform-origin: 0 0; + pointer-events: none; + box-sizing: border-box; + border: 1rpx solid var(--white); + opacity: 0.5; +} + +.cu-custom .cu-bar .border-custom::before { + content: " "; + width: 1rpx; + height: 110%; + position: absolute; + top: 22.5%; + left: 0; + right: 0; + margin: auto; + transform: scale(0.5); + transform-origin: 0 0; + pointer-events: none; + box-sizing: border-box; + opacity: 0.6; + background-color: var(--white); +} + +.cu-custom .cu-bar .border-custom text { + display: block; + flex: 1; + margin: auto !important; + text-align: center; + font-size: 34rpx; +} + +/* ================== + 导航栏 + ==================== */ + +.nav { + white-space: nowrap; +} + +::-webkit-scrollbar { + display: none; +} + +.nav .cu-item { + height: 90rpx; + display: inline-block; + line-height: 90rpx; + margin: 0 10rpx; + padding: 0 20rpx; +} + +.nav .cu-item.cur { + border-bottom: 4rpx solid; +} +/* ================== + 表单 + ==================== */ + +.cu-form-group { + background-color: var(--white); + padding: 1rpx 30rpx; + display: flex; + align-items: center; + min-height: 100rpx; + justify-content: space-between; +} + +.cu-form-group+.cu-form-group { + border-top: 1rpx solid #eee; +} + +.cu-form-group .title { + text-align: justify; + /* padding-right: 30rpx; */ + font-size: 30rpx; + position: relative; + height: 60rpx; + line-height: 60rpx; +} + +.cu-form-group input { + flex: 1; + font-size: 30rpx; + color: #555; + padding-right: 20rpx; +} + +.cu-form-group>text[class*="cuIcon-"] { + font-size: 36rpx; + padding: 0; + box-sizing: border-box; +} + +.cu-form-group textarea { + margin: 32rpx 0 30rpx; + height: 4.6em; + width: 100%; + line-height: 1.2em; + flex: 1; + font-size: 28rpx; + padding: 0; +} + +.cu-form-group.align-start .title { + height: 1em; + margin-top: 32rpx; + line-height: 1em; +} + +.cu-form-group picker { + flex: 1; + padding-right: 40rpx; + overflow: hidden; + position: relative; +} + +.cu-form-group picker .picker { + line-height: 100rpx; + font-size: 28rpx; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + text-align: right; +} + +.cu-form-group picker::after { + font-family: "cuIcon"; + display: block; + content: "\e6a3"; + position: absolute; + font-size: 34rpx; + color: var(--grey); + line-height: 100rpx; + width: 60rpx; + text-align: center; + top: 0; + bottom: 0; + right: -20rpx; + margin: auto; +} + +.cu-form-group textarea[disabled], +.cu-form-group textarea[disabled] .placeholder { + color: transparent; +} + +/* -- flex弹性布局 -- */ + +.flex { + display: flex; +} + +.flex-direction { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.align-start { + align-items: flex-start; +} + +.align-end { + align-items: flex-end; +} + +.align-center { + align-items: center; +} + +.align-stretch { + align-items: stretch; +} + +.self-start { + align-self: flex-start; +} + +.self-center { + align-self: flex-center; +} + +.self-end { + align-self: flex-end; +} + +.self-stretch { + align-self: stretch; +} + +.align-stretch { + align-items: stretch; +} + +.justify-start { + justify-content: flex-start; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.justify-around { + justify-content: space-around; +} +/* -- 内外边距 -- */ +.margin-top { + margin-top: 20rpx; +} +/* ================== + 文本 + ==================== */ + +.text-xs { + font-size: 22rpx; +} + +.text-sm { + font-size: 24rpx; +} + +.text-df { + font-size: 28rpx; +} + +.text-sg { + font-size: 30rpx; +} + +.text-lg { + font-size: 32rpx; +} + +.text-xl { + font-size: 36rpx; +} + +.text-xxl { + font-size: 44rpx; +} + +.text-xxxl { + font-size: 56rpx; +} + +.text-sl { + font-size: 80rpx; +} + +.text-xsl { + font-size: 100rpx; +} + +.text-Abc { + text-transform: Capitalize; +} + +.text-ABC { + text-transform: Uppercase; +} + +.text-abc { + text-transform: Lowercase; +} + +.text-price::before { + content: "¥"; + font-size: 80%; + margin-right: 4rpx; +} + +.text-cut { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.text-bold { + font-weight: bold; +} + +.text-center { + text-align: center; +} + +.text-content { + line-height: 1.6; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-red, .line-red, .lines-red { + color: var(--red); +} + +.text-orange, .line-orange, .lines-orange { + color: var(--orange); +} + +.text-yellow, .line-yellow, .lines-yellow { + color: var(--yellow); +} + +.text-olive, .line-olive, .lines-olive { + color: var(--olive); +} + +.text-green, .line-green, .lines-green { + color: var(--green); +} + +.text-cyan, .line-cyan, .lines-cyan { + color: var(--cyan); +} + +.text-blue, .line-blue, .lines-blue { + color: var(--blue); +} + +.text-purple, .line-purple, .lines-purple { + color: var(--purple); +} + +.text-mauve, .line-mauve, .lines-mauve { + color: var(--mauve); +} + +.text-pink, .line-pink, .lines-pink { + color: var(--pink); +} + +.text-brown, .line-brown, .lines-brown { + color: var(--brown); +} + +.text-grey, .line-grey, .lines-grey { + color: var(--grey); +} + +.text-gray, .line-gray, .lines-gray { + color: var(--gray); +} + +.text-black, .line-black, .lines-black { + color: var(--black); +} + +.text-white, .line-white, .lines-white { + color: var(--white); +} + +.list-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.img-empty { + width: 310rpx; + height: 220rpx; +} + +.text-empty { + margin-top: 48rpx; + font-size: 30rpx; + color: #666; + text-align: center; +} + +.input-grey { + color: #AAA; +} + +.font14 { + font-size: 28rpx; +} + +.cate_item { + min-height: 80rpx; + background-color: #eee; + border-radius: 8rpx; + margin: 0 24rpx; +} + +.margin-b { + margin-bottom: 16rpx; +} + +.flex-sub { + flex: 1; +} + + +/* ================== + 列表 + ==================== */ + .grayscale { + filter: grayscale(1); +} + +.cu-list+.cu-list { + margin-top: 30rpx +} + +.cu-list>.cu-item { + transition: all .6s ease-in-out 0s; + transform: translateX(0rpx) +} + +.cu-list>.cu-item.move-cur { + transform: translateX(-260rpx) +} + +.cu-list>.cu-item .move { + position: absolute; + right: 0; + display: flex; + width: 260rpx; + height: 100%; + transform: translateX(100%) +} + +.cu-list>.cu-item .move view { + display: flex; + flex: 1; + justify-content: center; + align-items: center +} + +.cu-list.menu-avatar { + overflow: hidden; +} + +.cu-list.menu-avatar>.cu-item { + position: relative; + display: flex; + padding-right: 10rpx; + height: 140rpx; + background-color: var(--white); + justify-content: flex-end; + align-items: center +} + +.cu-list.menu-avatar>.cu-item>.cu-avatar { + position: absolute; + left: 30rpx +} + +.cu-list.menu-avatar>.cu-item .flex .text-cut { + max-width: 510rpx +} + +.cu-list.menu-avatar>.cu-item .content { + position: absolute; + left: 146rpx; + width: calc(100% - 96rpx - 60rpx - 120rpx - 20rpx); + line-height: 1.6em; +} + +.cu-list.menu-avatar>.cu-item .content.flex-sub { + width: calc(100% - 96rpx - 60rpx - 20rpx); +} + +.cu-list.menu-avatar>.cu-item .content>view:first-child { + font-size: 30rpx; + display: flex; + align-items: center +} + +.cu-list.menu-avatar>.cu-item .content .cu-tag.sm { + display: inline-block; + margin-left: 10rpx; + height: 28rpx; + font-size: 16rpx; + line-height: 32rpx +} + +.cu-list.menu-avatar>.cu-item .action { + width: 100rpx; + text-align: center +} + +.cu-list.menu-avatar>.cu-item .action view+view { + margin-top: 10rpx +} + +.cu-list.menu-avatar.comment>.cu-item .content { + position: relative; + left: 0; + width: auto; + flex: 1; +} + +.cu-list.menu-avatar.comment>.cu-item { + padding: 30rpx 30rpx 30rpx 120rpx; + height: auto +} + +.cu-list.menu-avatar.comment .cu-avatar { + align-self: flex-start +} + +.cu-list.menu>.cu-item { + position: relative; + display: flex; + padding: 0 30rpx; + min-height: 96rpx; + background-color: var(--white); + justify-content: space-between; + align-items: center +} + +.cu-list.menu>.cu-item:last-child:after { + border: none +} + +.cu-list.menu>.cu-item:after { + position: absolute; + top: 0; + left: 0; + box-sizing: border-box; + width: 200%; + height: 200%; + border-bottom: 1rpx solid #ddd; + border-radius: inherit; + content: " "; + transform: scale(.5); + transform-origin: 0 0; + pointer-events: none +} + +.cu-list.menu>.cu-item.grayscale { + background-color: #f5f5f5 +} + +.cu-list.menu>.cu-item.cur { + background-color: #fcf7e9 +} + +.cu-list.menu>.cu-item.arrow { + padding-right: 90rpx +} + +.cu-list.menu>.cu-item.arrow:before { + position: absolute; + top: 0; + right: 30rpx; + bottom: 0; + display: block; + margin: auto; + width: 30rpx; + height: 30rpx; + color: var(--grey); + content: "\e6a3"; + text-align: center; + font-size: 34rpx; + font-family: "cuIcon"; + line-height: 30rpx +} + +.cu-list.menu>.cu-item button.content { + padding: 0; + background-color: transparent; + justify-content: flex-start +} + +.cu-list.menu>.cu-item button.content:after { + display: none +} + +.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar { + border-color: var(--white) +} + +.cu-list.menu>.cu-item .content>view:first-child { + display: flex; + align-items: center +} + +.cu-list.menu>.cu-item .content>text[class*=cuIcon] { + display: inline-block; + margin-right: 10rpx; + width: 1.6em; + text-align: center +} + +.cu-list.menu>.cu-item .content>image { + display: inline-block; + margin-right: 10rpx; + width: 1.6em; + height: 1.6em; + vertical-align: middle +} + +.cu-list.menu>.cu-item .content { + font-size: 30rpx; + line-height: 1.6em; + flex: 1 +} + +.cu-list.menu>.cu-item .content .cu-tag.sm { + display: inline-block; + margin-left: 10rpx; + height: 28rpx; + font-size: 16rpx; + line-height: 32rpx +} + +.cu-list.menu>.cu-item .action .cu-tag:empty { + right: 10rpx +} + +.cu-list.menu { + display: block; + overflow: hidden +} + +.cu-list.menu.sm-border>.cu-item:after { + left: 30rpx; + width: calc(200% - 120rpx) +} + +.cu-list.grid>.cu-item { + position: relative; + display: flex; + padding: 20rpx 0 30rpx; + transition-duration: 0s; + flex-direction: column +} + +.cu-list.grid>.cu-item:after { + position: absolute; + top: 0; + left: 0; + box-sizing: border-box; + width: 200%; + height: 200%; + border-right: 1px solid rgba(0, 0, 0, .1); + border-bottom: 1px solid rgba(0, 0, 0, .1); + border-radius: inherit; + content: " "; + transform: scale(.5); + transform-origin: 0 0; + pointer-events: none +} + +.cu-list.grid>.cu-item text { + display: block; + margin-top: 10rpx; + color: #888; + font-size: 26rpx; + line-height: 40rpx +} + +.cu-list.grid>.cu-item [class*=cuIcon] { + position: relative; + display: block; + margin-top: 20rpx; + width: 100%; + font-size: 48rpx +} + +.cu-list.grid>.cu-item .cu-tag { + right: auto; + left: 50%; + margin-left: 20rpx +} + +.cu-list.grid { + background-color: var(--white); + text-align: center +} + +.cu-list.grid.no-border>.cu-item { + padding-top: 10rpx; + padding-bottom: 20rpx +} + +.cu-list.grid.no-border>.cu-item:after { + border: none +} + +.cu-list.grid.no-border { + padding: 20rpx 10rpx +} + +.cu-list.grid.col-3>.cu-item:nth-child(3n):after, +.cu-list.grid.col-4>.cu-item:nth-child(4n):after, +.cu-list.grid.col-5>.cu-item:nth-child(5n):after { + border-right-width: 0 +} + +.grid { + display: flex; + flex-wrap: wrap; +} + +.grid.col-1>view { + width: 100%; +} + +.grid.col-2>view { + width: 50%; +} + +.grid.col-3>view { + width: 33.33%; +} + +.grid.col-4>view { + width: 25%; +} + +.grid.col-5>view { + width: 20%; +} \ No newline at end of file diff --git a/components/action-sheet/index.js b/components/action-sheet/index.js new file mode 100644 index 0000000..3044481 --- /dev/null +++ b/components/action-sheet/index.js @@ -0,0 +1,62 @@ +import { VantComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +VantComponent({ + mixins: [button, openType], + props: { + show: Boolean, + title: String, + cancelText: String, + description: String, + round: { + type: Boolean, + value: true + }, + zIndex: { + type: Number, + value: 100 + }, + actions: { + type: Array, + value: [] + }, + overlay: { + type: Boolean, + value: true + }, + closeOnClickOverlay: { + type: Boolean, + value: true + }, + closeOnClickAction: { + type: Boolean, + value: true + }, + safeAreaInsetBottom: { + type: Boolean, + value: true + } + }, + methods: { + onSelect(event) { + const { index } = event.currentTarget.dataset; + const item = this.data.actions[index]; + if (item && !item.disabled && !item.loading) { + this.$emit('select', item); + if (this.data.closeOnClickAction) { + this.onClose(); + } + } + }, + onCancel() { + this.$emit('cancel'); + }, + onClose() { + this.$emit('close'); + }, + onClickOverlay() { + this.$emit('click-overlay'); + this.onClose(); + } + } +}); diff --git a/components/action-sheet/index.json b/components/action-sheet/index.json new file mode 100644 index 0000000..19bf989 --- /dev/null +++ b/components/action-sheet/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-popup": "../popup/index", + "van-loading": "../loading/index" + } +} diff --git a/components/action-sheet/index.wxml b/components/action-sheet/index.wxml new file mode 100644 index 0000000..813b12a --- /dev/null +++ b/components/action-sheet/index.wxml @@ -0,0 +1,34 @@ + + + + + {{ title }} + + + {{ description }} + + + + + + + {{ cancelText }} + + \ No newline at end of file diff --git a/components/action-sheet/index.wxss b/components/action-sheet/index.wxss new file mode 100644 index 0000000..dc54840 --- /dev/null +++ b/components/action-sheet/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:50px;line-height:var(--action-sheet-item-height,50px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:before{display:block;content:" ";height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f7f8fa;background-color:var(--action-sheet-cancel-padding-color,#f7f8fa)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-left:4px;margin-left:var(--padding-base,4px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#646566;color:var(--action-sheet-subname-color,#646566)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:44px;line-height:var(--action-sheet-header-height,44px)}.van-action-sheet__description{text-align:center;padding:16px;padding:var(--padding-md,16px);color:#646566;color:var(--action-sheet-description-color,#646566);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 12px;padding:var(--action-sheet-close-icon-padding,0 12px);font-size:18px!important;font-size:var(--action-sheet-close-icon-size,18px)!important;color:#969799;color:var(--action-sheet-close-icon-color,#969799)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important;height:50px;height:var(--action-sheet-item-height,50px)} \ No newline at end of file diff --git a/components/animation-group/index.js b/components/animation-group/index.js new file mode 100644 index 0000000..bbfdc01 --- /dev/null +++ b/components/animation-group/index.js @@ -0,0 +1,383 @@ +import baseComponent from '../helpers/baseComponent' +import styleToCssString from '../helpers/styleToCssString' + +const ENTER = 'enter' +const ENTERING = 'entering' +const ENTERED = 'entered' +const EXIT = 'exit' +const EXITING = 'exiting' +const EXITED = 'exited' +const UNMOUNTED = 'unmounted' + +const TRANSITION = 'transition' +const ANIMATION = 'animation' + +const TIMEOUT = 1000 / 60 + +const defaultClassNames = { + enter: '', // 进入过渡的开始状态,在过渡过程完成之后移除 + enterActive: '', // 进入过渡的结束状态,在过渡过程完成之后移除 + enterDone: '', // 进入过渡的完成状态 + exit: '', // 离开过渡的开始状态,在过渡过程完成之后移除 + exitActive: '', // 离开过渡的结束状态,在过渡过程完成之后移除 + exitDone: '', // 离开过渡的完成状态 +} + +baseComponent({ + properties: { + // 触发组件进入或离开过渡的状态 + in: { + type: Boolean, + value: false, + observer(newVal) { + if (this.data.isMounting) { + this.updated(newVal) + } + }, + }, + // 过渡的类名 + classNames: { + type: null, + value: defaultClassNames, + }, + // 过渡持续时间 + duration: { + type: null, + value: null, + }, + // 过渡动效的类型 + type: { + type: String, + value: TRANSITION, + }, + // 首次挂载时是否触发进入过渡 + appear: { + type: Boolean, + value: false, + }, + // 是否启用进入过渡 + enter: { + type: Boolean, + value: true, + }, + // 是否启用离开过渡 + exit: { + type: Boolean, + value: true, + }, + // 首次进入过渡时是否懒挂载组件 + mountOnEnter: { + type: Boolean, + value: true, + }, + // 离开过渡完成时是否卸载组件 + unmountOnExit: { + type: Boolean, + value: true, + }, + // 自定义类名 + wrapCls: { + type: String, + value: '', + }, + // 自定义样式 + wrapStyle: { + type: [String, Object], + value: '', + observer(newVal) { + this.setData({ + extStyle: styleToCssString(newVal), + }) + }, + }, + disableScroll: { + type: Boolean, + value: false, + }, + }, + data: { + animateCss: '', // 动画样式 + animateStatus: EXITED, // 动画状态,可选值 entering、entered、exiting、exited + isMounting: false, // 是否首次挂载 + extStyle: '', // 组件样式 + }, + methods: { + /** + * 监听过渡或动画的回调函数 + */ + addEventListener() { + const { animateStatus } = this.data + const { enter, exit } = this.getTimeouts() + + if (animateStatus === ENTERING && !enter && this.data.enter) { + this.performEntered() + } + + if (animateStatus === EXITING && !exit && this.data.exit) { + this.performExited() + } + }, + /** + * 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 + */ + onTransitionEnd() { + if (this.data.type === TRANSITION) { + this.addEventListener() + } + }, + /** + * 会在一个 WXSS animation 动画完成时触发 + */ + onAnimationEnd() { + if (this.data.type === ANIMATION) { + this.addEventListener() + } + }, + /** + * 更新组件状态 + * @param {String} nextStatus 下一状态,ENTERING 或 EXITING + * @param {Boolean} mounting 是否首次挂载 + */ + updateStatus(nextStatus, mounting = false) { + if (nextStatus !== null) { + this.cancelNextCallback() + this.isAppearing = mounting + + if (nextStatus === ENTERING) { + this.performEnter() + } else { + this.performExit() + } + } + }, + /** + * 进入过渡 + */ + performEnter() { + const { className, activeClassName } = this.getClassNames(ENTER) + const { enter } = this.getTimeouts() + const enterParams = { + animateStatus: ENTER, + animateCss: className, + } + const enteringParams = { + animateStatus: ENTERING, + animateCss: `${className} ${activeClassName}`, + } + + // 若已禁用进入过渡,则更新状态至 ENTERED + if (!this.isAppearing && !this.data.enter) { + return this.performEntered() + } + + // 第一阶段:设置进入过渡的开始状态,并触发 ENTER 事件 + // 第二阶段:延迟一帧后,设置进入过渡的结束状态,并触发 ENTERING 事件 + // 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发进入过渡完成 performEntered,否则等待触发 onTransitionEnd 或 onAnimationEnd + this.safeSetData(enterParams, () => { + this.triggerEvent('change', { animateStatus: ENTER }) + this.triggerEvent(ENTER, { isAppearing: this.isAppearing }) + + // 由于有些时候不能正确的触发动画完成的回调,具体原因未知 + // 所以采用延迟一帧的方式来确保可以触发回调 + this.delayHandler(TIMEOUT, () => { + this.safeSetData(enteringParams, () => { + this.triggerEvent('change', { animateStatus: ENTERING }) + this.triggerEvent(ENTERING, { isAppearing: this.isAppearing }) + + if (enter) { + this.delayHandler(enter, this.performEntered) + } + }) + }) + }) + }, + /** + * 进入过渡完成 + */ + performEntered() { + const { doneClassName } = this.getClassNames(ENTER) + const enteredParams = { + animateStatus: ENTERED, + animateCss: doneClassName, + } + + // 第三阶段:设置进入过渡的完成状态,并触发 ENTERED 事件 + this.safeSetData(enteredParams, () => { + this.triggerEvent('change', { animateStatus: ENTERED }) + this.triggerEvent(ENTERED, { isAppearing: this.isAppearing }) + }) + }, + /** + * 离开过渡 + */ + performExit() { + const { className, activeClassName } = this.getClassNames(EXIT) + const { exit } = this.getTimeouts() + const exitParams = { + animateStatus: EXIT, + animateCss: className, + } + const exitingParams = { + animateStatus: EXITING, + animateCss: `${className} ${activeClassName}`, + } + + // 若已禁用离开过渡,则更新状态至 EXITED + if (!this.data.exit) { + return this.performExited() + } + + // 第一阶段:设置离开过渡的开始状态,并触发 EXIT 事件 + // 第二阶段:延迟一帧后,设置离开过渡的结束状态,并触发 EXITING 事件 + // 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发离开过渡完成 performExited,否则等待触发 onTransitionEnd 或 onAnimationEnd + this.safeSetData(exitParams, () => { + this.triggerEvent('change', { animateStatus: EXIT }) + this.triggerEvent(EXIT) + + this.delayHandler(TIMEOUT, () => { + this.safeSetData(exitingParams, () => { + this.triggerEvent('change', { animateStatus: EXITING }) + this.triggerEvent(EXITING) + + if (exit) { + this.delayHandler(exit, this.performExited) + } + }) + }) + }) + }, + /** + * 离开过渡完成 + */ + performExited() { + const { doneClassName } = this.getClassNames(EXIT) + const exitedParams = { + animateStatus: EXITED, + animateCss: doneClassName, + } + + // 第三阶段:设置离开过渡的完成状态,并触发 EXITED 事件 + this.safeSetData(exitedParams, () => { + this.triggerEvent('change', { animateStatus: EXITED }) + this.triggerEvent(EXITED) + + // 判断离开过渡完成时是否卸载组件 + if (this.data.unmountOnExit) { + this.setData({ animateStatus: UNMOUNTED }, () => { + this.triggerEvent('change', { animateStatus: UNMOUNTED }) + }) + } + }) + }, + /** + * 获取指定状态下的类名 + * @param {String} type 过渡类型,enter 或 exit + */ + getClassNames(type) { + const { classNames } = this.data + const className = typeof classNames !== 'string' ? classNames[type] : `${classNames}-${type}` + const activeClassName = typeof classNames !== 'string' ? classNames[`${type}Active`] : `${classNames}-${type}-active` + const doneClassName = typeof classNames !== 'string' ? classNames[`${type}Done`] : `${classNames}-${type}-done` + + return { + className, + activeClassName, + doneClassName, + } + }, + /** + * 获取过渡持续时间 + */ + getTimeouts() { + const { duration } = this.data + + if (duration !== null && typeof duration === 'object') { + return { + enter: duration.enter, + exit: duration.exit, + } + } else if (typeof duration === 'number') { + return { + enter: duration, + exit: duration, + } + } + + return {} + }, + /** + * 属性值 in 被更改时的响应函数 + * @param {Boolean} newVal 触发组件进入或离开过渡的状态 + */ + updated(newVal) { + let { animateStatus } = this.pendingData || this.data + let nextStatus = null + + if (newVal) { + if (animateStatus === UNMOUNTED) { + animateStatus = EXITED + this.setData({ animateStatus: EXITED }, () => { + this.triggerEvent('change', { animateStatus: EXITED }) + }) + } + if (animateStatus !== ENTER && animateStatus !== ENTERING && animateStatus !== ENTERED) { + nextStatus = ENTERING + } + } else { + if (animateStatus === ENTER || animateStatus === ENTERING || animateStatus === ENTERED) { + nextStatus = EXITING + } + } + + this.updateStatus(nextStatus) + }, + /** + * 延迟一段时间触发回调 + * @param {Number} timeout 延迟时间 + * @param {Function} handler 回调函数 + */ + delayHandler(timeout, handler) { + if (timeout) { + this.setNextCallback(handler) + setTimeout(this.nextCallback, timeout) + } + }, + /** + * 点击事件 + */ + onTap() { + this.triggerEvent('click') + }, + /** + * 阻止移动触摸 + */ + noop() { + }, + }, + attached() { + let animateStatus = null + let appearStatus = null + + if (this.data.in) { + if (this.data.appear) { + animateStatus = EXITED + appearStatus = ENTERING + } else { + animateStatus = ENTERED + } + } else { + if (this.data.unmountOnExit || this.data.mountOnEnter) { + animateStatus = UNMOUNTED + } else { + animateStatus = EXITED + } + } + + // 由于小程序组件首次挂载时 observer 事件总是优先于 attached 事件 + // 所以使用 isMounting 来强制优先触发 attached 事件 + this.safeSetData({ animateStatus, isMounting: true }, () => { + this.triggerEvent('change', { animateStatus }) + this.updateStatus(appearStatus, true) + }) + }, +}) diff --git a/components/animation-group/index.json b/components/animation-group/index.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/animation-group/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/animation-group/index.wxml b/components/animation-group/index.wxml new file mode 100644 index 0000000..7a68452 --- /dev/null +++ b/components/animation-group/index.wxml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/components/animation-group/index.wxss b/components/animation-group/index.wxss new file mode 100644 index 0000000..ac89862 --- /dev/null +++ b/components/animation-group/index.wxss @@ -0,0 +1,206 @@ +.wux-animate--fadeIn-enter { + transition: opacity .3s; + opacity: 0 +} +.wux-animate--fadeIn-enter-active, +.wux-animate--fadeIn-enter-done { + opacity: 1 +} +.wux-animate--fadeIn-exit { + transition: opacity .3s; + opacity: 1 +} +.wux-animate--fadeIn-exit-active, +.wux-animate--fadeIn-exit-done { + opacity: 0 +} +.wux-animate--fadeInDown-enter { + transition: opacity .3s,transform .3s; + opacity: 0; + transform: translate3d(0,-100%,0) +} +.wux-animate--fadeInDown-enter-active, +.wux-animate--fadeInDown-enter-done { + opacity: 1; + transform: none +} +.wux-animate--fadeInDown-exit { + transition: opacity .3s,transform .3s; + opacity: 1; + transform: none +} +.wux-animate--fadeInDown-exit-active, +.wux-animate--fadeInDown-exit-done { + opacity: 0; + transform: translate3d(0,-100%,0) +} +.wux-animate--fadeInLeft-enter { + transition: opacity .3s,transform .3s; + opacity: 0; + transform: translate3d(-100%,0,0) +} +.wux-animate--fadeInLeft-enter-active, +.wux-animate--fadeInLeft-enter-done { + opacity: 1; + transform: none +} +.wux-animate--fadeInLeft-exit { + transition: opacity .3s,transform .3s; + opacity: 1; + transform: none +} +.wux-animate--fadeInLeft-exit-active, +.wux-animate--fadeInLeft-exit-done { + opacity: 0; + transform: translate3d(-100%,0,0) +} +.wux-animate--fadeInRight-enter { + transition: opacity .3s,transform .3s; + opacity: 0; + transform: translate3d(100%,0,0) +} +.wux-animate--fadeInRight-enter-active, +.wux-animate--fadeInRight-enter-done { + opacity: 1; + transform: none +} +.wux-animate--fadeInRight-exit { + transition: opacity .3s,transform .3s; + opacity: 1; + transform: none +} +.wux-animate--fadeInRight-exit-active, +.wux-animate--fadeInRight-exit-done { + opacity: 0; + transform: translate3d(100%,0,0) +} +.wux-animate--fadeInUp-enter { + transition: opacity .3s,transform .3s; + opacity: 0; + transform: translate3d(0,100%,0) +} +.wux-animate--fadeInUp-enter-active, +.wux-animate--fadeInUp-enter-done { + opacity: 1; + transform: none +} +.wux-animate--fadeInUp-exit { + transition: opacity .3s,transform .3s; + opacity: 1; + transform: none +} +.wux-animate--fadeInUp-exit-active, +.wux-animate--fadeInUp-exit-done { + opacity: 0; + transform: translate3d(0,100%,0) +} +.wux-animate--slideInUp-enter { + transition: transform .3s; + transform: translate3d(0,100%,0); + visibility: visible +} +.wux-animate--slideInUp-enter-active, +.wux-animate--slideInUp-enter-done { + transform: translateZ(0) +} +.wux-animate--slideInUp-exit { + transition: transform .3s; + transform: translateZ(0) +} +.wux-animate--slideInUp-exit-active, +.wux-animate--slideInUp-exit-done { + transform: translate3d(0,100%,0); + visibility: visible +} +.wux-animate--slideInDown-enter { + transition: transform .3s; + transform: translate3d(0,-100%,0); + visibility: visible +} +.wux-animate--slideInDown-enter-active, +.wux-animate--slideInDown-enter-done { + transform: translateZ(0) +} +.wux-animate--slideInDown-exit { + transition: transform .3s; + transform: translateZ(0) +} +.wux-animate--slideInDown-exit-active, +.wux-animate--slideInDown-exit-done { + transform: translate3d(0,-100%,0); + visibility: visible +} +.wux-animate--slideInLeft-enter { + transition: transform .3s; + transform: translate3d(-100%,0,0); + visibility: visible +} +.wux-animate--slideInLeft-enter-active, +.wux-animate--slideInLeft-enter-done { + transform: translateZ(0) +} +.wux-animate--slideInLeft-exit { + transition: transform .3s; + transform: translateZ(0) +} +.wux-animate--slideInLeft-exit-active, +.wux-animate--slideInLeft-exit-done { + transform: translate3d(-100%,0,0); + visibility: visible +} +.wux-animate--slideInRight-enter { + transition: transform .3s; + transform: translate3d(100%,0,0); + visibility: visible +} +.wux-animate--slideInRight-enter-active, +.wux-animate--slideInRight-enter-done { + transform: none +} +.wux-animate--slideInRight-exit { + transition: transform .3s; + transform: none +} +.wux-animate--slideInRight-exit-active, +.wux-animate--slideInRight-exit-done { + transform: translate3d(100%,0,0); + visibility: visible +} +.wux-animate--zoom-enter { + transition: all .3s cubic-bezier(.215,.61,.355,1); + opacity: .01; + transform: scale(.75) +} +.wux-animate--zoom-enter-active, +.wux-animate--zoom-enter-done { + opacity: 1; + transform: none +} +.wux-animate--zoom-exit { + transition: all .25s linear; + transform: none +} +.wux-animate--zoom-exit-active, +.wux-animate--zoom-exit-done { + opacity: .01; + transform: scale(.75) +} +.wux-animate--punch-enter { + transition: all .3s cubic-bezier(.215,.61,.355,1); + opacity: .01; + transform: scale(1.35) +} +.wux-animate--punch-enter-active, +.wux-animate--punch-enter-done { + opacity: 1; + transform: none +} +.wux-animate--punch-exit { + transition: all .25s linear; + transform: none +} +.wux-animate--punch-exit-active, +.wux-animate--punch-exit-done { + opacity: .01; + transform: scale(1.35) +} \ No newline at end of file diff --git a/components/area/index.js b/components/area/index.js new file mode 100644 index 0000000..e17234c --- /dev/null +++ b/components/area/index.js @@ -0,0 +1,210 @@ +import { VantComponent } from '../common/component'; +import { pickerProps } from '../picker/shared'; +const COLUMNSPLACEHOLDERCODE = '000000'; +VantComponent({ + classes: ['active-class', 'toolbar-class', 'column-class'], + props: Object.assign(Object.assign({}, pickerProps), { value: { + type: String, + observer(value) { + this.code = value; + this.setValues(); + }, + }, areaList: { + type: Object, + value: {}, + observer: 'setValues' + }, columnsNum: { + type: null, + value: 3, + observer(value) { + this.setData({ + displayColumns: this.data.columns.slice(0, +value) + }); + } + }, columnsPlaceholder: { + type: Array, + observer(val) { + this.setData({ + typeToColumnsPlaceholder: { + province: val[0] || '', + city: val[1] || '', + county: val[2] || '', + } + }); + } + } }), + data: { + columns: [{ values: [] }, { values: [] }, { values: [] }], + displayColumns: [{ values: [] }, { values: [] }, { values: [] }], + typeToColumnsPlaceholder: {} + }, + mounted() { + setTimeout(() => { + this.setValues(); + }, 0); + }, + methods: { + getPicker() { + if (this.picker == null) { + this.picker = this.selectComponent('.van-area__picker'); + } + return this.picker; + }, + onCancel(event) { + this.emit('cancel', event.detail); + }, + onConfirm(event) { + const { index } = event.detail; + let { value } = event.detail; + value = this.parseOutputValues(value); + this.emit('confirm', { value, index }); + }, + emit(type, detail) { + detail.values = detail.value; + delete detail.value; + this.$emit(type, detail); + }, + // parse output columns data + parseOutputValues(values) { + const { columnsPlaceholder } = this.data; + return values.map((value, index) => { + // save undefined value + if (!value) + return value; + value = JSON.parse(JSON.stringify(value)); + if (!value.code || value.name === columnsPlaceholder[index]) { + value.code = ''; + value.name = ''; + } + return value; + }); + }, + onChange(event) { + const { index, picker, value } = event.detail; + this.code = value[index].code; + this.setValues().then(() => { + this.$emit('change', { + picker, + values: this.parseOutputValues(picker.getValues()), + index + }); + }); + }, + getConfig(type) { + const { areaList } = this.data; + return (areaList && areaList[`${type}_list`]) || {}; + }, + getList(type, code) { + const { typeToColumnsPlaceholder } = this.data; + let result = []; + if (type !== 'province' && !code) { + return result; + } + const list = this.getConfig(type); + result = Object.keys(list).map(code => ({ + code, + name: list[code] + })); + if (code) { + // oversea code + if (code[0] === '9' && type === 'city') { + code = '9'; + } + result = result.filter(item => item.code.indexOf(code) === 0); + } + if (typeToColumnsPlaceholder[type] && result.length) { + // set columns placeholder + const codeFill = type === 'province' ? '' : type === 'city' ? COLUMNSPLACEHOLDERCODE.slice(2, 4) : COLUMNSPLACEHOLDERCODE.slice(4, 6); + result.unshift({ + code: `${code}${codeFill}`, + name: typeToColumnsPlaceholder[type] + }); + } + return result; + }, + getIndex(type, code) { + let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6; + const list = this.getList(type, code.slice(0, compareNum - 2)); + // oversea code + if (code[0] === '9' && type === 'province') { + compareNum = 1; + } + code = code.slice(0, compareNum); + for (let i = 0; i < list.length; i++) { + if (list[i].code.slice(0, compareNum) === code) { + return i; + } + } + return 0; + }, + setValues() { + const county = this.getConfig('county'); + let { code } = this; + if (!code) { + if (this.data.columnsPlaceholder.length) { + code = COLUMNSPLACEHOLDERCODE; + } + else if (Object.keys(county)[0]) { + code = Object.keys(county)[0]; + } + else { + code = ''; + } + } + const province = this.getList('province'); + const city = this.getList('city', code.slice(0, 2)); + const picker = this.getPicker(); + if (!picker) { + return; + } + const stack = []; + stack.push(picker.setColumnValues(0, province, false)); + stack.push(picker.setColumnValues(1, city, false)); + if (city.length && code.slice(2, 4) === '00') { + [{ code }] = city; + } + stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false)); + return Promise.all(stack) + .catch(() => { }) + .then(() => picker.setIndexes([ + this.getIndex('province', code), + this.getIndex('city', code), + this.getIndex('county', code) + ])) + .catch(() => { }); + }, + getValues() { + const picker = this.getPicker(); + return picker ? picker.getValues().filter(value => !!value) : []; + }, + getDetail() { + const values = this.getValues(); + const area = { + code: '', + country: '', + province: '', + city: '', + county: '' + }; + if (!values.length) { + return area; + } + const names = values.map((item) => item.name); + area.code = values[values.length - 1].code; + if (area.code[0] === '9') { + area.country = names[1] || ''; + area.province = names[2] || ''; + } + else { + area.province = names[0] || ''; + area.city = names[1] || ''; + area.county = names[2] || ''; + } + return area; + }, + reset(code) { + this.code = code || ''; + return this.setValues(); + } + } +}); diff --git a/components/area/index.json b/components/area/index.json new file mode 100644 index 0000000..a778e91 --- /dev/null +++ b/components/area/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-picker": "../picker/index" + } +} diff --git a/components/area/index.wxml b/components/area/index.wxml new file mode 100644 index 0000000..6075794 --- /dev/null +++ b/components/area/index.wxml @@ -0,0 +1,18 @@ + diff --git a/components/area/index.wxss b/components/area/index.wxss new file mode 100644 index 0000000..99694d6 --- /dev/null +++ b/components/area/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; \ No newline at end of file diff --git a/components/backdrop/index.js b/components/backdrop/index.js new file mode 100644 index 0000000..cf43b99 --- /dev/null +++ b/components/backdrop/index.js @@ -0,0 +1,62 @@ +import baseComponent from '../helpers/baseComponent' + +baseComponent({ + properties: { + prefixCls: { + type: String, + value: 'wux-backdrop', + }, + transparent: { + type: Boolean, + value: false, + }, + zIndex: { + type: Number, + value: 1000, + }, + classNames: { + type: null, + value: 'wux-animate--fadeIn', + }, + }, + computed: { + classes: ['prefixCls, transparent', function(prefixCls, transparent) { + const wrap = transparent ? `${prefixCls}--transparent` : prefixCls + + return { + wrap, + } + }], + }, + methods: { + /** + * 保持锁定 + */ + retain() { + if (typeof this.backdropHolds !== 'number' || !this.backdropHolds) { + this.backdropHolds = 0 + } + + this.backdropHolds = this.backdropHolds + 1 + + if (this.backdropHolds === 1) { + this.setData({ in: true }) + } + }, + /** + * 释放锁定 + */ + release() { + if (this.backdropHolds === 1) { + this.setData({ in: false }) + } + this.backdropHolds = Math.max(0, this.backdropHolds - 1) + }, + /** + * 点击事件 + */ + onClick() { + this.triggerEvent('click') + }, + }, +}) diff --git a/components/backdrop/index.json b/components/backdrop/index.json new file mode 100644 index 0000000..9b9e7ab --- /dev/null +++ b/components/backdrop/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "wux-animation-group": "../animation-group/index" + } +} \ No newline at end of file diff --git a/components/backdrop/index.wxml b/components/backdrop/index.wxml new file mode 100644 index 0000000..d6ee398 --- /dev/null +++ b/components/backdrop/index.wxml @@ -0,0 +1 @@ + diff --git a/components/backdrop/index.wxss b/components/backdrop/index.wxss new file mode 100644 index 0000000..be44d1b --- /dev/null +++ b/components/backdrop/index.wxss @@ -0,0 +1,15 @@ +.wux-backdrop { + background: rgba(0,0,0,.4) +} +.wux-backdrop, +.wux-backdrop--transparent { + position: fixed; + z-index: 1000; + top: 0; + right: 0; + left: 0; + bottom: 0 +} +.wux-backdrop--transparent { + background: 0 0 +} \ No newline at end of file diff --git a/components/button/index.js b/components/button/index.js new file mode 100644 index 0000000..599aa98 --- /dev/null +++ b/components/button/index.js @@ -0,0 +1,69 @@ +import { VantComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +VantComponent({ + mixins: [button, openType], + classes: ['hover-class', 'loading-class'], + data: { + baseStyle: '' + }, + props: { + icon: String, + plain: Boolean, + block: Boolean, + round: Boolean, + square: Boolean, + loading: Boolean, + hairline: Boolean, + disabled: Boolean, + loadingText: String, + customStyle: String, + loadingType: { + type: String, + value: 'circular' + }, + type: { + type: String, + value: 'default' + }, + size: { + type: String, + value: 'normal' + }, + loadingSize: { + type: String, + value: '20px' + }, + color: { + type: String, + observer(color) { + let style = ''; + if (color) { + style += `color: ${this.data.plain ? color : 'white'};`; + if (!this.data.plain) { + // Use background instead of backgroundColor to make linear-gradient work + style += `background: ${color};`; + } + // hide border when color is linear-gradient + if (color.indexOf('gradient') !== -1) { + style += 'border: 0;'; + } + else { + style += `border-color: ${color};`; + } + } + if (style !== this.data.baseStyle) { + this.setData({ baseStyle: style }); + } + } + } + }, + methods: { + onClick() { + if (!this.data.loading) { + this.$emit('click'); + } + }, + noop() { } + } +}); diff --git a/components/button/index.json b/components/button/index.json new file mode 100644 index 0000000..e00a588 --- /dev/null +++ b/components/button/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-loading": "../loading/index" + } +} diff --git a/components/button/index.wxml b/components/button/index.wxml new file mode 100644 index 0000000..b4b05d5 --- /dev/null +++ b/components/button/index.wxml @@ -0,0 +1,44 @@ + + + + + + + function get(type, color, plain) { + if (plain) { + return color ? color : '#c9c9c9'; + } + + if (type === 'default') { + return '#c9c9c9'; + } + return 'white'; + } + + module.exports = get; + \ No newline at end of file diff --git a/components/button/index.wxss b/components/button/index.wxss new file mode 100644 index 0000000..5a591fb --- /dev/null +++ b/components/button/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);line-height:20px;line-height:var(--button-line-height,20px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background:#fff;background:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background:#07c160;background:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background:#1989fa;background:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background:#ee0a24;background:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background:#ff976a;background:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background:#fff;background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0} \ No newline at end of file diff --git a/components/cell-group/index.js b/components/cell-group/index.js new file mode 100644 index 0000000..3611e09 --- /dev/null +++ b/components/cell-group/index.js @@ -0,0 +1,10 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + title: String, + border: { + type: Boolean, + value: true + } + } +}); diff --git a/components/cell-group/index.json b/components/cell-group/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/cell-group/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/cell-group/index.wxml b/components/cell-group/index.wxml new file mode 100644 index 0000000..6e0b471 --- /dev/null +++ b/components/cell-group/index.wxml @@ -0,0 +1,9 @@ + + {{ title }} + + + + diff --git a/components/cell-group/index.wxss b/components/cell-group/index.wxss new file mode 100644 index 0000000..edbccd5 --- /dev/null +++ b/components/cell-group/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)} \ No newline at end of file diff --git a/components/cell/index.js b/components/cell/index.js new file mode 100644 index 0000000..bba1242 --- /dev/null +++ b/components/cell/index.js @@ -0,0 +1,35 @@ +import { link } from '../mixins/link' +import { VantComponent } from '../common/component' + +VantComponent({ + classes: [ + 'title-class', + 'label-class', + 'value-class', + 'right-icon-class', + 'hover-class' + ], + mixins: [link], + props: { + title: null, + value: null, + icon: String, + size: String, + label: String, + center: Boolean, + isLink: Boolean, + required: Boolean, + clickable: Boolean, + titleWidth: String, + customStyle: String, + arrowDirection: String, + useLabelSlot: Boolean, + border: { type: Boolean, value: true } + }, + methods: { + onClick(event) { + this.$emit('click', event.detail) + this.jumpLink() + } + } +}) \ No newline at end of file diff --git a/components/cell/index.json b/components/cell/index.json new file mode 100644 index 0000000..a9ab393 --- /dev/null +++ b/components/cell/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} \ No newline at end of file diff --git a/components/cell/index.wxml b/components/cell/index.wxml new file mode 100644 index 0000000..ed9d091 --- /dev/null +++ b/components/cell/index.wxml @@ -0,0 +1,30 @@ + + + + + + + + {{ title }} + + + + + {{ label }} + + + + + {{ value }} + + + + + + + + \ No newline at end of file diff --git a/components/cell/index.wxss b/components/cell/index.wxss new file mode 100644 index 0000000..06c2857 --- /dev/null +++ b/components/cell/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-cell{min-height: 96rpx;align-items: center;position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:auto;right:0;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:16px;font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)} \ No newline at end of file diff --git a/components/checkbox/index.js b/components/checkbox/index.js new file mode 100644 index 0000000..db5b551 --- /dev/null +++ b/components/checkbox/index.js @@ -0,0 +1,76 @@ +import { VantComponent } from '../common/component'; +function emit(target, value) { + target.$emit('input', value); + target.$emit('change', value); +} +VantComponent({ + field: true, + relation: { + name: 'checkbox-group', + type: 'ancestor', + current: 'checkbox', + }, + classes: ['icon-class', 'label-class'], + props: { + value: Boolean, + disabled: Boolean, + useIconSlot: Boolean, + checkedColor: String, + labelPosition: String, + labelDisabled: Boolean, + shape: { + type: String, + value: 'round' + }, + iconSize: { + type: null, + value: 20 + } + }, + data: { + parentDisabled: false + }, + methods: { + emitChange(value) { + if (this.parent) { + this.setParentValue(this.parent, value); + } + else { + emit(this, value); + } + }, + toggle() { + const { parentDisabled, disabled, value } = this.data; + if (!disabled && !parentDisabled) { + this.emitChange(!value); + } + }, + onClickLabel() { + const { labelDisabled, parentDisabled, disabled, value } = this.data; + if (!disabled && !labelDisabled && !parentDisabled) { + this.emitChange(!value); + } + }, + setParentValue(parent, value) { + const parentValue = parent.data.value.slice(); + const { name } = this.data; + const { max } = parent.data; + if (value) { + if (max && parentValue.length >= max) { + return; + } + if (parentValue.indexOf(name) === -1) { + parentValue.push(name); + emit(parent, parentValue); + } + } + else { + const index = parentValue.indexOf(name); + if (index !== -1) { + parentValue.splice(index, 1); + emit(parent, parentValue); + } + } + } + } +}); diff --git a/components/checkbox/index.json b/components/checkbox/index.json new file mode 100644 index 0000000..0a336c0 --- /dev/null +++ b/components/checkbox/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/components/checkbox/index.wxml b/components/checkbox/index.wxml new file mode 100644 index 0000000..94789d8 --- /dev/null +++ b/components/checkbox/index.wxml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/components/checkbox/index.wxs b/components/checkbox/index.wxs new file mode 100644 index 0000000..927eb55 --- /dev/null +++ b/components/checkbox/index.wxs @@ -0,0 +1,20 @@ +/* eslint-disable */ +var utils = require('../wxs/utils.wxs'); + +function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) { + var styles = [['font-size', utils.addUnit(iconSize)]]; + if (checkedColor && value && !disabled && !parentDisabled) { + styles.push(['border-color', checkedColor]); + styles.push(['background-color', checkedColor]); + } + + return styles + .map(function(item) { + return item.join(':'); + }) + .join(';'); +} + +module.exports = { + iconStyle: iconStyle +}; diff --git a/components/checkbox/index.wxss b/components/checkbox/index.wxss new file mode 100644 index 0000000..afaf37b --- /dev/null +++ b/components/checkbox/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0} \ No newline at end of file diff --git a/components/checker/index.js b/components/checker/index.js new file mode 100644 index 0000000..25af514 --- /dev/null +++ b/components/checker/index.js @@ -0,0 +1,58 @@ +import { VantComponent } from '../common/component'; +import { pickerProps } from './shared'; + +VantComponent({ + classes: ['active-class', 'toolbar-class', 'column-class'], + props: Object.assign(Object.assign({}, pickerProps), { + max: { + type: Number, + value: Infinity, + }, + activeId: { + type: Array, + value: [] + }, + toolbarPosition: { + type: String, + value: 'top' + }, + defaultIndex: { + type: Number, + value: 0 + }, + columns: { + type: Array, + value: [] + }, + selectedIcon: { + type: String, + value: 'success', + } + }), + methods: { + emit(event) { + const { type } = event.currentTarget.dataset; + if (this.data.columns.length) { + this.$emit(type, this.data.activeId ); + } else { + this.$emit(type, { }); + } + }, + onSelectItem(event) { + const { item } = event.currentTarget.dataset; + const isArray = Array.isArray(this.data.activeId); + // 判断有没有超出右侧选择的最大数 + const isOverMax = isArray && this.data.activeId.length >= this.data.max; + // 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件 + const index = this.data.activeId.indexOf(item.id) + if (!item.disabled && !isOverMax) { + if(index > -1){ + this.data.activeId.splice(index, 1) + } else { + this.data.activeId.push(item.id) + } + this.setData({ activeId: this.data.activeId }); + } + }, + } +}); diff --git a/components/checker/index.json b/components/checker/index.json new file mode 100644 index 0000000..5433fbf --- /dev/null +++ b/components/checker/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "loading": "../loading/index" + } +} diff --git a/components/checker/index.wxml b/components/checker/index.wxml new file mode 100644 index 0000000..23632ce --- /dev/null +++ b/components/checker/index.wxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + {{ item.name }} + + + + + \ No newline at end of file diff --git a/components/checker/index.wxs b/components/checker/index.wxs new file mode 100644 index 0000000..b1cbb39 --- /dev/null +++ b/components/checker/index.wxs @@ -0,0 +1,12 @@ +/* eslint-disable */ +var array = require('../wxs/array.wxs'); + +function isActive (activeList, itemId) { + if (array.isArray(activeList)) { + return activeList.indexOf(itemId) > -1; + } + + return activeList === itemId; +} + +module.exports.isActive = isActive; diff --git a/components/checker/index.wxss b/components/checker/index.wxss new file mode 100644 index 0000000..5b0e2a6 --- /dev/null +++ b/components/checker/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;-webkit-user-select:none;user-select:none;background-color:#fff;background-color:var(--picker-background-color,#fff)}.van-picker__toolbar{display:-webkit-flex;display:flex;-webkit-justify-content:space-between;justify-content:space-between;height:44px;height:var(--picker-toolbar-height,44px);line-height:44px;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#666666;color:var(--picker-action-text-color,#666666)}.van-picker__confirm{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#1989fa;color:var(--picker-action-text-color,#1989fa)}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5;background-color:var(--picker-action-active-color,#f2f3f5)}.van-picker__title{max-width:50%;text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background-color:hsla(0,0%,100%,.9);background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9))}.van-picker__mask{position:absolute;top:0;left:0;z-index:2;width:100%;height:100%;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-repeat:no-repeat;background-position:top,bottom;-webkit-backface-visibility:hidden;backface-visibility:hidden;pointer-events:none}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);pointer-events:none}.van-tree-select{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;font-size:14px;font-size:var(--tree-select-font-size,14px)}.van-tree-select__nav{-webkit-flex:1;flex:1;background-color:#f7f8fa;background-color:var(--tree-select-nav-background-color,#f7f8fa);--sidebar-padding:12px 8px 12px 12px}.van-tree-select__nav__inner{width:100%!important;height:100%}.van-tree-select__content{-webkit-flex:2;flex:2;background-color:#fff;background-color:var(--tree-select-content-background-color,#fff)}.van-tree-select__item{position:relative;font-weight:700;line-height:44px;line-height:var(--tree-select-item-height,44px)}.van-tree-select__item--active{color:#1989fa;color:var(--tree-select-item-active-color,#1989fa)}.van-tree-select__item--disabled{color:#c8c9cc;color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:0px;} \ No newline at end of file diff --git a/components/checker/shared.js b/components/checker/shared.js new file mode 100644 index 0000000..18d133c --- /dev/null +++ b/components/checker/shared.js @@ -0,0 +1,21 @@ +export const pickerProps = { + title: String, + loading: Boolean, + showToolbar: Boolean, + cancelButtonText: { + type: String, + value: '取消' + }, + confirmButtonText: { + type: String, + value: '确认' + }, + visibleItemCount: { + type: Number, + value: 5 + }, + itemHeight: { + type: Number, + value: 45 + } +}; diff --git a/components/checker/toolbar.wxml b/components/checker/toolbar.wxml new file mode 100644 index 0000000..d112b29 --- /dev/null +++ b/components/checker/toolbar.wxml @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/components/col/index.js b/components/col/index.js new file mode 100644 index 0000000..ec12aa9 --- /dev/null +++ b/components/col/index.js @@ -0,0 +1,24 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'row', + type: 'ancestor', + current: 'col', + }, + props: { + span: Number, + offset: Number + }, + data: { + viewStyle: '' + }, + methods: { + setGutter(gutter) { + const padding = `${gutter / 2}px`; + const viewStyle = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : ''; + if (viewStyle !== this.data.viewStyle) { + this.setData({ viewStyle }); + } + } + } +}); diff --git a/components/col/index.json b/components/col/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/col/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/col/index.wxml b/components/col/index.wxml new file mode 100644 index 0000000..52544f0 --- /dev/null +++ b/components/col/index.wxml @@ -0,0 +1,8 @@ + + + + + diff --git a/components/col/index.wxss b/components/col/index.wxss new file mode 100644 index 0000000..44c896a --- /dev/null +++ b/components/col/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%} \ No newline at end of file diff --git a/components/collapse-item/index.js b/components/collapse-item/index.js new file mode 100644 index 0000000..9ff56b8 --- /dev/null +++ b/components/collapse-item/index.js @@ -0,0 +1,95 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + classes: ['title-class', 'content-class'], + relation: { + name: 'collapse', + type: 'ancestor', + current: 'collapse-item', + }, + props: { + name: null, + title: null, + value: null, + icon: String, + label: String, + disabled: Boolean, + clickable: Boolean, + border: { + type: Boolean, + value: true, + }, + isLink: { + type: Boolean, + value: true, + }, + }, + data: { + expanded: false, + }, + created() { + this.animation = wx.createAnimation({ + duration: 0, + timingFunction: 'ease-in-out', + }); + }, + mounted() { + this.updateExpanded(); + this.inited = true; + }, + methods: { + updateExpanded() { + if (!this.parent) { + return Promise.resolve(); + } + const { value, accordion } = this.parent.data; + const { children = [] } = this.parent; + const { name } = this.data; + const index = children.indexOf(this); + const currentName = name == null ? index : name; + const expanded = accordion + ? value === currentName + : (value || []).some((name) => name === currentName); + if (expanded !== this.data.expanded) { + this.updateStyle(expanded); + } + this.setData({ index, expanded }); + }, + updateStyle(expanded) { + const { inited } = this; + this.getRect('.van-collapse-item__content') + .then((rect) => rect.height) + .then((height) => { + const { animation } = this; + if (expanded) { + animation + .height(height) + .top(1) + .step({ + duration: inited ? 300 : 1, + }) + .height('auto') + .step(); + this.setData({ + animation: animation.export(), + }); + return; + } + animation.height(height).top(0).step({ duration: 1 }).height(0).step({ + duration: 300, + }); + this.setData({ + animation: animation.export(), + }); + }); + }, + onClick() { + if (this.data.disabled) { + return; + } + const { name, expanded } = this.data; + const index = this.parent.children.indexOf(this); + const currentName = name == null ? index : name; + this.parent.switch(currentName, !expanded); + }, + }, +}); diff --git a/components/collapse-item/index.json b/components/collapse-item/index.json new file mode 100644 index 0000000..0e5425c --- /dev/null +++ b/components/collapse-item/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-cell": "../cell/index" + } +} diff --git a/components/collapse-item/index.wxml b/components/collapse-item/index.wxml new file mode 100644 index 0000000..60bade3 --- /dev/null +++ b/components/collapse-item/index.wxml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/collapse-item/index.wxss b/components/collapse-item/index.wxss new file mode 100644 index 0000000..0e075bd --- /dev/null +++ b/components/collapse-item/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)} \ No newline at end of file diff --git a/components/collapse/index.js b/components/collapse/index.js new file mode 100644 index 0000000..33dae31 --- /dev/null +++ b/components/collapse/index.js @@ -0,0 +1,47 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'collapse-item', + type: 'descendant', + current: 'collapse', + }, + props: { + value: { + type: null, + observer: 'updateExpanded', + }, + accordion: { + type: Boolean, + observer: 'updateExpanded', + }, + border: { + type: Boolean, + value: true, + }, + }, + methods: { + updateExpanded() { + this.children.forEach((child) => { + child.updateExpanded(); + }); + }, + switch(name, expanded) { + const { accordion, value } = this.data; + const changeItem = name; + if (!accordion) { + name = expanded + ? (value || []).concat(name) + : (value || []).filter((activeName) => activeName !== name); + } else { + name = expanded ? name : ''; + } + if (expanded) { + this.$emit('open', changeItem); + } else { + this.$emit('close', changeItem); + } + this.$emit('change', name); + this.$emit('input', name); + }, + }, +}); diff --git a/components/collapse/index.json b/components/collapse/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/collapse/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/collapse/index.wxml b/components/collapse/index.wxml new file mode 100644 index 0000000..fd4e171 --- /dev/null +++ b/components/collapse/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/components/collapse/index.wxss b/components/collapse/index.wxss new file mode 100644 index 0000000..99694d6 --- /dev/null +++ b/components/collapse/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; \ No newline at end of file diff --git a/components/common/classNames.js b/components/common/classNames.js new file mode 100644 index 0000000..9a61073 --- /dev/null +++ b/components/common/classNames.js @@ -0,0 +1 @@ +"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var hasOwn={}.hasOwnProperty;function classNames(){for(var e=[],t=0;t it !== child); + }, + }, +}; +function mapKeys(source, target, map) { + Object.keys(map).forEach(key => { + if (source[key]) { + target[map[key]] = source[key]; + } + }); +} +function makeRelation(options, vantOptions, relation) { + const { type, name, linked, unlinked, linkChanged } = relation; + const { beforeCreate, destroyed } = vantOptions; + if (type === 'descendant') { + options.created = function () { + beforeCreate && beforeCreate.bind(this)(); + this.children = this.children || []; + }; + options.detached = function () { + this.children = []; + destroyed && destroyed.bind(this)(); + }; + } + options.relations = Object.assign(options.relations || {}, { + [`../${name}/index`]: { + type, + linked(node) { + relationFunctions[type].linked.bind(this)(node); + linked && linked.bind(this)(node); + }, + linkChanged(node) { + linkChanged && linkChanged.bind(this)(node); + }, + unlinked(node) { + relationFunctions[type].unlinked.bind(this)(node); + unlinked && unlinked.bind(this)(node); + }, + } + }); +} +function VantComponent(vantOptions = {}) { + const options = {}; + mapKeys(vantOptions, options, { + data: 'data', + props: 'properties', + mixins: 'behaviors', + methods: 'methods', + beforeCreate: 'created', + created: 'attached', + mounted: 'ready', + relations: 'relations', + destroyed: 'detached', + classes: 'externalClasses' + }); + const { relation } = vantOptions; + if (relation) { + makeRelation(options, vantOptions, relation); + } + // add default externalClasses + options.externalClasses = options.externalClasses || []; + options.externalClasses.push('custom-class'); + // add default behaviors + options.behaviors = options.behaviors || []; + options.behaviors.push(basic); + // map field to form-field behavior + if (vantOptions.field) { + options.behaviors.push('wx://form-field'); + } + if (options.properties) { + Object.keys(options.properties).forEach(name => { + if (Array.isArray(options.properties[name])) { + // miniprogram do not allow multi type + options.properties[name] = null; + } + }); + } + // add default options + options.options = { + multipleSlots: true, + addGlobalClass: true + }; + Component(options); +} +export { VantComponent }; diff --git a/components/common/index.wxss b/components/common/index.wxss new file mode 100644 index 0000000..976825d --- /dev/null +++ b/components/common/index.wxss @@ -0,0 +1 @@ +.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #ebedf0;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px} \ No newline at end of file diff --git a/components/common/style/clearfix.wxss b/components/common/style/clearfix.wxss new file mode 100644 index 0000000..a0ca838 --- /dev/null +++ b/components/common/style/clearfix.wxss @@ -0,0 +1 @@ +.van-clearfix:after{display:table;clear:both;content:""} \ No newline at end of file diff --git a/components/common/style/ellipsis.wxss b/components/common/style/ellipsis.wxss new file mode 100644 index 0000000..1e9dbc9 --- /dev/null +++ b/components/common/style/ellipsis.wxss @@ -0,0 +1 @@ +.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3} \ No newline at end of file diff --git a/components/common/style/hairline.wxss b/components/common/style/hairline.wxss new file mode 100644 index 0000000..f64e2f8 --- /dev/null +++ b/components/common/style/hairline.wxss @@ -0,0 +1 @@ +.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px} \ No newline at end of file diff --git a/components/common/style/mixins/clearfix.wxss b/components/common/style/mixins/clearfix.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/mixins/ellipsis.wxss b/components/common/style/mixins/ellipsis.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/mixins/hairline.wxss b/components/common/style/mixins/hairline.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/theme.wxss b/components/common/style/theme.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/var.wxss b/components/common/style/var.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/utils.js b/components/common/utils.js new file mode 100644 index 0000000..4884a32 --- /dev/null +++ b/components/common/utils.js @@ -0,0 +1,47 @@ +export function isDef(value) { + return value !== undefined && value !== null; +} +export function isObj(x) { + const type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +} +export function isNumber(value) { + return /^\d+(\.\d+)?$/.test(value); +} +export function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} +export function nextTick(fn) { + setTimeout(() => { + fn(); + }, 1000 / 30); +} +let systemInfo = null; +export function getSystemInfoSync() { + if (systemInfo == null) { + systemInfo = wx.getSystemInfoSync(); + } + return systemInfo; +} +export function addUnit(value) { + if (!isDef(value)) { + return undefined; + } + value = String(value); + return isNumber(value) ? `${value}px` : value; +} +export function requestAnimationFrame(cb) { + const systemInfo = getSystemInfoSync(); + if (systemInfo.platform === 'devtools') { + return setTimeout(() => { + cb(); + }, 1000 / 30); + } + return wx + .createSelectorQuery() + .selectViewport() + .boundingClientRect() + .exec(() => { + cb(); + }); +} \ No newline at end of file diff --git a/components/common/validator.js b/components/common/validator.js new file mode 100644 index 0000000..1c7d1e9 --- /dev/null +++ b/components/common/validator.js @@ -0,0 +1,30 @@ +export function isFunction(val) { + return typeof val === 'function'; +} +export function isPlainObject(val) { + return val !== null && typeof val === 'object' && !Array.isArray(val); +} +export function isPromise(val) { + return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch); +} +export function isDef(value) { + return value !== undefined && value !== null; +} +export function isObj(x) { + const type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +} +export function isNumber(value) { + return /^\d+(\.\d+)?$/.test(value); +} +export function isBoolean(value) { + return typeof value === 'boolean'; +} +const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i; +const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i; +export function isImageUrl(url) { + return IMAGE_REGEXP.test(url); +} +export function isVideoUrl(url) { + return VIDEO_REGEXP.test(url); +} diff --git a/components/common/version.js b/components/common/version.js new file mode 100644 index 0000000..01f24f8 --- /dev/null +++ b/components/common/version.js @@ -0,0 +1,31 @@ +import { getSystemInfoSync } from './utils'; +function compareVersion(v1, v2) { + v1 = v1.split('.'); + v2 = v2.split('.'); + const len = Math.max(v1.length, v2.length); + while (v1.length < len) { + v1.push('0'); + } + while (v2.length < len) { + v2.push('0'); + } + for (let i = 0; i < len; i++) { + const num1 = parseInt(v1[i], 10); + const num2 = parseInt(v2[i], 10); + if (num1 > num2) { + return 1; + } + if (num1 < num2) { + return -1; + } + } + return 0; +} +export function canIUseModel() { + const system = getSystemInfoSync(); + return compareVersion(system.SDKVersion, '2.9.3') >= 0; +} +export function canIUseFormFieldButton() { + const system = getSystemInfoSync(); + return compareVersion(system.SDKVersion, '2.10.3') >= 0; +} diff --git a/components/count-down/index.js b/components/count-down/index.js new file mode 100644 index 0000000..a60ca79 --- /dev/null +++ b/components/count-down/index.js @@ -0,0 +1,98 @@ +import { VantComponent } from '../common/component'; +import { isSameSecond, parseFormat, parseTimeData } from './utils'; +function simpleTick(fn) { + return setTimeout(fn, 30); +} +VantComponent({ + props: { + useSlot: Boolean, + millisecond: Boolean, + time: { + type: Number, + observer: 'reset' + }, + format: { + type: String, + value: 'HH:mm:ss' + }, + autoStart: { + type: Boolean, + value: true + } + }, + data: { + timeData: parseTimeData(0), + formattedTime: '0' + }, + destroyed() { + clearTimeout(this.tid); + this.tid = null; + }, + methods: { + // 开始 + start() { + if (this.counting) { + return; + } + this.counting = true; + this.endTime = Date.now() + this.remain; + this.tick(); + }, + // 暂停 + pause() { + this.counting = false; + clearTimeout(this.tid); + }, + // 重置 + reset() { + this.pause(); + this.remain = this.data.time; + this.setRemain(this.remain); + if (this.data.autoStart) { + this.start() + } + }, + tick() { + if (this.data.millisecond) { + this.microTick() + } + else { + this.macroTick() + } + }, + microTick() { + this.tid = simpleTick(() => { + this.setRemain(this.getRemain()); + if (this.remain !== 0) { + this.microTick() + } + }); + }, + macroTick() { + this.tid = simpleTick(() => { + const remain = this.getRemain() + if (!isSameSecond(remain, this.remain) || remain === 0) { + this.setRemain(remain) + } + if (this.remain !== 0) { + this.macroTick() + } + }); + }, + getRemain() { + return Math.max(this.endTime - Date.now(), 0); + }, + setRemain(remain) { + this.remain = remain; + const timeData = parseTimeData(remain); + if (this.data.useSlot) { + this.$emit('change', timeData) + } + this.setData({ formattedTime: parseFormat(this.data.format, timeData) }) + if (remain === 0) { + this.pause() + this.$emit('finish') + } + } + } +}); diff --git a/components/count-down/index.json b/components/count-down/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/count-down/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/count-down/index.wxml b/components/count-down/index.wxml new file mode 100644 index 0000000..e206e16 --- /dev/null +++ b/components/count-down/index.wxml @@ -0,0 +1,4 @@ + + + {{ formattedTime }} + diff --git a/components/count-down/index.wxss b/components/count-down/index.wxss new file mode 100644 index 0000000..bc33f5d --- /dev/null +++ b/components/count-down/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-count-down{color:#323233;color:var(--count-down-text-color,#323233);font-size:14px;font-size:var(--count-down-font-size,14px);line-height:20px;line-height:var(--count-down-line-height,20px)} \ No newline at end of file diff --git a/components/count-down/utils.js b/components/count-down/utils.js new file mode 100644 index 0000000..3237988 --- /dev/null +++ b/components/count-down/utils.js @@ -0,0 +1,57 @@ +function padZero(num, targetLength = 2) { + let str = num + ''; + while (str.length < targetLength) { + str = '0' + str; + } + return str; +} +const SECOND = 1000; +const MINUTE = 60 * SECOND; +const HOUR = 60 * MINUTE; +const DAY = 24 * HOUR; +export function parseTimeData(time) { + const days = Math.floor(time / DAY); + const hours = Math.floor((time % DAY) / HOUR); + const minutes = Math.floor((time % HOUR) / MINUTE); + const seconds = Math.floor((time % MINUTE) / SECOND); + const milliseconds = Math.floor(time % SECOND); + return { + days, + hours, + minutes, + seconds, + milliseconds + }; +} +export function parseFormat(format, timeData) { + const { days } = timeData; + let { hours, minutes, seconds, milliseconds } = timeData; + if (format.indexOf('DD') === -1) { + hours += days * 24; + } + else { + format = format.replace('DD', padZero(days)); + } + if (format.indexOf('HH') === -1) { + minutes += hours * 60; + } + else { + format = format.replace('HH', padZero(hours)); + } + if (format.indexOf('mm') === -1) { + seconds += minutes * 60; + } + else { + format = format.replace('mm', padZero(minutes)); + } + if (format.indexOf('ss') === -1) { + milliseconds += seconds * 1000; + } + else { + format = format.replace('ss', padZero(seconds)); + } + return format.replace('SSS', padZero(milliseconds, 3)); +} +export function isSameSecond(time1, time2) { + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000); +} diff --git a/components/datetime-picker/index.js b/components/datetime-picker/index.js new file mode 100644 index 0000000..5944619 --- /dev/null +++ b/components/datetime-picker/index.js @@ -0,0 +1,297 @@ +import { VantComponent } from '../common/component'; +import { isDef } from '../common/utils'; +import { pickerProps } from '../picker/shared'; +const currentYear = new Date().getFullYear(); +function isValidDate(date) { + return isDef(date) && !isNaN(new Date(date).getTime()); +} +function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} +function padZero(val) { + return `00${val}`.slice(-2); +} +function times(n, iteratee) { + let index = -1; + const result = Array(n < 0 ? 0 : n); + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} +function getTrueValue(formattedValue) { + if (!formattedValue) + return; + while (isNaN(parseInt(formattedValue, 10))) { + formattedValue = formattedValue.slice(1); + } + return parseInt(formattedValue, 10); +} +function getMonthEndDay(year, month) { + return 32 - new Date(year, month - 1, 32).getDate(); +} +const defaultFormatter = (_, value) => value; +VantComponent({ + classes: ['active-class', 'toolbar-class', 'column-class'], + props: Object.assign(Object.assign({}, pickerProps), { value: { + type: null, + observer: 'updateValue' + }, filter: null, type: { + type: String, + value: 'datetime', + observer: 'updateValue' + }, showToolbar: { + type: Boolean, + value: true + }, formatter: { + type: null, + value: defaultFormatter + }, minDate: { + type: Number, + value: new Date(currentYear - 10, 0, 1).getTime(), + observer: 'updateValue' + }, maxDate: { + type: Number, + value: new Date(currentYear + 10, 11, 31).getTime(), + observer: 'updateValue' + }, minHour: { + type: Number, + value: 0, + observer: 'updateValue' + }, maxHour: { + type: Number, + value: 23, + observer: 'updateValue' + }, minMinute: { + type: Number, + value: 0, + observer: 'updateValue' + }, maxMinute: { + type: Number, + value: 59, + observer: 'updateValue' + } }), + data: { + innerValue: Date.now(), + columns: [] + }, + methods: { + updateValue() { + const { data } = this; + const val = this.correctValue(this.data.value); + const isEqual = val === data.innerValue; + if (!isEqual) { + this.updateColumnValue(val).then(() => { + this.$emit('input', val); + }); + } + else { + this.updateColumns(); + } + }, + getPicker() { + if (this.picker == null) { + this.picker = this.selectComponent('.van-datetime-picker'); + const { picker } = this; + const { setColumnValues } = picker; + picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]); + } + return this.picker; + }, + updateColumns() { + const { formatter = defaultFormatter } = this.data; + const results = this.getOriginColumns().map(column => ({ + values: column.values.map(value => formatter(column.type, value)) + })); + return this.set({ columns: results }); + }, + getOriginColumns() { + const { filter } = this.data; + const results = this.getRanges().map(({ type, range }) => { + let values = times(range[1] - range[0] + 1, index => { + let value = range[0] + index; + value = type === 'year' ? `${value}` : padZero(value); + return value; + }); + if (filter) { + values = filter(type, values); + } + return { type, values }; + }); + return results; + }, + getRanges() { + const { data } = this; + if (data.type === 'time') { + return [ + { + type: 'hour', + range: [data.minHour, data.maxHour] + }, + { + type: 'minute', + range: [data.minMinute, data.maxMinute] + } + ]; + } + const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue); + const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue); + const result = [ + { + type: 'year', + range: [minYear, maxYear] + }, + { + type: 'month', + range: [minMonth, maxMonth] + }, + { + type: 'day', + range: [minDate, maxDate] + }, + { + type: 'hour', + range: [minHour, maxHour] + }, + { + type: 'minute', + range: [minMinute, maxMinute] + } + ]; + if (data.type === 'date') + result.splice(3, 2); + if (data.type === 'year-month') + result.splice(2, 3); + return result; + }, + correctValue(value) { + const { data } = this; + // validate value + const isDateType = data.type !== 'time'; + if (isDateType && !isValidDate(value)) { + value = data.minDate; + } + else if (!isDateType && !value) { + const { minHour } = data; + value = `${padZero(minHour)}:00`; + } + // time type + if (!isDateType) { + let [hour, minute] = value.split(':'); + hour = padZero(range(hour, data.minHour, data.maxHour)); + minute = padZero(range(minute, data.minMinute, data.maxMinute)); + return `${hour}:${minute}`; + } + // date type + value = Math.max(value, data.minDate); + value = Math.min(value, data.maxDate); + return value; + }, + getBoundary(type, innerValue) { + const value = new Date(innerValue); + const boundary = new Date(this.data[`${type}Date`]); + const year = boundary.getFullYear(); + let month = 1; + let date = 1; + let hour = 0; + let minute = 0; + if (type === 'max') { + month = 12; + date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); + hour = 23; + minute = 59; + } + if (value.getFullYear() === year) { + month = boundary.getMonth() + 1; + if (value.getMonth() + 1 === month) { + date = boundary.getDate(); + if (value.getDate() === date) { + hour = boundary.getHours(); + if (value.getHours() === hour) { + minute = boundary.getMinutes(); + } + } + } + } + return { + [`${type}Year`]: year, + [`${type}Month`]: month, + [`${type}Date`]: date, + [`${type}Hour`]: hour, + [`${type}Minute`]: minute + }; + }, + onCancel() { + this.$emit('cancel'); + }, + onConfirm() { + this.$emit('confirm', this.data.innerValue); + }, + onChange() { + const { data } = this; + let value; + const picker = this.getPicker(); + if (data.type === 'time') { + const indexes = picker.getIndexes(); + value = `${+data.columns[0].values[indexes[0]]}:${+data.columns[1].values[indexes[1]]}`; + } + else { + const values = picker.getValues(); + const year = getTrueValue(values[0]); + const month = getTrueValue(values[1]); + const maxDate = getMonthEndDay(year, month); + let date = getTrueValue(values[2]); + if (data.type === 'year-month') { + date = 1; + } + date = date > maxDate ? maxDate : date; + let hour = 0; + let minute = 0; + if (data.type === 'datetime') { + hour = getTrueValue(values[3]); + minute = getTrueValue(values[4]); + } + value = new Date(year, month - 1, date, hour, minute); + } + value = this.correctValue(value); + this.updateColumnValue(value).then(() => { + this.$emit('input', value); + this.$emit('change', picker); + }); + }, + updateColumnValue(value) { + let values = []; + const { type, formatter = defaultFormatter } = this.data; + const picker = this.getPicker(); + if (type === 'time') { + const pair = value.split(':'); + values = [ + formatter('hour', pair[0]), + formatter('minute', pair[1]) + ]; + } + else { + const date = new Date(value); + values = [ + formatter('year', `${date.getFullYear()}`), + formatter('month', padZero(date.getMonth() + 1)) + ]; + if (type === 'date') { + values.push(formatter('day', padZero(date.getDate()))); + } + if (type === 'datetime') { + values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes()))); + } + } + return this.set({ innerValue: value }) + .then(() => this.updateColumns()) + .then(() => picker.setValues(values)); + } + }, + created() { + const innerValue = this.correctValue(this.data.value); + this.updateColumnValue(innerValue).then(() => { + this.$emit('input', innerValue); + }); + } +}); diff --git a/components/datetime-picker/index.json b/components/datetime-picker/index.json new file mode 100644 index 0000000..a778e91 --- /dev/null +++ b/components/datetime-picker/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-picker": "../picker/index" + } +} diff --git a/components/datetime-picker/index.wxml b/components/datetime-picker/index.wxml new file mode 100644 index 0000000..ade2202 --- /dev/null +++ b/components/datetime-picker/index.wxml @@ -0,0 +1,16 @@ + diff --git a/components/datetime-picker/index.wxss b/components/datetime-picker/index.wxss new file mode 100644 index 0000000..99694d6 --- /dev/null +++ b/components/datetime-picker/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; \ No newline at end of file diff --git a/components/dialog/dialog.js b/components/dialog/dialog.js new file mode 100644 index 0000000..2891917 --- /dev/null +++ b/components/dialog/dialog.js @@ -0,0 +1,68 @@ +let queue = []; + +function getContext() { + const pages = getCurrentPages(); + return pages[pages.length - 1]; +} +const Dialog = options => { + options = Object.assign(Object.assign({}, Dialog.currentOptions), options); + return new Promise((resolve, reject) => { + const context = options.context || getContext(); + const dialog = context.selectComponent(options.selector); + delete options.context; + delete options.selector; + if (dialog) { + dialog.setData(Object.assign({ + onCancel: reject, + onConfirm: resolve + }, options)); + queue.push(dialog); + } else { + console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确'); + } + }); +}; +Dialog.defaultOptions = { + show: true, + title: '', + width: null, + message: '', + zIndex: 60, + overlay: true, + selector: '#van-dialog', + className: '', + asyncClose: false, + transition: 'fade', + customStyle: '', + messageAlign: '', + overlayStyle: '', + confirmButtonText: '确认', + cancelButtonText: '取消', + showConfirmButton: true, + showCancelButton: false, + closeOnClickOverlay: false, + confirmButtonOpenType: '' +}; +Dialog.alert = Dialog; +Dialog.confirm = options => Dialog(Object.assign({ + showCancelButton: true +}, options)); +Dialog.close = () => { + queue.forEach(dialog => { + dialog.close(); + }); + queue = []; +}; +Dialog.stopLoading = () => { + queue.forEach(dialog => { + dialog.stopLoading(); + }); +}; +Dialog.setDefaultOptions = options => { + Object.assign(Dialog.currentOptions, options); +}; +Dialog.resetDefaultOptions = () => { + Dialog.currentOptions = Object.assign({}, Dialog.defaultOptions); +}; +Dialog.resetDefaultOptions(); +export default Dialog; \ No newline at end of file diff --git a/components/dialog/index.js b/components/dialog/index.js new file mode 100644 index 0000000..10b3b0a --- /dev/null +++ b/components/dialog/index.js @@ -0,0 +1,104 @@ +import { VantComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType} from '../mixins/open-type'; +import {GRAY,BLUE } from '../common/color'; +VantComponent({ + mixins: [button, openType], + props: { + show: { + type: Boolean, + observer(show) { + !show && this.stopLoading(); + } + }, + title: String, + message: String, + useSlot: Boolean, + className: String, + customStyle: String, + asyncClose: Boolean, + messageAlign: String, + overlayStyle: String, + useTitleSlot: Boolean, + showCancelButton: Boolean, + closeOnClickOverlay: Boolean, + confirmButtonOpenType: String, + width: null, + zIndex: { + type: Number, + value: 20 + }, + confirmButtonText: { + type: String, + value: '确认' + }, + cancelButtonText: { + type: String, + value: '取消' + }, + confirmButtonColor: { + type: String, + value: BLUE + }, + cancelButtonColor: { + type: String, + value: GRAY + }, + showConfirmButton: { + type: Boolean, + value: true + }, + overlay: { + type: Boolean, + value: true + }, + transition: { + type: String, + value: 'scale' + }, + logined: { + type: Boolean, + value: false + } + }, + data: { + loading: { confirm: false, cancel: false } + }, + methods: { + onConfirm() { + this.handleAction('confirm'); + }, + onCancel() { + this.handleAction('cancel'); + }, + onClickOverlay() { + this.onClose('overlay'); + }, + handleAction(action) { + if (this.data.asyncClose) { + this.setData({ [`loading.${action}`]: true }); + } + if (!this.data.logined) { + this.onClose(action) + } + }, + close() { + this.setData({ show: false }); + }, + stopLoading() { + this.setData({ loading: { confirm: false, cancel: false } }); + }, + onClose(action) { + if (!this.data.asyncClose) { + this.close(); + } + this.$emit('close', action); + // 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading + this.$emit(action, { dialog: this }); + const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel']; + if (callback) { + callback(this); + } + } + } +}); \ No newline at end of file diff --git a/components/dialog/index.json b/components/dialog/index.json new file mode 100644 index 0000000..e2ee09a --- /dev/null +++ b/components/dialog/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-popup": "../popup/index", + "van-button": "../button/index" + } +} diff --git a/components/dialog/index.wxml b/components/dialog/index.wxml new file mode 100644 index 0000000..57d8d11 --- /dev/null +++ b/components/dialog/index.wxml @@ -0,0 +1,35 @@ + + + + + + {{ title }} + + + + + {{ message }} + + + + + {{ cancelButtonText }} + + + {{ confirmButtonText }} + + + \ No newline at end of file diff --git a/components/dialog/index.wxss b/components/dialog/index.wxss new file mode 100644 index 0000000..9e3d20f --- /dev/null +++ b/components/dialog/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-dialog{top:45%!important;overflow:hidden;width:320px;width:var(--dialog-width,320px);font-size:16px;font-size:var(--dialog-font-size,16px);border-radius:16rpx;border-radius:var(--dialog-border-radius,16rpx);background-color:#fff;background-color:var(--dialog-background-color,#fff)}@media (max-width:321px){.van-dialog{width:90%;width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-size:32rpx;color:#333333;text-align:center;padding-top:24px;padding-top:var(--dialog-header-padding-top,24px);font-weight:500;font-weight:var(--dialog-header-font-weight,500);line-height:24px;line-height:var(--dialog-header-line-height,24px)}.van-dialog__header--isolated{padding:24px 0;padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{overflow-y:auto;text-align:center;-webkit-overflow-scrolling:touch;font-size:14px;font-size:var(--dialog-message-font-size,14px);line-height:20px;line-height:var(--dialog-message-line-height,20px);max-height:60vh;max-height:var(--dialog-message-max-height,60vh);padding:24px;padding:var(--dialog-message-padding,24px)}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--has-title{padding-top:12px;padding-top:var(--dialog-has-title-message-padding-top,12px);color:#646566;color:var(--dialog-has-title-message-text-color,#646566)}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-dialog-bounce-leave-active{-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9);opacity:0} \ No newline at end of file diff --git a/components/divider/index.js b/components/divider/index.js new file mode 100644 index 0000000..73f833d --- /dev/null +++ b/components/divider/index.js @@ -0,0 +1,33 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + dashed: { + type: Boolean, + value: false + }, + hairline: { + type: Boolean, + value: false + }, + contentPosition: { + type: String, + value: '' + }, + fontSize: { + type: Number, + value: '' + }, + borderColor: { + type: String, + value: '' + }, + textColor: { + type: String, + value: '' + }, + customStyle: { + type: String, + value: '' + } + } +}); diff --git a/components/divider/index.json b/components/divider/index.json new file mode 100644 index 0000000..e8cfaaf --- /dev/null +++ b/components/divider/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/components/divider/index.wxml b/components/divider/index.wxml new file mode 100644 index 0000000..3237bb4 --- /dev/null +++ b/components/divider/index.wxml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/components/divider/index.wxss b/components/divider/index.wxss new file mode 100644 index 0000000..89e0bc2 --- /dev/null +++ b/components/divider/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-divider{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin:16px 0;margin:var(--divider-margin,24rpx 0);color:#969799;color:var(--divider-text-color,#969799);font-size:14px;font-size:var(--divider-font-size,14px);line-height:24px;line-height:var(--divider-line-height,24px);border:0 solid #ebedf0;border-color:var(--divider-border-color,#ebedf0)}.van-divider:after,.van-divider:before{display:block;-webkit-flex:1;flex:1;box-sizing:border-box;height:1px;border-color:inherit;border-style:inherit;border-width:1px 0 0}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:16px;margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:16px;margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:10%;max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:10%;max-width:var(--divider-content-right-width,10%)} \ No newline at end of file diff --git a/components/field/index.js b/components/field/index.js new file mode 100644 index 0000000..e27bae4 --- /dev/null +++ b/components/field/index.js @@ -0,0 +1,94 @@ +import { VantComponent } from '../common/component'; +import { commonProps, inputProps, textareaProps } from './props'; +VantComponent({ + field: true, + classes: ['input-class', 'right-icon-class'], + props: Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), inputProps), textareaProps), { size: String, icon: String, label: String, error: Boolean, center: Boolean, isLink: Boolean, leftIcon: String, rightIcon: String, autosize: [Boolean, Object], readonly: { + type: Boolean, + observer: 'setShowClear' + }, required: Boolean, iconClass: String, clearable: { + type: Boolean, + observer: 'setShowClear' + }, clickable: Boolean, inputAlign: String, customStyle: String, errorMessage: String, arrowDirection: String, showWordLimit: Boolean, errorMessageAlign: String, border: { + type: Boolean, + value: true + }, titleWidth: { + type: String, + value: '90px' + } }), + data: { + focused: false, + innerValue: '', + showClear: false + }, + created() { + this.value = this.data.value + this.setData({ innerValue: this.value }) + }, + methods: { + onInput(event) { + const { value = '' } = event.detail || {} + this.value = value + this.setShowClear() + this.emitChange() + }, + onFocus(event) { + this.data.focused = true + this.setShowClear() + this.$emit('focus', event.detail) + }, + onBlur(event) { + this.data.focused = false + this.setShowClear() + this.$emit('blur', event.detail) + }, + onClickInput(event) { + this.$emit('click-input', event.detail); + }, + onClickIcon() { + this.$emit('click-icon') + }, + onClear() { + this.setData({ innerValue: '' }) + this.value = '' + this.setShowClear() + wx.nextTick(() => { + this.emitChange() + this.$emit('clear', '') + }); + }, + onConfirm(event) { + const { value = '' } = event.detail || {} + this.value = value + this.setShowClear() + this.$emit('confirm', value) + }, + setValue(value) { + this.value = value + this.setShowClear() + if (value === '') { + this.setData({ innerValue: '' }) + } + this.emitChange(); + }, + onLineChange(event) { + this.$emit('linechange', event.detail) + }, + onKeyboardHeightChange(event) { + this.$emit('keyboardheightchange', event.detail) + }, + emitChange() { + this.setData({ value: this.value }); + wx.nextTick(() => { + this.$emit('input', this.value); + this.$emit('change', this.value); + }) + }, + setShowClear() { + const { clearable, readonly, focused } = this.data; + const { value } = this; + this.setData({ showClear: clearable && focused && !!value && !readonly }) + }, + noop() { } + } +}); diff --git a/components/field/index.json b/components/field/index.json new file mode 100644 index 0000000..8809c46 --- /dev/null +++ b/components/field/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-cell": "../cell/index", + "van-icon": "../icon/index" + } +} \ No newline at end of file diff --git a/components/field/index.wxml b/components/field/index.wxml new file mode 100644 index 0000000..b9da54d --- /dev/null +++ b/components/field/index.wxml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + {{ value.length }} + /{{ maxlength }} + + + {{ errorMessage }} + + \ No newline at end of file diff --git a/components/field/index.wxs b/components/field/index.wxs new file mode 100644 index 0000000..51b0378 --- /dev/null +++ b/components/field/index.wxs @@ -0,0 +1,21 @@ +/* eslint-disable */ +var utils = require('../wxs/utils.wxs'); + +function inputStyle(autosize) { + if (autosize.constructor === 'Object') { + var style = ''; + if (autosize.minHeight) { + style += 'min-height:' + utils.addUnit(autosize.minHeight) + ';'; + } + if (autosize.maxHeight) { + style += 'max-height:' + utils.addUnit(autosize.maxHeight) + ';'; + } + return style; + } + + return ''; +} + +module.exports = { + inputStyle: inputStyle +}; diff --git a/components/field/index.wxss b/components/field/index.wxss new file mode 100644 index 0000000..782b802 --- /dev/null +++ b/components/field/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-field{--cell-icon-size:16px;--cell-icon-size:var(--field-icon-size,16px)}.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{line-height:1.2em}.van-field__body--textarea,.van-field__input{min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__input{position:relative;display:block;box-sizing:border-box;width:100%;margin:0;padding:0;line-height:inherit;text-align:left;background-color:initial;border:0;resize:none;color:#323233;color:var(--field-input-text-color,#323233);height:24px;height:var(--cell-line-height,24px)}.van-field__input--textarea{height:18px;height:var(--field-text-area-min-height,18px);min-height:18px;min-height:var(--field-text-area-min-height,18px)}.van-field__input--error{color:#ee0a24;color:var(--field-input-error-text-color,#ee0a24)}.van-field__input--disabled{background-color:initial;opacity:1;color:#969799;color:var(--field-input-disabled-text-color,#969799)}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__placeholder{position:absolute;top:0;right:0;left:0;pointer-events:none;color:#969799;color:var(--field-placeholder-text-color,#969799)}.van-field__placeholder--error{color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;vertical-align:middle;padding:0 8px;padding:0 var(--padding-xs,8px);margin-right:-8px;margin-right:-var(--padding-xs,8px)}.van-field__button,.van-field__clear-root,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear-root{font-size:16px;font-size:var(--field-clear-icon-size,16px);color:#c8c9cc;color:var(--field-clear-icon-color,#c8c9cc)}.van-field__icon-container{font-size:16px;font-size:var(--field-icon-size,16px);color:#969799;color:var(--field-icon-container-color,#969799)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:8px;padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{text-align:left;font-size:12px;font-size:var(--field-error-message-text-font-size,12px);color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{text-align:right;margin-top:4px;margin-top:var(--padding-base,4px);color:#646566;color:var(--field-word-limit-color,#646566);font-size:12px;font-size:var(--field-word-limit-font-size,12px);line-height:16px;line-height:var(--field-word-limit-line-height,16px)}.van-field__word-num{display:inline}.van-field__word-num--full{color:#ee0a24;color:var(--field-word-num-full-color,#ee0a24)} \ No newline at end of file diff --git a/components/field/props.js b/components/field/props.js new file mode 100644 index 0000000..bceb8fd --- /dev/null +++ b/components/field/props.js @@ -0,0 +1,63 @@ +export const commonProps = { + value: { + type: String, + observer(value) { + if (value !== this.value) { + this.setData({ innerValue: value }); + this.value = value; + } + } + }, + placeholder: String, + placeholderStyle: String, + placeholderClass: String, + disabled: Boolean, + maxlength: { + type: Number, + value: -1 + }, + cursorSpacing: { + type: Number, + value: 50 + }, + autoFocus: Boolean, + focus: Boolean, + cursor: { + type: Number, + value: -1 + }, + selectionStart: { + type: Number, + value: -1 + }, + selectionEnd: { + type: Number, + value: -1 + }, + adjustPosition: { + type: Boolean, + value: true + }, + holdKeyboard: Boolean +}; +export const inputProps = { + type: { + type: String, + value: 'text' + }, + password: Boolean, + confirmType: String, + confirmHold: Boolean +}; +export const textareaProps = { + autoHeight: Boolean, + fixed: Boolean, + showConfirmBar: { + type: Boolean, + value: true + }, + disableDefaultPadding: { + type: Boolean, + value: true + }, +}; diff --git a/components/grid-item/index.js b/components/grid-item/index.js new file mode 100644 index 0000000..7d2ac40 --- /dev/null +++ b/components/grid-item/index.js @@ -0,0 +1,71 @@ +import { link } from '../mixins/link'; +import { VantComponent } from '../common/component'; +import { addUnit } from '../common/utils'; +VantComponent({ + relation: { + name: 'grid', + type: 'ancestor', + current: 'grid-item', + }, + classes: ['content-class', 'icon-class', 'text-class'], + mixins: [link], + props: { + icon: String, + dot: Boolean, + info: null, + text: String, + contentStyle: String, + useSlot: Boolean + }, + data: { + viewStyle: '', + }, + mounted() { + this.updateStyle(); + }, + methods: { + updateStyle() { + if (!this.parent) { + return; + } + const { data, children } = this.parent; + const { columnNum, border, square, gutter, clickable, center } = data; + const width = `${100 / columnNum}%`; + const styleWrapper = []; + styleWrapper.push(`width: ${width}`); + if (square) { + styleWrapper.push(`padding-top: ${width}`); + } + if (gutter) { + const gutterValue = addUnit(gutter); + styleWrapper.push(`padding-right: ${gutterValue}`); + const index = children.indexOf(this); + if (index >= columnNum) { + styleWrapper.push(`margin-top: ${gutterValue}`); + } + } + let contentStyle = ''; + if (square && gutter) { + const gutterValue = addUnit(gutter); + contentStyle = ` + right: ${gutterValue}; + bottom: ${gutterValue}; + height: auto; + `; + } + this.setData({ + viewStyle: styleWrapper.join('; '), + // contentStyle, + center, + border, + square, + gutter, + clickable + }); + }, + onClick() { + this.$emit('click'); + this.jumpLink(); + } + } +}); diff --git a/components/grid-item/index.json b/components/grid-item/index.json new file mode 100644 index 0000000..0a336c0 --- /dev/null +++ b/components/grid-item/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/components/grid-item/index.wxml b/components/grid-item/index.wxml new file mode 100644 index 0000000..69fdb61 --- /dev/null +++ b/components/grid-item/index.wxml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + {{ text }} + + + + + \ No newline at end of file diff --git a/components/grid-item/index.wxss b/components/grid-item/index.wxss new file mode 100644 index 0000000..7f2e818 --- /dev/null +++ b/components/grid-item/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-grid-item{position:relative;float:left;box-sizing:border-box}.van-grid-item--square{height:0}.van-grid-item__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;box-sizing:border-box;height:100%;padding:16px 8px;padding:var(--grid-item-content-padding,16px 8px);background-color:#fff;background-color:var(--grid-item-content-background-color,#fff)}.van-grid-item__content:after{z-index:1;border-width:0 1px 1px 0;border-bottom-width:var(--border-width-base,1px);border-right-width:var(--border-width-base,1px);border-top-width:0}.van-grid-item__content--surround:after{border-width:1px;border-width:var(--border-width-base,1px)}.van-grid-item__content--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-grid-item__content--square{position:absolute;top:0;right:0;left:0}.van-grid-item__content--clickable:active{background-color:#f2f3f5;background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{font-size:26px;font-size:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:#646566;color:var(--grid-item-text-color,#646566);font-size:12px;font-size:var(--grid-item-text-font-size,12px)} \ No newline at end of file diff --git a/components/grid/index.js b/components/grid/index.js new file mode 100644 index 0000000..0180b50 --- /dev/null +++ b/components/grid/index.js @@ -0,0 +1,57 @@ +import { VantComponent } from '../common/component'; +import { addUnit } from '../common/utils'; +VantComponent({ + relation: { + name: 'grid-item', + type: 'descendant', + current: 'grid', + }, + props: { + square: { + type: Boolean, + observer: 'updateChildren' + }, + gutter: { + type: [Number, String], + value: 0, + observer: 'updateChildren' + }, + clickable: { + type: Boolean, + observer: 'updateChildren' + }, + columnNum: { + type: Number, + value: 4, + observer: 'updateChildren' + }, + center: { + type: Boolean, + value: true, + observer: 'updateChildren' + }, + border: { + type: Boolean, + value: false, + observer: 'updateChildren' + } + }, + data: { + viewStyle: '', + }, + created() { + const { gutter } = this.data; + if (gutter) { + this.setData({ + viewStyle: `padding-left: ${addUnit(gutter)}` + }); + } + }, + methods: { + updateChildren() { + this.children.forEach((child) => { + child.updateStyle(); + }); + } + } +}); diff --git a/components/grid/index.json b/components/grid/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/grid/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/grid/index.wxml b/components/grid/index.wxml new file mode 100644 index 0000000..c5a545f --- /dev/null +++ b/components/grid/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/components/grid/index.wxss b/components/grid/index.wxss new file mode 100644 index 0000000..327fc5e --- /dev/null +++ b/components/grid/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-grid{position:relative;box-sizing:border-box;overflow:hidden} \ No newline at end of file diff --git a/components/helpers/arrayTreeFilter.js b/components/helpers/arrayTreeFilter.js new file mode 100644 index 0000000..94736eb --- /dev/null +++ b/components/helpers/arrayTreeFilter.js @@ -0,0 +1,24 @@ +/** + * https://github.com/afc163/array-tree-filter + */ +function arrayTreeFilter(data, filterFn, options) { + options = options || {} + options.childrenKeyName = options.childrenKeyName || 'children' + let children = data || [] + const result = [] + let level = 0 + do { + const foundItem = children.filter(function(item) { + return filterFn(item, level) + })[0] + if (!foundItem) { + break + } + result.push(foundItem) + children = foundItem[options.childrenKeyName] || [] + level += 1 + } while (children.length > 0) + return result +} + +export default arrayTreeFilter \ No newline at end of file diff --git a/components/helpers/baseComponent.js b/components/helpers/baseComponent.js new file mode 100644 index 0000000..7c5d66d --- /dev/null +++ b/components/helpers/baseComponent.js @@ -0,0 +1,77 @@ +import computedBehavior from './computedBehavior' +import relationsBehavior from './relationsBehavior' +import safeAreaBehavior from './safeAreaBehavior' +import safeSetDataBehavior from './safeSetDataBehavior' +import funcBehavior from './funcBehavior' +import compareVersion from './compareVersion' + +const { platform, SDKVersion } = wx.getSystemInfoSync() +const libVersion = '2.6.6' + +// check SDKVersion +if (platform === 'devtools' && compareVersion(SDKVersion, libVersion) < 0) { + if (wx && wx.showModal) { + wx.showModal({ + title: '提示', + content: `当前基础库版本(${SDKVersion})过低,无法使用 Wux Weapp 组件库,请更新基础库版本 >=${libVersion} 后重试。`, + }) + } +} + +const baseComponent = (options = {}) => { + // add default externalClasses + options.externalClasses = [ + 'wux-class', + 'wux-hover-class', + ...(options.externalClasses = options.externalClasses || []), + ] + + // add default behaviors + options.behaviors = [ + relationsBehavior, + safeSetDataBehavior, + ...(options.behaviors = options.behaviors || []), + computedBehavior, // make sure it's triggered + ] + + // use safeArea + if (options.useSafeArea) { + options.behaviors = [...options.behaviors, safeAreaBehavior] + delete options.useSafeArea + } + + // use func + if (options.useFunc) { + options.behaviors = [...options.behaviors, funcBehavior] + delete options.useFunc + } + + // use field + if (options.useField) { + options.behaviors = [...options.behaviors, 'wx://form-field'] + delete options.useField + } + + // use export + if (options.useExport) { + options.behaviors = [...options.behaviors, 'wx://component-export'] + options.methods = { + export () { + return this + }, + ...options.methods, + } + delete options.useExport + } + + // add default options + options.options = { + multipleSlots: true, + addGlobalClass: true, + ...options.options, + } + + return Component(options) +} + +export default baseComponent diff --git a/components/helpers/checkIPhoneX.js b/components/helpers/checkIPhoneX.js new file mode 100644 index 0000000..5d65c52 --- /dev/null +++ b/components/helpers/checkIPhoneX.js @@ -0,0 +1,29 @@ +/** + * 获取系统信息 + */ + +let systemInfo = null + +export const getSystemInfo = (isForce) => { + if (!systemInfo || isForce) { + try { + systemInfo = wx.getSystemInfoSync() + } catch(e) { /* Ignore */ } + } + + return systemInfo +} + +// iPhoneX 竖屏安全区域 +export const safeAreaInset = { + top: 88, // StatusBar & NavBar + left: 0, + right: 0, + bottom: 34, // Home Indicator +} + +const isIPhoneX = ({ model, platform }) => { + return /iPhone X/.test(model) && platform === 'ios' +} + +export const checkIPhoneX = (isForce) => isIPhoneX(getSystemInfo(isForce)) diff --git a/components/helpers/classNames.js b/components/helpers/classNames.js new file mode 100644 index 0000000..e2eb2d4 --- /dev/null +++ b/components/helpers/classNames.js @@ -0,0 +1,39 @@ +/*! + Copyright (c) 2018 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +/* global define */ +'use strict'; + +var hasOwn = {}.hasOwnProperty; + +function classNames() { + var classes = []; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + + var argType = typeof arg; + + if (argType === 'string' || argType === 'number') { + classes.push(arg); + } else if (Array.isArray(arg) && arg.length) { + var inner = classNames.apply(null, arg); + if (inner) { + classes.push(inner); + } + } else if (argType === 'object') { + for (var key in arg) { + if (hasOwn.call(arg, key) && arg[key]) { + classes.push(key); + } + } + } + } + + return classes.join(' '); +} + +export default classNames \ No newline at end of file diff --git a/components/helpers/colors.js b/components/helpers/colors.js new file mode 100644 index 0000000..fc4b9d8 --- /dev/null +++ b/components/helpers/colors.js @@ -0,0 +1,27 @@ +/** + * Don't modify this file! + * Colors generated by themes! + */ + +/* eslint-disable */ + +export const colors = { + 'light': '#ddd', + 'stable': '#b2b2b2', + 'positive': '#387ef5', + 'calm': '#11c1f3', + 'balanced': '#33cd5f', + 'energized': '#ffc900', + 'assertive': '#ef473a', + 'royal': '#886aea', + 'dark': '#444', +} + +export const isPresetColor = (color) => { + if (!color) { + return false + } + return colors[color] ? colors[color] : color +} + +/* eslint-enable */ diff --git a/components/helpers/compareVersion.js b/components/helpers/compareVersion.js new file mode 100644 index 0000000..47a2d59 --- /dev/null +++ b/components/helpers/compareVersion.js @@ -0,0 +1,27 @@ +function compareVersion(v1, v2) { + const $v1 = v1.split('.') + const $v2 = v2.split('.') + const len = Math.max($v1.length, $v2.length) + + while ($v1.length < len) { + $v1.push('0') + } + while ($v2.length < len) { + $v2.push('0') + } + + for (let i = 0; i < len; i++) { + const num1 = parseInt($v1[i]) + const num2 = parseInt($v2[i]) + + if (num1 > num2) { + return 1 + } else if (num1 < num2) { + return -1 + } + } + + return 0 +} + +export default compareVersion diff --git a/components/helpers/computedBehavior.js b/components/helpers/computedBehavior.js new file mode 100644 index 0000000..8650193 --- /dev/null +++ b/components/helpers/computedBehavior.js @@ -0,0 +1,48 @@ +import isEmpty from './isEmpty' +import shallowEqual from './shallowEqual' + +const ALL_DATA_KEY = '**' + +const trim = (str = '') => str.replace(/\s/g, '') + +export default Behavior({ + lifetimes: { + attached() { + this.initComputed() + }, + }, + definitionFilter(defFields) { + const { computed = {} } = defFields + const observers = Object.keys(computed).reduce((acc, name) => { + const [field, getter] = Array.isArray(computed[name]) ? computed[name] : [ALL_DATA_KEY, computed[name]] + return { + ...acc, + [field]: function(...args) { + if (typeof getter === 'function') { + const newValue = getter.apply(this, args) + const oldValue = this.data[name] + if (!isEmpty(newValue) && !shallowEqual(newValue, oldValue)) { + this.setData({ [name]: newValue }) + } + } + }, + } + }, {}) + + Object.assign(defFields.observers = (defFields.observers || {}), observers) + Object.assign(defFields.methods = (defFields.methods || {}), { + initComputed: function(data = {}, isForce = false) { + if (!this.runInitComputed || isForce) { + this.runInitComputed = false + const context = this + const result = { ...this.data, ...data } + Object.keys(observers).forEach((key) => { + const values = trim(key).split(',').reduce((acc, name) => ([...acc, result[name]]), []) + observers[key].apply(context, values) + }) + this.runInitComputed = true + } + }, + }) + }, +}) diff --git a/components/helpers/createFieldsStore.js b/components/helpers/createFieldsStore.js new file mode 100644 index 0000000..9dbb3ee --- /dev/null +++ b/components/helpers/createFieldsStore.js @@ -0,0 +1,75 @@ +class FieldsStore { + constructor(fields = {}) { + this.fields = fields + } + + setFields(fields) { + Object.assign(this.fields, fields) + } + + updateFields(fields) { + this.fields = fields + } + + clearField(name) { + delete this.fields[name] + } + + getValueFromFields(name, fields) { + const field = fields[name] + if (field && 'value' in field) { + return field.value + } + return field.initialValue + } + + getAllFieldsName() { + const { fields } = this + return fields ? Object.keys(fields) : [] + } + + getField(name) { + return { + ...this.fields[name], + name, + } + } + + getFieldValuePropValue(fieldOption) { + const { name, valuePropName } = fieldOption + const field = this.getField(name) + const fieldValue = 'value' in field ? field.value : field.initialValue + + return { + [valuePropName]: fieldValue, + } + } + + getFieldValue(name) { + return this.getValueFromFields(name, this.fields) + } + + getFieldsValue(names) { + const fields = names || this.getAllFieldsName() + return fields.reduce((acc, name) => { + acc[name] = this.getFieldValue(name) + return acc + }, {}) + } + + resetFields(ns) { + const { fields } = this + const names = ns || this.getAllFieldsName() + return names.reduce((acc, name) => { + const field = fields[name] + if (field) { + acc[name] = field.initialValue + } + return acc + }, {}) + } +} + +export default function createFieldsStore(fields) { + return new FieldsStore(fields) +} diff --git a/components/helpers/debounce.js b/components/helpers/debounce.js new file mode 100644 index 0000000..207e486 --- /dev/null +++ b/components/helpers/debounce.js @@ -0,0 +1,56 @@ +export default function debounce(func, wait, immediate) { + let timeout, + args, + context, + timestamp, + result + + function later() { + const last = +(new Date()) - timestamp + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = undefined + if (!immediate) { + result = func.apply(context, args) + if (!timeout) { + context = undefined + args = undefined + } + } + } + } + + function debounced() { + context = this + args = arguments + timestamp = +(new Date()) + + const callNow = immediate && !timeout + if (!timeout) { + timeout = setTimeout(later, wait) + } + + if (callNow) { + result = func.apply(context, args) + context = undefined + args = undefined + } + + return result + } + + function cancel() { + if (timeout !== undefined) { + clearTimeout(timeout) + timeout = undefined + } + + context = undefined + args = undefined + } + + debounced.cancel = cancel + + return debounced +} \ No newline at end of file diff --git a/components/helpers/eventsMixin.js b/components/helpers/eventsMixin.js new file mode 100644 index 0000000..f690335 --- /dev/null +++ b/components/helpers/eventsMixin.js @@ -0,0 +1,53 @@ +const defaultEvents = { + onChange() {}, +} + +export default function eventsMixin(params = { defaultEvents }) { + return Behavior({ + lifetimes: { + created () { + this._oriTriggerEvent = this.triggerEvent + this.triggerEvent = this._triggerEvent + }, + }, + properties: { + events: { + type: Object, + value: defaultEvents, + }, + }, + data: { + inputEvents: defaultEvents, + }, + definitionFilter(defFields) { + // set default data + Object.assign(defFields.data = (defFields.data || {}), { + inputEvents: Object.assign({}, defaultEvents, defFields.inputEvents), + }) + + // set default methods + Object.assign(defFields.methods = (defFields.methods || {}), { + _triggerEvent(name, params, runCallbacks = true, option) { + const { inputEvents } = this.data + const method = `on${name[0].toUpperCase()}${name.slice(1)}` + const func = inputEvents[method] + + if (runCallbacks && typeof func === 'function') { + func.call(this, params) + } + + this._oriTriggerEvent(name, params, option) + }, + }) + + // set default observers + Object.assign(defFields.observers = (defFields.observers || {}), { + events(newVal) { + this.setData({ + inputEvents: Object.assign({}, defaultEvents, this.data.inputEvents, newVal), + }) + }, + }) + }, + }) +} diff --git a/components/helpers/funcBehavior.js b/components/helpers/funcBehavior.js new file mode 100644 index 0000000..948075c --- /dev/null +++ b/components/helpers/funcBehavior.js @@ -0,0 +1,97 @@ +/** + * 过滤对象的函数属性 + * @param {Object} opts + */ +const mergeOptionsToData = (opts = {}) => { + const options = Object.assign({}, opts) + + for (const key in options) { + if (options.hasOwnProperty(key) && typeof options[key] === 'function') { + delete options[key] + } + } + + return options +} + +/** + * Simple bind, faster than native + * + * @param {Function} fn + * @param {Object} ctx + * @return {Function} + */ +const bind = (fn, ctx) => { + return (...args) => { + return args.length ? fn.apply(ctx, args) : fn.call(ctx) + } +} + +/** + * Object assign + */ +const assign = (...args) => Object.assign({}, ...args) + +export default Behavior({ + definitionFilter(defFields) { + defFields.data = mergeOptionsToData(defFields.data) + defFields.data.in = false + defFields.data.visible = false + }, + methods: { + /** + * 过滤对象的函数属性 + * @param {Object} opts + */ + $$mergeOptionsToData: mergeOptionsToData, + /** + * 合并参数并绑定方法 + * + * @param {Object} opts 参数对象 + * @param {Object} fns 方法挂载的属性 + */ + $$mergeOptionsAndBindMethods (opts = {}, fns = this.fns) { + const options = Object.assign({}, opts) + + for (const key in options) { + if (options.hasOwnProperty(key) && typeof options[key] === 'function') { + fns[key] = bind(options[key], this) + delete options[key] + } + } + + return options + }, + /** + * Promise setData + * @param {Array} args 参数对象 + */ + $$setData (...args) { + const params = assign({}, ...args) + + return new Promise((resolve) => { + this.setData(params, resolve) + }) + }, + /** + * 延迟指定时间执行回调函数 + * @param {Function} callback 回调函数 + * @param {Number} timeout 延迟时间 + */ + $$requestAnimationFrame (callback = () => {}, timeout = 1000 / 60) { + return new Promise((resolve) => setTimeout(resolve, timeout)).then(callback) + }, + }, + /** + * 组件生命周期函数,在组件实例进入页面节点树时执行 + */ + created () { + this.fns = {} + }, + /** + * 组件生命周期函数,在组件实例被从页面节点树移除时执行 + */ + detached () { + this.fns = {} + }, +}) diff --git a/components/helpers/gestures.js b/components/helpers/gestures.js new file mode 100644 index 0000000..99a4a40 --- /dev/null +++ b/components/helpers/gestures.js @@ -0,0 +1,50 @@ +/** + * 获取触摸点位置信息 + */ +export const getTouchPoints = (nativeEvent, index = 0) => { + const touches = nativeEvent.touches + const changedTouches = nativeEvent.changedTouches + const hasTouches = touches && touches.length > 0 + const hasChangedTouches = changedTouches && changedTouches.length > 0 + const points = !hasTouches && hasChangedTouches ? changedTouches[index] : hasTouches ? touches[index] : nativeEvent + + return { + x: points.pageX, + y: points.pageY, + } +} + +/** + * 获取触摸点个数 + */ +export const getPointsNumber = (e) => e.touches && e.touches.length || e.changedTouches && e.changedTouches.length + +/** + * 判断是否为同一点 + */ +export const isEqualPoints = (p1, p2) => p1.x === p2.x && p1.y === p2.y + +/** + * 判断是否为相近的两点 + */ +export const isNearbyPoints = (p1, p2, DOUBLE_TAP_RADIUS = 25) => { + const xMove = Math.abs(p1.x - p2.x) + const yMove = Math.abs(p1.y - p2.y) + return xMove < DOUBLE_TAP_RADIUS & yMove < DOUBLE_TAP_RADIUS +} + +/** + * 获取两点之间的距离 + */ +export const getPointsDistance = (p1, p2) => { + const xMove = Math.abs(p1.x - p2.x) + const yMove = Math.abs(p1.y - p2.y) + return Math.sqrt(xMove * xMove + yMove * yMove) +} + +/** + * 获取触摸移动方向 + */ +export const getSwipeDirection = (x1, x2, y1, y2) => { + return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') +} diff --git a/components/helpers/isEmpty.js b/components/helpers/isEmpty.js new file mode 100644 index 0000000..56fc4f8 --- /dev/null +++ b/components/helpers/isEmpty.js @@ -0,0 +1,19 @@ +/** + * Checks if a value is empty. + */ +function isEmpty(value) { + if (Array.isArray(value)) { + return value.length === 0 + } else if (typeof value === 'object') { + if (value) { + for (const _ in value) { + return false + } + } + return true + } else { + return !value + } +} + +export default isEmpty \ No newline at end of file diff --git a/components/helpers/mergeOptionsToData.js b/components/helpers/mergeOptionsToData.js new file mode 100644 index 0000000..47f5acc --- /dev/null +++ b/components/helpers/mergeOptionsToData.js @@ -0,0 +1,17 @@ +/** + * 过滤对象的函数属性 + * @param {Object} opts + */ +const mergeOptionsToData = (opts = {}) => { + const options = Object.assign({}, opts) + + for (const key in options) { + if (options.hasOwnProperty(key) && typeof options[key] === 'function') { + delete options[key] + } + } + + return options +} + +export default mergeOptionsToData diff --git a/components/helpers/relationsBehavior.js b/components/helpers/relationsBehavior.js new file mode 100644 index 0000000..2f05c35 --- /dev/null +++ b/components/helpers/relationsBehavior.js @@ -0,0 +1,67 @@ +import isEmpty from './isEmpty' +import debounce from './debounce' + +/** + * bind func to obj + */ +function bindFunc(obj, method, observer) { + const oldFn = obj[method] + obj[method] = function(target) { + if (observer) { + observer.call(this, target, { + [method]: true, + }) + } + if (oldFn) { + oldFn.call(this, target) + } + } +} + +// default methods +const methods = ['linked', 'linkChanged', 'unlinked'] + +// extra props +const extProps = ['observer'] + +export default Behavior({ + lifetimes: { + created() { + this._debounce = null + }, + detached() { + if (this._debounce && this._debounce.cancel) { + this._debounce.cancel() + } + }, + }, + definitionFilter(defFields) { + const { relations } = defFields + + if (!isEmpty(relations)) { + for (const key in relations) { + const relation = relations[key] + + // bind func + methods.forEach((method) => bindFunc(relation, method, relation.observer)) + + // delete extProps + extProps.forEach((prop) => delete relation[prop]) + } + } + + Object.assign(defFields.methods = (defFields.methods || {}), { + getRelationsName: function(types = ['parent', 'child', 'ancestor', 'descendant']) { + return Object.keys(relations || {}).map((key) => { + if (relations[key] && types.includes(relations[key].type)) { + return key + } + return null + }).filter((v) => !!v) + }, + debounce: function(func, wait = 0, immediate = false) { + return (this._debounce = this._debounce || debounce(func.bind(this), wait, immediate)).call(this) + }, + }) + }, +}) diff --git a/components/helpers/safeAreaBehavior.js b/components/helpers/safeAreaBehavior.js new file mode 100644 index 0000000..c81fad0 --- /dev/null +++ b/components/helpers/safeAreaBehavior.js @@ -0,0 +1,46 @@ +import { getSystemInfo, checkIPhoneX } from './checkIPhoneX' + +const defaultSafeArea = { + top: false, + bottom: false, +} + +const setSafeArea = (params) => { + if (typeof params === 'boolean') { + return Object.assign({}, defaultSafeArea, { + top: params, + bottom: params, + }) + } else if (params !== null && typeof params === 'object') { + return Object.assign({}, defaultSafeArea) + } else if (typeof params === 'string') { + return Object.assign({}, defaultSafeArea, { + [params]: true, + }) + } + return defaultSafeArea +} + +export default Behavior({ + properties: { + safeArea: { + type: [Boolean, String, Object], + value: false, + }, + }, + observers: { + safeArea(newVal) { + this.setData({ safeAreaConfig: setSafeArea(newVal) }) + }, + }, + definitionFilter(defFields) { + const { statusBarHeight } = getSystemInfo() || {} + const isIPhoneX = checkIPhoneX() + + Object.assign(defFields.data = (defFields.data || {}), { + safeAreaConfig: defaultSafeArea, + statusBarHeight, + isIPhoneX, + }) + }, +}) diff --git a/components/helpers/safeSetDataBehavior.js b/components/helpers/safeSetDataBehavior.js new file mode 100644 index 0000000..f00f0ae --- /dev/null +++ b/components/helpers/safeSetDataBehavior.js @@ -0,0 +1,57 @@ +export default Behavior({ + lifetimes: { + created() { + this.nextCallback = null + }, + detached() { + this.cancelNextCallback() + }, + }, + methods: { + /** + * safeSetData + * @param {Object} nextData 数据对象 + * @param {Function} callback 回调函数 + */ + safeSetData(nextData, callback) { + this.pendingData = Object.assign({}, this.data, nextData) + callback = this.setNextCallback(callback) + + this.setData(nextData, () => { + this.pendingData = null + callback() + }) + }, + /** + * 设置下一回调函数 + * @param {Function} callback 回调函数 + */ + setNextCallback(callback) { + let active = true + + this.nextCallback = (event) => { + if (active) { + active = false + this.nextCallback = null + + callback.call(this, event) + } + } + + this.nextCallback.cancel = () => { + active = false + } + + return this.nextCallback + }, + /** + * 取消下一回调函数 + */ + cancelNextCallback() { + if (this.nextCallback !== null) { + this.nextCallback.cancel() + this.nextCallback = null + } + }, + }, +}) \ No newline at end of file diff --git a/components/helpers/shallowEqual.js b/components/helpers/shallowEqual.js new file mode 100644 index 0000000..8aece72 --- /dev/null +++ b/components/helpers/shallowEqual.js @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + * + */ + +/*eslint-disable no-self-compare */ + +'use strict'; + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + // SameValue algorithm + if (x === y) { + // Steps 1-5, 7-10 + // Steps 6.b-6.e: +0 != -0 + // Added the nonzero y check to make Flow happy, but it is redundant + return x !== 0 || y !== 0 || 1 / x === 1 / y; + } else { + // Step 6.a: NaN == NaN + return x !== x && y !== y; + } +} + +/** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ +function shallowEqual(objA, objB) { + if (is(objA, objB)) { + return true; + } + + if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + // Test for A's keys different from B. + for (var i = 0; i < keysA.length; i++) { + if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { + return false; + } + } + + return true; +} + +export default shallowEqual \ No newline at end of file diff --git a/components/helpers/styleToCssString.js b/components/helpers/styleToCssString.js new file mode 100644 index 0000000..1665cf7 --- /dev/null +++ b/components/helpers/styleToCssString.js @@ -0,0 +1,138 @@ +'use strict'; + +/** + * CSS properties which accept numbers but are not in units of "px". + */ +var isUnitlessNumber = { + boxFlex: true, + boxFlexGroup: true, + columnCount: true, + flex: true, + flexGrow: true, + flexPositive: true, + flexShrink: true, + flexNegative: true, + fontWeight: true, + lineClamp: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + widows: true, + zIndex: true, + zoom: true, + + // SVG-related properties + fillOpacity: true, + strokeDashoffset: true, + strokeOpacity: true, + strokeWidth: true +}; + +/** + * @param {string} prefix vendor-specific prefix, eg: Webkit + * @param {string} key style name, eg: transitionDuration + * @return {string} style name prefixed with `prefix`, properly camelCased, eg: + * WebkitTransitionDuration + */ +function prefixKey(prefix, key) { + return prefix + key.charAt(0).toUpperCase() + key.substring(1); +} + +/** + * Support style names that may come passed in prefixed by adding permutations + * of vendor prefixes. + */ +var prefixes = ['Webkit', 'ms', 'Moz', 'O']; + +// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an +// infinite loop, because it iterates over the newly added props too. +Object.keys(isUnitlessNumber).forEach(function(prop) { + prefixes.forEach(function(prefix) { + isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; + }); +}); + +var msPattern = /^ms-/; + +var _uppercasePattern = /([A-Z])/g; + +/** + * Hyphenates a camelcased string, for example: + * + * > hyphenate('backgroundColor') + * < "background-color" + * + * For CSS style names, use `hyphenateStyleName` instead which works properly + * with all vendor prefixes, including `ms`. + * + * @param {string} string + * @return {string} + */ +function hyphenate(string) { + return string.replace(_uppercasePattern, '-$1').toLowerCase(); +} + +/** + * Hyphenates a camelcased CSS property name, for example: + * + * > hyphenateStyleName('backgroundColor') + * < "background-color" + * > hyphenateStyleName('MozTransition') + * < "-moz-transition" + * > hyphenateStyleName('msTransition') + * < "-ms-transition" + * + * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix + * is converted to `-ms-`. + * + * @param {string} string + * @return {string} + */ +function hyphenateStyleName(string) { + return hyphenate(string).replace(msPattern, '-ms-'); +} + +var isArray = Array.isArray; +var keys = Object.keys; + +var counter = 1; +// Follows syntax at https://developer.mozilla.org/en-US/docs/Web/CSS/content, +// including multiple space separated values. +var unquotedContentValueRegex = /^(normal|none|(\b(url\([^)]*\)|chapter_counter|attr\([^)]*\)|(no-)?(open|close)-quote|inherit)((\b\s*)|$|\s+))+)$/; + +function buildRule(key, value) { + if (!isUnitlessNumber[key] && typeof value === 'number') { + value = '' + value + 'px'; + } else if (key === 'content' && !unquotedContentValueRegex.test(value)) { + value = "'" + value.replace(/'/g, "\\'") + "'"; + } + + return hyphenateStyleName(key) + ': ' + value + '; '; +} + +function styleToCssString(rules) { + var result = '' + if (typeof rules === 'string') { + return rules + } + if (!rules || keys(rules).length === 0) { + return result; + } + var styleKeys = keys(rules); + for (var j = 0, l = styleKeys.length; j < l; j++) { + var styleKey = styleKeys[j]; + var value = rules[styleKey]; + + if (isArray(value)) { + for (var i = 0, len = value.length; i < len; i++) { + result += buildRule(styleKey, value[i]); + } + } else { + result += buildRule(styleKey, value); + } + } + return result; +} + +export default styleToCssString \ No newline at end of file diff --git a/components/highlight-text/index.js b/components/highlight-text/index.js new file mode 100644 index 0000000..aa49468 --- /dev/null +++ b/components/highlight-text/index.js @@ -0,0 +1,35 @@ +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + content: { type: String, value: '' }, + keyword: { type: String, value: '' }, + keywordColor: { type: String, value: '#008aff' } + }, + observers: { + 'keyword': function () { + this.setContent() + } + }, + data: { + contain: false + }, + methods: { + setContent: function () { + if(this.data.keyword == null || '' == this.data.keyword || this.data.keyword.length == 0){ + this.setData({contain: false}) + return + } + var index = this.data.content.indexOf(this.data.keyword) + if(index < 0){ + this.setData({contain: false}) + } else { + var textstrA = this.data.content.substring(0, index) + var textstrB = this.data.content.substring(index + this.data.keyword.length) + this.setData({contain: true, textstrA, textstrB}) + } + } + } +}) \ No newline at end of file diff --git a/components/highlight-text/index.json b/components/highlight-text/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/highlight-text/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/highlight-text/index.wxml b/components/highlight-text/index.wxml new file mode 100644 index 0000000..36d2718 --- /dev/null +++ b/components/highlight-text/index.wxml @@ -0,0 +1,6 @@ + + {{textstrA}} + {{keyword}} + {{textstrB}} + +{{content}} \ No newline at end of file diff --git a/components/highlight-text/index.wxss b/components/highlight-text/index.wxss new file mode 100644 index 0000000..cc6bf07 --- /dev/null +++ b/components/highlight-text/index.wxss @@ -0,0 +1,3 @@ +.keyword { + color: #008aff; +} \ No newline at end of file diff --git a/components/icon/index.js b/components/icon/index.js new file mode 100644 index 0000000..2cfe253 --- /dev/null +++ b/components/icon/index.js @@ -0,0 +1,27 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + dot: Boolean, + info: null, + size: null, + color: String, + customStyle: String, + classPrefix: { + type: String, + value: 'van-icon' + }, + name: { + type: String, + observer(val) { + this.setData({ + isImageName: val.indexOf('/') !== -1 + }); + } + } + }, + methods: { + onClick() { + this.$emit('click'); + } + } +}); diff --git a/components/icon/index.json b/components/icon/index.json new file mode 100644 index 0000000..bf0ebe0 --- /dev/null +++ b/components/icon/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-info": "../info/index" + } +} diff --git a/components/icon/index.wxml b/components/icon/index.wxml new file mode 100644 index 0000000..7543af5 --- /dev/null +++ b/components/icon/index.wxml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/components/icon/index.wxss b/components/icon/index.wxss new file mode 100644 index 0000000..cf0b49a --- /dev/null +++ b/components/icon/index.wxss @@ -0,0 +1,960 @@ +@import '../common/index.wxss'; + +@font-face { + font-family: 'vant-icon'; + src: url('data:application/font-woff;charset=utf-8;base64,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') format('woff'), + url('vant-icon-d3825a.ttf') format('truetype'); + font-weight: 400; + font-style: normal; + font-display: auto; +} + + + +.van-icon { + position: relative; + font: normal normal normal 14px/1 vant-icon; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased +} + +.van-icon, +.van-icon:before { + display: inline-block +} + +.van-icon-add-o:before { + content: "\F000" +} + +.van-icon-add-square:before { + content: "\F001" +} + +.van-icon-add:before { + content: "\F002" +} + +.van-icon-after-sale:before { + content: "\F003" +} + +.van-icon-aim:before { + content: "\F004" +} + +.van-icon-alipay:before { + content: "\F005" +} + +.van-icon-apps-o:before { + content: "\F006" +} + +.van-icon-arrow-down:before { + content: "\F007" +} + +.van-icon-arrow-left:before { + content: "\F008" +} + +.van-icon-arrow-up:before { + content: "\F009" +} + +.van-icon-arrow:before { + content: "\F00A" +} + +.van-icon-ascending:before { + content: "\F00B" +} + +.van-icon-audio:before { + content: "\F00C" +} + +.van-icon-award-o:before { + content: "\F00D" +} + +.van-icon-award:before { + content: "\F00E" +} + +.van-icon-bag-o:before { + content: "\F00F" +} + +.van-icon-bag:before { + content: "\F010" +} + +.van-icon-balance-list-o:before { + content: "\F011" +} + +.van-icon-balance-list:before { + content: "\F012" +} + +.van-icon-balance-o:before { + content: "\F013" +} + +.van-icon-balance-pay:before { + content: "\F014" +} + +.van-icon-bar-chart-o:before { + content: "\F015" +} + +.van-icon-bars:before { + content: "\F016" +} + +.van-icon-bell:before { + content: "\F017" +} + +.van-icon-bill-o:before { + content: "\F018" +} + +.van-icon-bill:before { + content: "\F019" +} + +.van-icon-birthday-cake-o:before { + content: "\F01A" +} + +.van-icon-bookmark-o:before { + content: "\F01B" +} + +.van-icon-bookmark:before { + content: "\F01C" +} + +.van-icon-browsing-history-o:before { + content: "\F01D" +} + +.van-icon-browsing-history:before { + content: "\F01E" +} + +.van-icon-brush-o:before { + content: "\F01F" +} + +.van-icon-bulb-o:before { + content: "\F020" +} + +.van-icon-bullhorn-o:before { + content: "\F021" +} + +.van-icon-calender-o:before { + content: "\F022" +} + +.van-icon-card:before { + content: "\F023" +} + +.van-icon-cart-circle-o:before { + content: "\F024" +} + +.van-icon-cart-circle:before { + content: "\F025" +} + +.van-icon-cart-o:before { + content: "\F026" +} + +.van-icon-cart:before { + content: "\F027" +} + +.van-icon-cash-back-record:before { + content: "\F028" +} + +.van-icon-cash-on-deliver:before { + content: "\F029" +} + +.van-icon-cashier-o:before { + content: "\F02A" +} + +.van-icon-certificate:before { + content: "\F02B" +} + +.van-icon-chart-trending-o:before { + content: "\F02C" +} + +.van-icon-chat-o:before { + content: "\F02D" +} + +.van-icon-chat:before { + content: "\F02E" +} + +.van-icon-checked:before { + content: "\F02F" +} + +.van-icon-circle:before { + content: "\F030" +} + +.van-icon-clear:before { + content: "\F031" +} + +.van-icon-clock-o:before { + content: "\F032" +} + +.van-icon-clock:before { + content: "\F033" +} + +.van-icon-close:before { + content: "\F034" +} + +.van-icon-closed-eye:before { + content: "\F035" +} + +.van-icon-cluster-o:before { + content: "\F036" +} + +.van-icon-cluster:before { + content: "\F037" +} + +.van-icon-column:before { + content: "\F038" +} + +.van-icon-comment-circle-o:before { + content: "\F039" +} + +.van-icon-comment-circle:before { + content: "\F03A" +} + +.van-icon-comment-o:before { + content: "\F03B" +} + +.van-icon-comment:before { + content: "\F03C" +} + +.van-icon-completed:before { + content: "\F03D" +} + +.van-icon-contact:before { + content: "\F03E" +} + +.van-icon-coupon-o:before { + content: "\F03F" +} + +.van-icon-coupon:before { + content: "\F040" +} + +.van-icon-credit-pay:before { + content: "\F041" +} + +.van-icon-cross:before { + content: "\F042" +} + +.van-icon-debit-pay:before { + content: "\F043" +} + +.van-icon-delete:before { + content: "\F044" +} + +.van-icon-descending:before { + content: "\F045" +} + +.van-icon-description:before { + content: "\F046" +} + +.van-icon-desktop-o:before { + content: "\F047" +} + +.van-icon-diamond-o:before { + content: "\F048" +} + +.van-icon-diamond:before { + content: "\F049" +} + +.van-icon-discount:before { + content: "\F04A" +} + +.van-icon-down:before { + content: "\F04B" +} + +.van-icon-ecard-pay:before { + content: "\F04C" +} + +.van-icon-edit:before { + content: "\F04D" +} + +.van-icon-ellipsis:before { + content: "\F04E" +} + +.van-icon-empty:before { + content: "\F04F" +} + +.van-icon-envelop-o:before { + content: "\F050" +} + +.van-icon-exchange:before { + content: "\F051" +} + +.van-icon-expand-o:before { + content: "\F052" +} + +.van-icon-expand:before { + content: "\F053" +} + +.van-icon-eye-o:before { + content: "\F054" +} + +.van-icon-eye:before { + content: "\F055" +} + +.van-icon-fail:before { + content: "\F056" +} + +.van-icon-failure:before { + content: "\F057" +} + +.van-icon-filter-o:before { + content: "\F058" +} + +.van-icon-fire-o:before { + content: "\F059" +} + +.van-icon-fire:before { + content: "\F05A" +} + +.van-icon-flag-o:before { + content: "\F05B" +} + +.van-icon-flower-o:before { + content: "\F05C" +} + +.van-icon-free-postage:before { + content: "\F05D" +} + +.van-icon-friends-o:before { + content: "\F05E" +} + +.van-icon-friends:before { + content: "\F05F" +} + +.van-icon-gem-o:before { + content: "\F060" +} + +.van-icon-gem:before { + content: "\F061" +} + +.van-icon-gift-card-o:before { + content: "\F062" +} + +.van-icon-gift-card:before { + content: "\F063" +} + +.van-icon-gift-o:before { + content: "\F064" +} + +.van-icon-gift:before { + content: "\F065" +} + +.van-icon-gold-coin-o:before { + content: "\F066" +} + +.van-icon-gold-coin:before { + content: "\F067" +} + +.van-icon-good-job-o:before { + content: "\F068" +} + +.van-icon-good-job:before { + content: "\F069" +} + +.van-icon-goods-collect-o:before { + content: "\F06A" +} + +.van-icon-goods-collect:before { + content: "\F06B" +} + +.van-icon-graphic:before { + content: "\F06C" +} + +.van-icon-home-o:before { + content: "\F06D" +} + +.van-icon-hot-o:before { + content: "\F06E" +} + +.van-icon-hot-sale-o:before { + content: "\F06F" +} + +.van-icon-hot-sale:before { + content: "\F070" +} + +.van-icon-hot:before { + content: "\F071" +} + +.van-icon-hotel-o:before { + content: "\F072" +} + +.van-icon-idcard:before { + content: "\F073" +} + +.van-icon-info-o:before { + content: "\F074" +} + +.van-icon-info:before { + content: "\F075" +} + +.van-icon-invition:before { + content: "\F076" +} + +.van-icon-label-o:before { + content: "\F077" +} + +.van-icon-label:before { + content: "\F078" +} + +.van-icon-like-o:before { + content: "\F079" +} + +.van-icon-like:before { + content: "\F07A" +} + +.van-icon-live:before { + content: "\F07B" +} + +.van-icon-location-o:before { + content: "\F07C" +} + +.van-icon-location:before { + content: "\F07D" +} + +.van-icon-lock:before { + content: "\F07E" +} + +.van-icon-logistics:before { + content: "\F07F" +} + +.van-icon-manager-o:before { + content: "\F080" +} + +.van-icon-manager:before { + content: "\F081" +} + +.van-icon-map-marked:before { + content: "\F082" +} + +.van-icon-medal-o:before { + content: "\F083" +} + +.van-icon-medal:before { + content: "\F084" +} + +.van-icon-more-o:before { + content: "\F085" +} + +.van-icon-more:before { + content: "\F086" +} + +.van-icon-music-o:before { + content: "\F087" +} + +.van-icon-music:before { + content: "\F088" +} + +.van-icon-new-arrival-o:before { + content: "\F089" +} + +.van-icon-new-arrival:before { + content: "\F08A" +} + +.van-icon-new-o:before { + content: "\F08B" +} + +.van-icon-new:before { + content: "\F08C" +} + +.van-icon-newspaper-o:before { + content: "\F08D" +} + +.van-icon-notes-o:before { + content: "\F08E" +} + +.van-icon-orders-o:before { + content: "\F08F" +} + +.van-icon-other-pay:before { + content: "\F090" +} + +.van-icon-paid:before { + content: "\F091" +} + +.van-icon-passed:before { + content: "\F092" +} + +.van-icon-pause-circle-o:before { + content: "\F093" +} + +.van-icon-pause-circle:before { + content: "\F094" +} + +.van-icon-pause:before { + content: "\F095" +} + +.van-icon-peer-pay:before { + content: "\F096" +} + +.van-icon-pending-payment:before { + content: "\F097" +} + +.van-icon-phone-circle-o:before { + content: "\F098" +} + +.van-icon-phone-circle:before { + content: "\F099" +} + +.van-icon-phone-o:before { + content: "\F09A" +} + +.van-icon-phone:before { + content: "\F09B" +} + +.van-icon-photo-o:before { + content: "\F09C" +} + +.van-icon-photo:before { + content: "\F09D" +} + +.van-icon-photograph:before { + content: "\F09E" +} + +.van-icon-play-circle-o:before { + content: "\F09F" +} + +.van-icon-play-circle:before { + content: "\F0A0" +} + +.van-icon-play:before { + content: "\F0A1" +} + +.van-icon-plus:before { + content: "\F0A2" +} + +.van-icon-point-gift-o:before { + content: "\F0A3" +} + +.van-icon-point-gift:before { + content: "\F0A4" +} + +.van-icon-points:before { + content: "\F0A5" +} + +.van-icon-printer:before { + content: "\F0A6" +} + +.van-icon-qr-invalid:before { + content: "\F0A7" +} + +.van-icon-qr:before { + content: "\F0A8" +} + +.van-icon-question-o:before { + content: "\F0A9" +} + +.van-icon-question:before { + content: "\F0AA" +} + +.van-icon-records:before { + content: "\F0AB" +} + +.van-icon-refund-o:before { + content: "\F0AC" +} + +.van-icon-replay:before { + content: "\F0AD" +} + +.van-icon-scan:before { + content: "\F0AE" +} + +.van-icon-search:before { + content: "\F0AF" +} + +.van-icon-send-gift-o:before { + content: "\F0B0" +} + +.van-icon-send-gift:before { + content: "\F0B1" +} + +.van-icon-service-o:before { + content: "\F0B2" +} + +.van-icon-service:before { + content: "\F0B3" +} + +.van-icon-setting-o:before { + content: "\F0B4" +} + +.van-icon-setting:before { + content: "\F0B5" +} + +.van-icon-share:before { + content: "\F0B6" +} + +.van-icon-shop-collect-o:before { + content: "\F0B7" +} + +.van-icon-shop-collect:before { + content: "\F0B8" +} + +.van-icon-shop-o:before { + content: "\F0B9" +} + +.van-icon-shop:before { + content: "\F0BA" +} + +.van-icon-shopping-cart-o:before { + content: "\F0BB" +} + +.van-icon-shopping-cart:before { + content: "\F0BC" +} + +.van-icon-shrink:before { + content: "\F0BD" +} + +.van-icon-sign:before { + content: "\F0BE" +} + +.van-icon-smile-comment-o:before { + content: "\F0BF" +} + +.van-icon-smile-comment:before { + content: "\F0C0" +} + +.van-icon-smile-o:before { + content: "\F0C1" +} + +.van-icon-smile:before { + content: "\F0C2" +} + +.van-icon-star-o:before { + content: "\F0C3" +} + +.van-icon-star:before { + content: "\F0C4" +} + +.van-icon-stop-circle-o:before { + content: "\F0C5" +} + +.van-icon-stop-circle:before { + content: "\F0C6" +} + +.van-icon-stop:before { + content: "\F0C7" +} + +.van-icon-success:before { + content: "\F0C8" +} + +.van-icon-thumb-circle-o:before { + content: "\F0C9" +} + +.van-icon-thumb-circle:before { + content: "\F0CA" +} + +.van-icon-todo-list-o:before { + content: "\F0CB" +} + +.van-icon-todo-list:before { + content: "\F0CC" +} + +.van-icon-tosend:before { + content: "\F0CD" +} + +.van-icon-tv-o:before { + content: "\F0CE" +} + +.van-icon-umbrella-circle:before { + content: "\F0CF" +} + +.van-icon-underway-o:before { + content: "\F0D0" +} + +.van-icon-underway:before { + content: "\F0D1" +} + +.van-icon-upgrade:before { + content: "\F0D2" +} + +.van-icon-user-circle-o:before { + content: "\F0D3" +} + +.van-icon-user-o:before { + content: "\F0D4" +} + +.van-icon-video-o:before { + content: "\F0D5" +} + +.van-icon-video:before { + content: "\F0D6" +} + +.van-icon-vip-card-o:before { + content: "\F0D7" +} + +.van-icon-vip-card:before { + content: "\F0D8" +} + +.van-icon-volume-o:before { + content: "\F0D9" +} + +.van-icon-volume:before { + content: "\F0DA" +} + +.van-icon-wap-home-o:before { + content: "\F0DB" +} + +.van-icon-wap-home:before { + content: "\F0DC" +} + +.van-icon-wap-nav:before { + content: "\F0DD" +} + +.van-icon-warn-o:before { + content: "\F0DE" +} + +.van-icon-warning-o:before { + content: "\F0DF" +} + +.van-icon-warning:before { + content: "\F0E0" +} + +.van-icon-weapp-nav:before { + content: "\F0E1" +} + +.van-icon-wechat:before { + content: "\F0E2" +} + +.van-icon-youzan-shield:before { + content: "\F0E3" +} + +:host { + display: -webkit-inline-flex; + display: inline-flex; + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center +} + +.van-icon--image { + width: 1em; + height: 1em +} + +.van-icon__image { + width: 100%; + height: 100% +} + +.van-icon__info { + z-index: 1 +} \ No newline at end of file diff --git a/components/image-upload/index.js b/components/image-upload/index.js new file mode 100644 index 0000000..729e303 --- /dev/null +++ b/components/image-upload/index.js @@ -0,0 +1,59 @@ +import { zconfig } from'../../api/ztb' +const util = require('../../utils/util') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + data: { + path: null + }, + methods: { + chooseImage: function(e) { + this.triggerEvent('before', null) + var that = this + wx.chooseImage({ + count: 1, //默认9 + sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有 + sourceType: ['album', 'camera'], //从相册选择 + success: (res) => { + that.setData({ path: res.tempFilePaths[0] }) + that.uploadFile(res.tempFilePaths[0]) + } + }) + }, + uploadFile: function (path) { + var that = this + var header = { ...zconfig.header, 'X-APP-ID': app.xAppId, appversion: app.version, 'Content-Type': 'multipart/form-data' } + wx.uploadFile({ + url: zconfig.baseUrl + '/recycle-user-center/file-uploading/upload/image', + filePath: path, + name: 'image', + header, + success: function (result) { + var resp = null + if (!util.isEmpty(result.data)) { + resp = JSON.parse(result.data) + } + if (resp && resp.code === 0) { + that.triggerEvent('uploaded', {id: that.data.id, url: resp.data}) + } else { + util.showToast('图片上传失败,请重新上传') + } + }, + fail: function (res) { + util.showToast('图片上传失败,请重新上传') + } + }) + }, + viewImage: function(e) { + this.setData({ focus: false }) + wx.previewImage({ urls: [this.data.path], current: this.data.path }) + }, + deleteImg: function(e) { + this.setData({ path: null }) + } + } +}) \ No newline at end of file diff --git a/components/image-upload/index.json b/components/image-upload/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/image-upload/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/image-upload/index.wxml b/components/image-upload/index.wxml new file mode 100644 index 0000000..be0211b --- /dev/null +++ b/components/image-upload/index.wxml @@ -0,0 +1,10 @@ + + + 上传图片 + + + + + + + \ No newline at end of file diff --git a/components/image-upload/index.wxss b/components/image-upload/index.wxss new file mode 100644 index 0000000..84d83c2 --- /dev/null +++ b/components/image-upload/index.wxss @@ -0,0 +1,48 @@ +.image-reader-item { + position: relative; + width: 99%; + height: 100%; + background-color: #f8f8f8; + box-sizing: border-box; + list-style: none; + background-size: cover; + border-radius: 6rpx; +} + +.image-reader-item .md-icon { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0.5; +} + +.image-reader-item .md-load { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.image-reader-item .md-hint { + position: absolute; + top: 50%; + left: 0; + width: 100%; + margin-top: 10px; + font-size: 12px; + color: #bababa; + text-align: center; +} + +.image-reader-item .delete { + position: absolute; + top: 0px; + right: 0px; + opacity: 0.8; + border-top-right-radius: 6rpx; + border-bottom-left-radius: 8rpx; + padding: 6rpx 12rpx; + height: auto; + background-color: rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/components/image/index.js b/components/image/index.js new file mode 100644 index 0000000..580715f --- /dev/null +++ b/components/image/index.js @@ -0,0 +1,101 @@ +import { addUnit, isDef } from '../common/utils'; +import { VantComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +const FIT_MODE_MAP = { + none: 'center', + fill: 'scaleToFill', + cover: 'aspectFill', + contain: 'aspectFit', + widthFix: 'widthFix', + heightFix: 'heightFix' +}; +VantComponent({ + mixins: [button, openType], + classes: ['custom-class', 'loading-class', 'error-class', 'image-class'], + props: { + src: { + type: String, + observer() { + this.setData({ + error: false, + loading: true + }); + } + }, + round: Boolean, + width: { + type: null, + observer: 'setStyle' + }, + height: { + type: null, + observer: 'setStyle' + }, + radius: null, + lazyLoad: Boolean, + useErrorSlot: Boolean, + useLoadingSlot: Boolean, + showMenuByLongpress: Boolean, + fit: { + type: String, + value: 'fill', + observer: 'setMode' + }, + showError: { + type: Boolean, + value: true + }, + showLoading: { + type: Boolean, + value: true + } + }, + data: { + error: false, + loading: true, + viewStyle: '', + }, + mounted() { + this.setMode(); + this.setStyle(); + }, + methods: { + setMode() { + this.setData({ + mode: FIT_MODE_MAP[this.data.fit], + }); + }, + setStyle() { + const { width, height, radius } = this.data; + let style = ''; + if (isDef(width)) { + style += `width: ${addUnit(width)};`; + } + if (isDef(height)) { + style += `height: ${addUnit(height)};`; + } + if (isDef(radius)) { + style += 'overflow: hidden;'; + style += `border-radius: ${addUnit(radius)};`; + } + this.setData({ viewStyle: style }); + }, + onLoad(event) { + this.setData({ + loading: false + }); + this.$emit('load', event.detail); + }, + onError(event) { + this.setData({ + loading: false, + error: true + }); + this.$emit('error', event.detail); + }, + onClick(event) { + this.$emit('click', event.detail); + } + } +}); diff --git a/components/image/index.json b/components/image/index.json new file mode 100644 index 0000000..e00a588 --- /dev/null +++ b/components/image/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-loading": "../loading/index" + } +} diff --git a/components/image/index.wxml b/components/image/index.wxml new file mode 100644 index 0000000..0195c90 --- /dev/null +++ b/components/image/index.wxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/image/index.wxss b/components/image/index.wxss new file mode 100644 index 0000000..e914cb8 --- /dev/null +++ b/components/image/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-image{position:relative}.van-image--round{overflow:hidden;border-radius:50%}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;width:100%;height:100%}.van-image__error,.van-image__loading{position:absolute;top:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#969799;color:var(--image-placeholder-text-color,#969799);font-size:14px;font-size:var(--image-placeholder-font-size,14px);background-color:#f7f8fa;background-color:var(--image-placeholder-background-color,#f7f8fa)} \ No newline at end of file diff --git a/components/index-anchor/index.js b/components/index-anchor/index.js new file mode 100644 index 0000000..94f5060 --- /dev/null +++ b/components/index-anchor/index.js @@ -0,0 +1,30 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'index-bar', + type: 'ancestor', + current: 'index-anchor' + }, + props: { + useSlot: Boolean, + index: null + }, + data: { + active: false, + wrapperStyle: '', + anchorStyle: '' + }, + methods: { + scrollIntoView(scrollTop) { + this.getBoundingClientRect().then((rect) => { + wx.pageScrollTo({ + duration: 0, + scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop + }); + }); + }, + getBoundingClientRect() { + return this.getRect('.van-index-anchor-wrapper'); + } + } +}); diff --git a/components/index-anchor/index.json b/components/index-anchor/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/index-anchor/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/index-anchor/index.wxml b/components/index-anchor/index.wxml new file mode 100644 index 0000000..49affa7 --- /dev/null +++ b/components/index-anchor/index.wxml @@ -0,0 +1,14 @@ + + + + + {{ index }} + + + diff --git a/components/index-anchor/index.wxss b/components/index-anchor/index.wxss new file mode 100644 index 0000000..b8c3c0a --- /dev/null +++ b/components/index-anchor/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-index-anchor{padding:0 16px;padding:var(--index-anchor-padding,0 16px);color:#323233;color:var(--index-anchor-text-color,#323233);font-weight:500;font-weight:var(--index-anchor-font-weight,500);font-size:14px;font-size:var(--index-anchor-font-size,14px);line-height:32px;line-height:var(--index-anchor-line-height,32px);background-color:initial;background-color:var(--index-anchor-background-color,transparent)}.van-index-anchor--active{right:0;left:0;color:#07c160;color:var(--index-anchor-active-text-color,#07c160);background-color:#fff;background-color:var(--index-anchor-active-background-color,#fff)} \ No newline at end of file diff --git a/components/info/index.js b/components/info/index.js new file mode 100644 index 0000000..a08ad2c --- /dev/null +++ b/components/info/index.js @@ -0,0 +1,10 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +var component_1 = require('../common/component'); +component_1.VantComponent({ + props: { + dot: Boolean, + info: null, + customStyle: String, + }, +}); diff --git a/components/info/index.json b/components/info/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/info/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/info/index.wxml b/components/info/index.wxml new file mode 100644 index 0000000..fcb5e40 --- /dev/null +++ b/components/info/index.wxml @@ -0,0 +1,4 @@ + + +{{ dot ? '' : info }} \ No newline at end of file diff --git a/components/info/index.wxss b/components/info/index.wxss new file mode 100644 index 0000000..6d44b8e --- /dev/null +++ b/components/info/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-info{position:absolute;top:0;right:0;box-sizing:border-box;white-space:nowrap;text-align:center;-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%);-webkit-transform-origin:100%;transform-origin:100%;min-width:16px;min-width:var(--info-size,16px);padding:0 3px;padding:var(--info-padding,0 3px);color:#fff;color:var(--info-color,#fff);font-weight:500;font-weight:var(--info-font-weight,500);font-size:12px;font-size:var(--info-font-size,12px);font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--info-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif);line-height:14px;line-height:calc(var(--info-size, 16px) - var(--info-border-width, 1px)*2);background-color:#ee0a24;background-color:var(--info-background-color,#ee0a24);border:1px solid #fff;border:var(--info-border-width,1px) solid var(--white,#fff);border-radius:16px;border-radius:var(--info-size,16px)}.van-info--dot{min-width:0;border-radius:100%;width:8px;width:var(--info-dot-size,8px);height:8px;height:var(--info-dot-size,8px);background-color:#ee0a24;background-color:var(--info-dot-color,#ee0a24)} \ No newline at end of file diff --git a/components/loading/index.js b/components/loading/index.js new file mode 100644 index 0000000..f5be7ad --- /dev/null +++ b/components/loading/index.js @@ -0,0 +1,16 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + color: String, + vertical: Boolean, + type: { + type: String, + value: 'circular' + }, + size: String, + textSize: String + }, + data: { + array12: Array.from({ length: 12 }), + }, +}); diff --git a/components/loading/index.json b/components/loading/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/loading/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/loading/index.wxml b/components/loading/index.wxml new file mode 100644 index 0000000..5e97d63 --- /dev/null +++ b/components/loading/index.wxml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/components/loading/index.wxss b/components/loading/index.wxss new file mode 100644 index 0000000..f28a6b4 --- /dev/null +++ b/components/loading/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#c8c9cc;color:var(--loading-spinner-color,#c8c9cc)}.van-loading__spinner{position:relative;box-sizing:border-box;width:30px;width:var(--loading-spinner-size,30px);max-width:100%;max-height:100%;height:30px;height:var(--loading-spinner-size,30px);-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite;-webkit-animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-top-color:initial;border-radius:100%}.van-loading__text{margin-left:8px;margin-left:var(--padding-xs,8px);color:#969799;color:var(--loading-text-color,#969799);font-size:14px;font-size:var(--loading-text-font-size,14px);line-height:20px;line-height:var(--loading-text-line-height,20px)}.van-loading__text:empty{display:none}.van-loading--vertical{-webkit-flex-direction:column;flex-direction:column}.van-loading--vertical .van-loading__text{margin:8px 0 0;margin:var(--padding-xs,8px) 0 0}.van-loading__dot{position:absolute;top:0;left:0;width:100%;height:100%}.van-loading__dot:before{display:block;width:2px;height:25%;margin:0 auto;background-color:currentColor;border-radius:40%;content:" "}.van-loading__dot:first-of-type{-webkit-transform:rotate(30deg);transform:rotate(30deg);opacity:1}.van-loading__dot:nth-of-type(2){-webkit-transform:rotate(60deg);transform:rotate(60deg);opacity:.9375}.van-loading__dot:nth-of-type(3){-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:.875}.van-loading__dot:nth-of-type(4){-webkit-transform:rotate(120deg);transform:rotate(120deg);opacity:.8125}.van-loading__dot:nth-of-type(5){-webkit-transform:rotate(150deg);transform:rotate(150deg);opacity:.75}.van-loading__dot:nth-of-type(6){-webkit-transform:rotate(180deg);transform:rotate(180deg);opacity:.6875}.van-loading__dot:nth-of-type(7){-webkit-transform:rotate(210deg);transform:rotate(210deg);opacity:.625}.van-loading__dot:nth-of-type(8){-webkit-transform:rotate(240deg);transform:rotate(240deg);opacity:.5625}.van-loading__dot:nth-of-type(9){-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:.5}.van-loading__dot:nth-of-type(10){-webkit-transform:rotate(300deg);transform:rotate(300deg);opacity:.4375}.van-loading__dot:nth-of-type(11){-webkit-transform:rotate(330deg);transform:rotate(330deg);opacity:.375}.van-loading__dot:nth-of-type(12){-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:.3125}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}} \ No newline at end of file diff --git a/components/mixins/basic.js b/components/mixins/basic.js new file mode 100644 index 0000000..dd1f9d5 --- /dev/null +++ b/components/mixins/basic.js @@ -0,0 +1,26 @@ +export const basic = Behavior({ + methods: { + $emit(...args) { + this.triggerEvent(...args); + }, + set(data, callback) { + this.setData(data, callback); + return new Promise(resolve => wx.nextTick(resolve)); + }, + getRect(selector, all) { + return new Promise(resolve => { + wx.createSelectorQuery() + .in(this)[all ? 'selectAll' : 'select'](selector) + .boundingClientRect(rect => { + if (all && Array.isArray(rect) && rect.length) { + resolve(rect); + } + if (!all && rect) { + resolve(rect); + } + }) + .exec(); + }); + } + } +}); diff --git a/components/mixins/button.js b/components/mixins/button.js new file mode 100644 index 0000000..f2d5da6 --- /dev/null +++ b/components/mixins/button.js @@ -0,0 +1,15 @@ +export const button = Behavior({ + externalClasses: ['hover-class'], + properties: { + id: String, + lang: String, + businessId: Number, + sessionFrom: String, + sendMessageTitle: String, + sendMessagePath: String, + sendMessageImg: String, + showMessageCard: Boolean, + appParameter: String, + ariaLabel: String + } +}); diff --git a/components/mixins/link.js b/components/mixins/link.js new file mode 100644 index 0000000..d7aed0c --- /dev/null +++ b/components/mixins/link.js @@ -0,0 +1,17 @@ +export const link = Behavior({ + properties: { + url: String, + linkType: { + type: String, + value: 'navigateTo' + } + }, + methods: { + jumpLink(urlKey = 'url') { + const url = this.data[urlKey]; + if (url) { + wx[this.data.linkType]({ url }); + } + } + } +}); diff --git a/components/mixins/open-type.js b/components/mixins/open-type.js new file mode 100644 index 0000000..514517e --- /dev/null +++ b/components/mixins/open-type.js @@ -0,0 +1,25 @@ +export const openType = Behavior({ + properties: { + openType: String + }, + methods: { + bindGetUserInfo(event) { + this.$emit('getuserinfo', event.detail); + }, + bindContact(event) { + this.$emit('contact', event.detail); + }, + bindGetPhoneNumber(event) { + this.$emit('getphonenumber', event.detail); + }, + bindError(event) { + this.$emit('error', event.detail); + }, + bindLaunchApp(event) { + this.$emit('launchapp', event.detail); + }, + bindOpenSetting(event) { + this.$emit('opensetting', event.detail); + }, + } +}); diff --git a/components/mixins/page-scroll.js b/components/mixins/page-scroll.js new file mode 100644 index 0000000..cbf85e2 --- /dev/null +++ b/components/mixins/page-scroll.js @@ -0,0 +1,28 @@ +function getCurrentPage() { + const pages = getCurrentPages(); + return pages[pages.length - 1] || {}; +} +function onPageScroll(event) { + const { vanPageScroller = [] } = getCurrentPage(); + vanPageScroller.forEach((scroller) => { + if (typeof scroller === 'function') { + scroller(event); + } + }); +} +export const pageScrollMixin = (scroller) => Behavior({ + attached() { + const page = getCurrentPage(); + if (Array.isArray(page.vanPageScroller)) { + page.vanPageScroller.push(scroller.bind(this)); + } + else { + page.vanPageScroller = [page.onPageScroll, scroller.bind(this)]; + } + page.onPageScroll = onPageScroll; + }, + detached() { + const page = getCurrentPage(); + page.vanPageScroller = (page.vanPageScroller || []).filter(item => item !== scroller); + } +}); diff --git a/components/mixins/touch.js b/components/mixins/touch.js new file mode 100644 index 0000000..2a79426 --- /dev/null +++ b/components/mixins/touch.js @@ -0,0 +1,35 @@ +const MIN_DISTANCE = 10; +function getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; +} +export const touch = Behavior({ + methods: { + resetTouchStatus() { + this.direction = ''; + this.deltaX = 0; + this.deltaY = 0; + this.offsetX = 0; + this.offsetY = 0; + }, + touchStart(event) { + this.resetTouchStatus(); + const touch = event.touches[0]; + this.startX = touch.clientX; + this.startY = touch.clientY; + }, + touchMove(event) { + const touch = event.touches[0]; + this.deltaX = touch.clientX - this.startX; + this.deltaY = touch.clientY - this.startY; + this.offsetX = Math.abs(this.deltaX); + this.offsetY = Math.abs(this.deltaY); + this.direction = this.direction || getDirection(this.offsetX, this.offsetY); + } + } +}); diff --git a/components/mixins/transition.js b/components/mixins/transition.js new file mode 100644 index 0000000..698d40a --- /dev/null +++ b/components/mixins/transition.js @@ -0,0 +1,118 @@ +import { isObj } from '../common/utils'; +const getClassNames = (name) => ({ + enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`, + 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`, + leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`, + 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class` +}); +const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30)); +export const transition = function (showDefaultValue) { + return Behavior({ + properties: { + customStyle: String, + // @ts-ignore + show: { + type: Boolean, + value: showDefaultValue, + observer: 'observeShow' + }, + // @ts-ignore + duration: { + type: null, + value: 300, + observer: 'observeDuration' + }, + name: { + type: String, + value: 'fade' + } + }, + data: { + type: '', + inited: false, + display: false + }, + methods: { + observeShow(value, old) { + if (value === old) { + return; + } + value ? this.enter() : this.leave(); + }, + enter() { + const { duration, name } = this.data; + const classNames = getClassNames(name); + const currentDuration = isObj(duration) ? duration.enter : duration; + this.status = 'enter'; + this.$emit('before-enter'); + Promise.resolve() + .then(nextTick) + .then(() => { + this.checkStatus('enter'); + this.$emit('enter'); + this.setData({ + inited: true, + display: true, + classes: classNames.enter, + currentDuration + }); + }) + .then(nextTick) + .then(() => { + this.checkStatus('enter'); + this.transitionEnded = false; + this.setData({ + classes: classNames['enter-to'] + }); + }) + .catch(() => { }); + }, + leave() { + if (!this.data.display) { + return; + } + const { duration, name } = this.data; + const classNames = getClassNames(name); + const currentDuration = isObj(duration) ? duration.leave : duration; + this.status = 'leave'; + this.$emit('before-leave'); + Promise.resolve() + .then(nextTick) + .then(() => { + this.checkStatus('leave'); + this.$emit('leave'); + this.setData({ + classes: classNames.leave, + currentDuration + }); + }) + .then(nextTick) + .then(() => { + this.checkStatus('leave'); + this.transitionEnded = false; + setTimeout(() => this.onTransitionEnd(), currentDuration); + this.setData({ + classes: classNames['leave-to'] + }); + }) + .catch(() => { }); + }, + checkStatus(status) { + if (status !== this.status) { + throw new Error(`incongruent status: ${status}`); + } + }, + onTransitionEnd() { + if (this.transitionEnded) { + return; + } + this.transitionEnded = true; + this.$emit(`after-${this.status}`); + const { show, display } = this.data; + if (!show && display) { + this.setData({ display: false }); + } + } + } + }); +}; diff --git a/components/notice-bar/index.js b/components/notice-bar/index.js new file mode 100644 index 0000000..0a1ac0a --- /dev/null +++ b/components/notice-bar/index.js @@ -0,0 +1,128 @@ +import { VantComponent } from '../common/component'; +const FONT_COLOR = '#ed6a0c'; +const BG_COLOR = '#fffbe8'; +VantComponent({ + props: { + text: { + type: String, + value: '', + observer() { + wx.nextTick(() => { + this.init(); + }); + }, + }, + mode: { + type: String, + value: '' + }, + url: { + type: String, + value: '' + }, + openType: { + type: String, + value: 'navigate' + }, + delay: { + type: Number, + value: 1 + }, + speed: { + type: Number, + value: 50, + observer() { + wx.nextTick(() => { + this.init(); + }); + } + }, + scrollable: { + type: Boolean, + value: true + }, + leftIcon: { + type: String, + value: '' + }, + color: { + type: String, + value: FONT_COLOR + }, + backgroundColor: { + type: String, + value: BG_COLOR + }, + wrapable: Boolean + }, + data: { + show: true + }, + created() { + this.resetAnimation = wx.createAnimation({ + duration: 0, + timingFunction: 'linear' + }); + }, + destroyed() { + this.timer && clearTimeout(this.timer); + }, + methods: { + init() { + Promise.all([ + this.getRect('.van-notice-bar__content'), + this.getRect('.van-notice-bar__wrap') + ]).then((rects) => { + const [contentRect, wrapRect] = rects; + if (contentRect == null || + wrapRect == null || + !contentRect.width || + !wrapRect.width) { + return; + } + const { speed, scrollable, delay } = this.data; + if (scrollable && wrapRect.width < contentRect.width) { + const duration = (contentRect.width / speed) * 1000; + this.wrapWidth = wrapRect.width; + this.contentWidth = contentRect.width; + this.duration = duration; + this.animation = wx.createAnimation({ + duration, + timingFunction: 'linear', + delay + }); + this.scroll(); + } + }); + }, + scroll() { + this.timer && clearTimeout(this.timer); + this.timer = null; + this.setData({ + animationData: this.resetAnimation + .translateX(this.wrapWidth) + .step() + .export() + }); + setTimeout(() => { + this.setData({ + animationData: this.animation + .translateX(-this.contentWidth) + .step() + .export() + }); + }, 20); + this.timer = setTimeout(() => { + this.scroll(); + }, this.duration); + }, + onClickIcon() { + this.timer && clearTimeout(this.timer); + this.timer = null; + this.setData({ show: false }); + }, + onClick(event) { + this.$emit('click', event); + } + } +}); diff --git a/components/notice-bar/index.json b/components/notice-bar/index.json new file mode 100644 index 0000000..a9ab393 --- /dev/null +++ b/components/notice-bar/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} \ No newline at end of file diff --git a/components/notice-bar/index.wxml b/components/notice-bar/index.wxml new file mode 100644 index 0000000..eb0851c --- /dev/null +++ b/components/notice-bar/index.wxml @@ -0,0 +1,37 @@ + + + + + + + + + {{ text }} + + + + + + + + + diff --git a/components/notice-bar/index.wxss b/components/notice-bar/index.wxss new file mode 100644 index 0000000..6a49858 --- /dev/null +++ b/components/notice-bar/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:40px;height:var(--notice-bar-height,40px);padding:0 16px;padding:var(--notice-bar-padding,0 16px);font-size:14px;font-size:var(--notice-bar-font-size,14px);color:#ed6a0c;color:var(--notice-bar-text-color,#ed6a0c);line-height:24px;line-height:var(--notice-bar-line-height,24px);background-color:#fffbe8;background-color:var(--notice-bar-background-color,#fffbe8)}.van-notice-bar--withicon{position:relative;padding-right:40px}.van-notice-bar--wrapable{height:auto;padding:8px 16px;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:16px;font-size:var(--notice-bar-icon-size,16px);min-width:22px;min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px}.van-notice-bar__wrap{position:relative;-webkit-flex:1;flex:1;overflow:hidden;height:24px;height:var(--notice-bar-line-height,24px)}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%} \ No newline at end of file diff --git a/components/overlay/index.js b/components/overlay/index.js new file mode 100644 index 0000000..848b5a7 --- /dev/null +++ b/components/overlay/index.js @@ -0,0 +1,22 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + show: Boolean, + customStyle: String, + duration: { + type: null, + value: 0 + }, + zIndex: { + type: Number, + value: 1 + } + }, + methods: { + onClick() { + this.$emit('click'); + }, + // for prevent touchmove + noop() { } + } +}); diff --git a/components/overlay/index.json b/components/overlay/index.json new file mode 100644 index 0000000..c14a65f --- /dev/null +++ b/components/overlay/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-transition": "../transition/index" + } +} diff --git a/components/overlay/index.wxml b/components/overlay/index.wxml new file mode 100644 index 0000000..9212348 --- /dev/null +++ b/components/overlay/index.wxml @@ -0,0 +1,10 @@ + + + diff --git a/components/overlay/index.wxss b/components/overlay/index.wxss new file mode 100644 index 0000000..342d1d5 --- /dev/null +++ b/components/overlay/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.8);background-color:var(--overlay-background-color,rgba(0,0,0,.6))} \ No newline at end of file diff --git a/components/picker-column/index.js b/components/picker-column/index.js new file mode 100644 index 0000000..80ac3fd --- /dev/null +++ b/components/picker-column/index.js @@ -0,0 +1,117 @@ +import { VantComponent } from '../common/component'; +import { isObj, range } from '../common/utils'; +const DEFAULT_DURATION = 200; +VantComponent({ + classes: ['active-class'], + props: { + valueKey: String, + className: String, + itemHeight: Number, + visibleItemCount: Number, + initialOptions: { + type: Array, + value: [] + }, + defaultIndex: { + type: Number, + value: 0, + observer(value) { + this.setIndex(value); + } + } + }, + data: { + startY: 0, + offset: 0, + duration: 0, + startOffset: 0, + options: [], + currentIndex: 0 + }, + created() { + const { defaultIndex, initialOptions } = this.data; + this.set({ + currentIndex: defaultIndex, + options: initialOptions + }).then(() => { + this.setIndex(defaultIndex); + }); + }, + methods: { + getCount() { + return this.data.options.length; + }, + onTouchStart(event) { + this.setData({ + startY: event.touches[0].clientY, + startOffset: this.data.offset, + duration: 0 + }); + }, + onTouchMove(event) { + const { data } = this; + const deltaY = event.touches[0].clientY - data.startY; + this.setData({ + offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight) + }); + }, + onTouchEnd() { + const { data } = this; + if (data.offset !== data.startOffset) { + this.setData({ duration: DEFAULT_DURATION }); + const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1); + this.setIndex(index, true); + } + }, + onClickItem(event) { + const { index } = event.currentTarget.dataset; + this.setIndex(index, true); + }, + adjustIndex(index) { + const { data } = this; + const count = this.getCount(); + index = range(index, 0, count); + for (let i = index; i < count; i++) { + if (!this.isDisabled(data.options[i])) + return i; + } + for (let i = index - 1; i >= 0; i--) { + if (!this.isDisabled(data.options[i])) + return i; + } + }, + isDisabled(option) { + return isObj(option) && option.disabled; + }, + getOptionText(option) { + const { data } = this; + return isObj(option) && data.valueKey in option + ? option[data.valueKey] + : option; + }, + setIndex(index, userAction) { + const { data } = this; + index = this.adjustIndex(index) || 0; + const offset = -index * data.itemHeight; + if (index !== data.currentIndex) { + return this.set({ offset, currentIndex: index }).then(() => { + userAction && this.$emit('change', index); + }); + } + return this.set({ offset }); + }, + setValue(value) { + const { options } = this.data; + for (let i = 0; i < options.length; i++) { + if (this.getOptionText(options[i]) === value) { + return this.setIndex(i); + } + } + return Promise.resolve(); + }, + getValue() { + const { data } = this; + return data.options[data.currentIndex]; + } + } +}); diff --git a/components/picker-column/index.json b/components/picker-column/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/picker-column/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/picker-column/index.wxml b/components/picker-column/index.wxml new file mode 100644 index 0000000..f052ed9 --- /dev/null +++ b/components/picker-column/index.wxml @@ -0,0 +1,22 @@ + + + + + {{ getOptionText(option, valueKey) }} + + diff --git a/components/picker-column/index.wxs b/components/picker-column/index.wxs new file mode 100644 index 0000000..3c8fc68 --- /dev/null +++ b/components/picker-column/index.wxs @@ -0,0 +1,8 @@ +function isObj(x) { + var type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +} + +module.exports = function (option, valueKey) { + return isObj(option) && option[valueKey] != null ? option[valueKey] : option; +} diff --git a/components/picker-column/index.wxss b/components/picker-column/index.wxss new file mode 100644 index 0000000..c5c6910 --- /dev/null +++ b/components/picker-column/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-picker-column{overflow:hidden;text-align:center;color:#000;color:var(--picker-option-text-color,#000);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--picker-option-selected-text-color,#323233)}.van-picker-column__item--disabled{opacity:.3;opacity:var(--picker-option-disabled-opacity,.3)} \ No newline at end of file diff --git a/components/picker/index.js b/components/picker/index.js new file mode 100644 index 0000000..6a28a20 --- /dev/null +++ b/components/picker/index.js @@ -0,0 +1,140 @@ +import { VantComponent } from '../common/component'; +import { pickerProps } from './shared'; +VantComponent({ + classes: ['active-class', 'toolbar-class', 'column-class'], + props: Object.assign(Object.assign({}, pickerProps), { + valueKey: { + type: String, + value: 'text' + }, + toolbarPosition: { + type: String, + value: 'top' + }, + defaultIndex: { + type: Number, + value: 0 + }, + columns: { + type: Array, + value: [], + observer(columns = []) { + this.simple = columns.length && !columns[0].values; + this.children = this.selectAllComponents('.van-picker__column'); + if (Array.isArray(this.children) && this.children.length) { + this.setColumns().catch(() => { }); + } + } + } + }), + beforeCreate() { + this.children = []; + }, + methods: { + noop() { }, + setColumns() { + const { data } = this; + const columns = this.simple ? [{ values: data.columns }] : data.columns; + const stack = columns.map((column, index) => this.setColumnValues(index, column.values)); + return Promise.all(stack); + }, + emit(event) { + const { type } = event.currentTarget.dataset; + if (this.simple) { + this.$emit(type, { + value: this.getColumnValue(0), + index: this.getColumnIndex(0) + }); + } + else { + this.$emit(type, { + value: this.getValues(), + index: this.getIndexes() + }); + } + }, + onChange(event) { + if (this.simple) { + this.$emit('change', { + picker: this, + value: this.getColumnValue(0), + index: this.getColumnIndex(0) + }); + } + else { + this.$emit('change', { + picker: this, + value: this.getValues(), + index: event.currentTarget.dataset.index + }); + } + }, + // get column instance by index + getColumn(index) { + return this.children[index]; + }, + // get column value by index + getColumnValue(index) { + const column = this.getColumn(index); + return column && column.getValue(); + }, + // set column value by index + setColumnValue(index, value) { + const column = this.getColumn(index); + if (column == null) { + return Promise.reject(new Error('setColumnValue: 对应列不存在')); + } + return column.setValue(value); + }, + // get column option index by column index + getColumnIndex(columnIndex) { + return (this.getColumn(columnIndex) || {}).data.currentIndex; + }, + // set column option index by column index + setColumnIndex(columnIndex, optionIndex) { + const column = this.getColumn(columnIndex); + if (column == null) { + return Promise.reject(new Error('setColumnIndex: 对应列不存在')); + } + return column.setIndex(optionIndex); + }, + // get options of column by index + getColumnValues(index) { + return (this.children[index] || {}).data.options; + }, + // set options of column by index + setColumnValues(index, options, needReset = true) { + const column = this.children[index]; + if (column == null) { + return Promise.reject(new Error('setColumnValues: 对应列不存在')); + } + const isSame = JSON.stringify(column.data.options) === JSON.stringify(options); + if (isSame) { + return Promise.resolve(); + } + return column.set({ options }).then(() => { + if (needReset) { + column.setIndex(0); + } + }); + }, + // get values of all columns + getValues() { + return this.children.map((child) => child.getValue()); + }, + // set values of all columns + setValues(values) { + const stack = values.map((value, index) => this.setColumnValue(index, value)); + return Promise.all(stack); + }, + // get indexes of all columns + getIndexes() { + return this.children.map((child) => child.data.currentIndex); + }, + // set indexes of all columns + setIndexes(indexes) { + const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex)); + return Promise.all(stack); + } + } +}); diff --git a/components/picker/index.json b/components/picker/index.json new file mode 100644 index 0000000..2fcec89 --- /dev/null +++ b/components/picker/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "picker-column": "../picker-column/index", + "loading": "../loading/index" + } +} diff --git a/components/picker/index.wxml b/components/picker/index.wxml new file mode 100644 index 0000000..bcd9eb9 --- /dev/null +++ b/components/picker/index.wxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + function isSimple(columns) { + return columns.length && !columns[0].values; + } + module.exports = isSimple; + \ No newline at end of file diff --git a/components/picker/index.wxss b/components/picker/index.wxss new file mode 100644 index 0000000..f8bfa93 --- /dev/null +++ b/components/picker/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;-webkit-user-select:none;user-select:none;background-color:#fff;background-color:var(--picker-background-color,#fff)}.van-picker__toolbar{display:-webkit-flex;display:flex;-webkit-justify-content:space-between;justify-content:space-between;height:44px;height:var(--picker-toolbar-height,44px);line-height:44px;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#666666;color:var(--picker-action-text-color,#666666)}.van-picker__confirm{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#1989fa;color:var(--picker-action-text-color,#1989fa)}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5;background-color:var(--picker-action-active-color,#f2f3f5)}.van-picker__title{max-width:50%;text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background-color:hsla(0,0%,100%,.9);background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9))}.van-picker__mask{position:absolute;top:0;left:0;z-index:2;width:100%;height:100%;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-repeat:no-repeat;background-position:top,bottom;-webkit-backface-visibility:hidden;backface-visibility:hidden;pointer-events:none}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);pointer-events:none} \ No newline at end of file diff --git a/components/picker/shared.js b/components/picker/shared.js new file mode 100644 index 0000000..cf57d1d --- /dev/null +++ b/components/picker/shared.js @@ -0,0 +1,21 @@ +export const pickerProps = { + title: String, + loading: Boolean, + showToolbar: Boolean, + cancelButtonText: { + type: String, + value: '取消' + }, + confirmButtonText: { + type: String, + value: '确认' + }, + visibleItemCount: { + type: Number, + value: 5 + }, + itemHeight: { + type: Number, + value: 44 + } +}; diff --git a/components/picker/toolbar.wxml b/components/picker/toolbar.wxml new file mode 100644 index 0000000..d112b29 --- /dev/null +++ b/components/picker/toolbar.wxml @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/components/plate-keyboard/index.js b/components/plate-keyboard/index.js new file mode 100644 index 0000000..7d6a81c --- /dev/null +++ b/components/plate-keyboard/index.js @@ -0,0 +1,116 @@ +Component({ + options: { + addGlobalClass: true, + }, + properties: { + plateNumber: { + type: Array, + value: ["", "", "", "", "", "", ""] + }, + triplet: { + type: Number, + value: 0 + }, + plateList: { + type: Array, + value: [] + }, + safeBottom: { + type: Number, + value: 0 + } + }, + data: { + provinces: "京津沪冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤川青藏琼宁渝港澳台", + letters: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + numbers: "0123456789", + visible: false, + activeIndex: -1, + type: 0, + disabled: true, + mode: 0 // 键盘模式 0 关闭状态 1 显示省份输入 2 显示数字和字母输入 + }, + lifetimes: { + attached: function () { + + }, + }, + methods: { + show: function (number, type) { + var index = 0 + if(number && number.length == 7){ + this.data.plateNumber = number.split('') + index = this.data.plateNumber.length - 1 + } else { + this.data.plateNumber = ["", "", "", "", "", "", ""] + } + this.data.type = type + this.updateNumber() + this.setData({ plateNumber: this.data.plateNumber, mode: index == 0 ? 1 : 2, activeIndex: index, visible: true}) + }, + hide: function () { + this.setData({visible: false, plateNumber: ["", "", "", "", "", "", ""]}) + this.triggerEvent("change", null) + }, + updateNumber: function(){ + this.data.disabled = false + for (let index = 0; index < this.data.plateNumber.length; index++) { + const element = this.data.plateNumber[index] + if(element.length == 0){ + this.data.disabled = true + break + } + } + this.setData({disabled: this.data.disabled, plateNumber: this.data.plateNumber}) + }, + inputKeyboard: function(e){ + let index = typeof e === 'number' ? e : e.currentTarget.dataset.index + if(e.currentTarget && this.data.plateNumber[index].length == 0){ + return + } + this.setData({ mode: index == 0 ? 1 : 2, activeIndex: index }) + }, + tapClear: function(){ + if(this.data.activeIndex == -1){ + return + } + this.setData({disabled: true, plateNumber: ["", "", "", "", "", "", ""], mode: 1, activeIndex: 0}) + }, + tapDelete: function(e){ + let activeIndex = this.data.activeIndex + this.data.plateNumber[activeIndex] = '' + this.updateNumber() + if (activeIndex > 0) { + this.inputKeyboard(--activeIndex) + } + }, + tapFinish: function(e){ + var plateNumber = '' + if(e){ + plateNumber = this.data.plateList[e.currentTarget.dataset.index] + } else { + if(this.data.disabled){ + return + } + plateNumber = this.data.plateNumber.join('') + } + this.setData({visible: false, activeIndex: -1 }) + this.triggerEvent("change", {plateNumber, type: this.data.type}) + }, + tapTriplet: function(){ + this.setData({visible: false, activeIndex: -1 }) + this.triggerEvent("change", { plateNumber: '三轮车', type: this.data.type}) + }, + tapKeyboard: function(e){ + let val = e.currentTarget.dataset.val + let activeIndex = this.data.activeIndex + this.data.plateNumber[activeIndex] = val + this.updateNumber() + if (activeIndex < 6) { + this.inputKeyboard(++activeIndex) + } else { + this.tapFinish() + } + }, + } +}) \ No newline at end of file diff --git a/components/plate-keyboard/index.json b/components/plate-keyboard/index.json new file mode 100644 index 0000000..0e0088d --- /dev/null +++ b/components/plate-keyboard/index.json @@ -0,0 +1,9 @@ +{ + "component": true, + "usingComponents": { + "van-button": "/components/button/index", + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index", + "van-popup": "../popup/index" + } +} \ No newline at end of file diff --git a/components/plate-keyboard/index.wxml b/components/plate-keyboard/index.wxml new file mode 100644 index 0000000..86f3ed4 --- /dev/null +++ b/components/plate-keyboard/index.wxml @@ -0,0 +1,48 @@ + + + + + + 车辆历史记录 + + 清空输入 + + + + {{item}} + + + + + {{plateNumber[0]}} + {{plateNumber[1]}} + + {{plateNumber[2]}} + {{plateNumber[3]}} + {{plateNumber[4]}} + {{plateNumber[5]}} + {{plateNumber[6]}} + + + + + + + + 三轮车 + + + + 确定 + + + + \ No newline at end of file diff --git a/components/plate-keyboard/index.wxss b/components/plate-keyboard/index.wxss new file mode 100644 index 0000000..e80c4ba --- /dev/null +++ b/components/plate-keyboard/index.wxss @@ -0,0 +1,113 @@ + +.license-number .item { + width: 64rpx; + height: 72rpx; + line-height: 72rpx; + text-align: center; + border: 1rpx solid #999590; + border-radius: 8rpx; + display: flex; + font-size: 32rpx; + align-items: center; + justify-content: center; +} +.license-number .item.item-new-energy { + line-height: 1em; + display: flex; + align-items: center; + border: 1rpx dashed #999590; +} +.license-number .item.item-new-energy .ico { + line-height: 1em; + font-size: 36rpx; + margin-bottom: -5rpx; + color: #777; +} +.license-number .item.item-new-energy .tit { + font-size: 12px; + transform: scale(0.7); + color: #777; +} + +.license-number .item.active { + border: 1rpx solid #008AFF; + color:#008AFF; +} + +.license-number .item.item-dot { + border: none; + width: auto; + padding: 0 6rpx; +} +.license-number .item.item-dot .dot { + width: 12rpx; + height: 12rpx; + background: #a09c96; + border-radius: 10rpx; +} + +.kb-keyboard { + padding: 6rpx; + position: relative; +} +.flex-brick { + display: flex; + flex-flow: row wrap; +} +.kb-keyboard-action { + display: flex; + justify-content: space-between; + position: absolute; + bottom: 6rpx; + right: 6rpx; +} +.kb-keyboard_td { + color: #1e1e1e; + box-shadow: 1rpx 1rpx 1rpx #919191; + background: #fff; + display: flex; + align-items: center; + justify-content: center; + width: calc((100vw - 12rpx) / 10 - 12rpx); + font-size: 18px; + height: 48px; + margin: 6rpx; + border-radius:5px; +} + +.kb-keyboard_td.disabled { + opacity: 0.5; + pointer-events: none; +} + +.kb-keyboard_td:active { + background: #f2f2f2; +} +.kb-keyboard__del { + align-self: flex-end; + width: calc(((100vw - 12rpx) / 10 - 12rpx) * 1.8); + height: 48px; + display: flex; + justify-content: center; + align-items: center; + padding-right: 1rpx; +} +.kb-keyboard__del .ico-del { + width: 44rpx; + height: 30rpx; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAeCAMAAABg6AyVAAAAclBMVEUAAAAwMDAxMTEMDAwpKSkpKSkwMDAqKioxMTExMTEpKSkqKiokJCQpKSkpKSkqKioqKioqKioqKioqKiopKSkoKCgoKCgnJycqKioqKioqKioqKioqKioqKioqKiorKysrKysoKCgqKioAAAAlJSUqKipvWYGQAAAAJXRSTlMA/lcC+OyZhmk+lioH8OXd1MlOPzQZDCDcvr2ysaWjajsTEgEiwq/YugAAAM9JREFUOMud1McWgyAQBdABKxp7S+/v/38xDUPAY/DwNs7iLoQZhoycCswkiFY69RL8SaTbA/yaZnJGQD9Z7ZA1NBuAVPoNgpaW4UuFPKVluCuxHmgZHgqUnTxmHAqSEWHsTXCao7rKOmaM8U/Jn2Vs4jbAtieZkL30aFlo4CbDXrVHsLeWlgkd1z6O3teOiMsPaZj7SG5EE62swqkvm25qZRWOkNAkfLTu2P4bzge0X51rU+ztdh0kmbtlRC3D7/Cs3B+s6yqwLxnX9WVfjA8P3SLCPZZ7QgAAAABJRU5ErkJggg==); + background-size: 100% 100%; +} +.kb-keyboard__finished { + width: calc(((100vw - 12rpx) / 10 - 12rpx) * 1.8); +} + + +@keyframes breath { + from { + border-color:rgba(11, 245, 183, 0.3); + } + 40% { border-color: #0bf5b7c2; } + 60% { border-color: #0bf5b7c2; } + to { border-color: rgba(11, 245, 183, 0.3); } +} \ No newline at end of file diff --git a/components/popover/index.js b/components/popover/index.js new file mode 100644 index 0000000..9c79ff2 --- /dev/null +++ b/components/popover/index.js @@ -0,0 +1,234 @@ +import baseComponent from '../helpers/baseComponent' +import classNames from '../helpers/classNames' +import styleToCssString from '../helpers/styleToCssString' + +const getPlacements = ([a, s, b] = rects, placement = 'top') => { + switch (placement) { + case 'topLeft': + return { + top: s.scrollTop + a.top - b.height - 4, + left: s.scrollLeft + a.left, + } + case 'top': + return { + top: s.scrollTop + a.top - b.height - 4, + left: s.scrollLeft + a.left + (a.width - b.width) / 2, + } + case 'topRight': + return { + top: s.scrollTop + a.top - b.height - 4, + left: s.scrollLeft + a.left + a.width - b.width, + } + case 'rightTop': + return { + top: s.scrollTop + a.top, + left: s.scrollLeft + a.left + a.width + 4, + } + case 'right': + return { + top: s.scrollTop + a.top + (a.height - b.height) / 2, + left: s.scrollLeft + a.left + a.width + 4, + } + case 'rightBottom': + return { + top: s.scrollTop + a.top + a.height - b.height, + left: s.scrollLeft + a.left + a.width + 4, + } + case 'bottomRight': + return { + top: s.scrollTop + a.top + a.height + 4, + left: s.scrollLeft + a.left + a.width - b.width, + } + case 'bottom': + return { + top: s.scrollTop + a.top + a.height + 4, + left: s.scrollLeft + a.left + (a.width - b.width) / 2, + } + case 'bottomLeft': + return { + top: s.scrollTop + a.top + a.height + 4, + left: s.scrollLeft + a.left, + } + case 'leftBottom': + return { + top: s.scrollTop + a.top + a.height - b.height, + left: s.scrollLeft + a.left - b.width - 4, + } + case 'left': + return { + top: s.scrollTop + a.top + (a.height - b.height) / 2, + left: s.scrollLeft + a.left - b.width - 4, + } + case 'leftTop': + return { + top: s.scrollTop + a.top, + left: s.scrollLeft + a.left - b.width - 4, + } + default: + return { + left: 0, + top: 0, + } + } +} + +baseComponent({ + properties: { + prefixCls: { + type: String, + value: 'wux-popover', + }, + classNames: { + type: null, + value: 'wux-animate--fadeIn', + }, + theme: { + type: String, + value: 'light', + }, + title: { + type: String, + value: '', + }, + content: { + type: String, + value: '', + }, + placement: { + type: String, + value: 'top', + }, + trigger: { + type: String, + value: 'click', + }, + bodyStyle: { + type: [String, Object], + value: '', + observer(newVal) { + this.setData({ + extStyle: styleToCssString(newVal), + }) + }, + }, + defaultVisible: { + type: Boolean, + value: false, + }, + visible: { + type: Boolean, + value: false, + observer(newVal) { + if (this.data.controlled) { + this.updated(newVal) + } + }, + }, + controlled: { + type: Boolean, + value: false, + }, + mask: { + type: Boolean, + value: false, + }, + maskClosable: { + type: Boolean, + value: true, + }, + }, + data: { + extStyle: '', + popoverStyle: '', + popoverVisible: false, + }, + computed: { + classes: ['prefixCls, theme, placement', function(prefixCls, theme, placement) { + const wrap = classNames(prefixCls, { + [`${prefixCls}--theme-${theme}`]: theme, + [`${prefixCls}--placement-${placement}`]: placement, + }) + const content = `${prefixCls}__content` + const arrow = `${prefixCls}__arrow` + const inner = `${prefixCls}__inner` + const title = `${prefixCls}__title` + const innerContent = `${prefixCls}__inner-content` + const element = `${prefixCls}__element` + + return { + wrap, + content, + arrow, + inner, + title, + innerContent, + element, + } + }], + }, + methods: { + updated(popoverVisible) { + if (this.data.popoverVisible !== popoverVisible) { + this.setData({ popoverVisible }) + this.setBackdropVisible(popoverVisible) + } + }, + getPopoverStyle() { + const { prefixCls, placement } = this.data + const query = wx.createSelectorQuery().in(this) + query.select(`.${prefixCls}__element`).boundingClientRect() + query.selectViewport().scrollOffset() + query.select(`.${prefixCls}`).boundingClientRect() + query.exec((rects) => { + if (rects.filter((n) => !n).length) return + + const placements = getPlacements(rects, placement) + const popoverStyle = styleToCssString(placements) + + this.setData({ + popoverStyle, + }) + }) + }, + /** + * 当组件进入过渡的开始状态时,设置气泡框位置信息 + */ + onEnter() { + this.getPopoverStyle() + }, + onChange() { + const { popoverVisible, controlled } = this.data + const nextVisible = !popoverVisible + + if (!controlled) { + this.updated(nextVisible) + } + + this.triggerEvent('change', { visible: nextVisible }) + }, + onClick() { + if (this.data.trigger === 'click') { + this.onChange() + } + }, + setBackdropVisible(visible) { + if (this.data.mask && this.wuxBackdrop) { + this.wuxBackdrop[visible ? 'retain' : 'release']() + } + }, + onMaskClick() { + const { maskClosable, popoverVisible } = this.data + if (maskClosable && popoverVisible) { + this.onChange() + } + }, + }, + ready() { + const { defaultVisible, visible, controlled } = this.data + const popoverVisible = controlled ? visible : defaultVisible + if (this.data.mask) { + this.wuxBackdrop = this.selectComponent('#wux-backdrop') + } + this.updated(popoverVisible) + }, +}) diff --git a/components/popover/index.json b/components/popover/index.json new file mode 100644 index 0000000..716bdf5 --- /dev/null +++ b/components/popover/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "wux-animation-group": "../animation-group/index", + "wux-backdrop": "../backdrop/index" + } +} diff --git a/components/popover/index.wxml b/components/popover/index.wxml new file mode 100644 index 0000000..c1dfa43 --- /dev/null +++ b/components/popover/index.wxml @@ -0,0 +1,17 @@ + + + + + + + {{ title }} + + {{ content }} + + + + + + + + diff --git a/components/popover/index.wxss b/components/popover/index.wxss new file mode 100644 index 0000000..24f765a --- /dev/null +++ b/components/popover/index.wxss @@ -0,0 +1,193 @@ +.wux-popover { + font-family: Monospaced Number,Chinese Quote,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif; + font-size: 28rpx; + line-height: 1.5; + color: rgba(0,0,0,.65); + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + position: absolute; + top: 0; + left: 0; + z-index: 1030; + cursor: auto; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + white-space: normal; + font-weight: 400; + text-align: left +} +.wux-popover::after { + content: ""; + position: absolute; + background: rgba(255,255,255,.01) +} +.wux-popover__container { + position: absolute; + top: 0; + left: 0; + width: 100% +} +.wux-popover__element { + display: inline-block; + line-height: 1 +} +.wux-popover--theme-dark .wux-popover__inner { + background-color: #333 +} +.wux-popover--theme-dark.wux-popover--placement-top .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-topLeft .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-topRight .wux-popover__arrow { + border-top-color: #333 +} +.wux-popover--theme-dark.wux-popover--placement-right .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-rightBottom .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-rightTop .wux-popover__arrow { + border-right-color: #333 +} +.wux-popover--theme-dark.wux-popover--placement-bottom .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-bottomLeft .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-bottomRight .wux-popover__arrow { + border-bottom-color: #333 +} +.wux-popover--theme-dark.wux-popover--placement-left .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-leftBottom .wux-popover__arrow, +.wux-popover--theme-dark.wux-popover--placement-leftTop .wux-popover__arrow { + border-left-color: #333 +} +.wux-popover--theme-dark .wux-popover__inner, +.wux-popover--theme-dark .wux-popover__title { + color: #fff +} +.wux-popover--placement-top, +.wux-popover--placement-topLeft, +.wux-popover--placement-topRight { + padding-bottom: 10px +} +.wux-popover--placement-right, +.wux-popover--placement-rightBottom, +.wux-popover--placement-rightTop { + padding-left: 10px +} +.wux-popover--placement-bottom, +.wux-popover--placement-bottomLeft, +.wux-popover--placement-bottomRight { + padding-top: 10px +} +.wux-popover--placement-left, +.wux-popover--placement-leftBottom, +.wux-popover--placement-leftTop { + padding-right: 10px +} +.wux-popover__inner { + background-color: #fff; + background-clip: padding-box; + border-radius: 4px; + box-shadow: 0 2px 8px rgba(0,0,0,.15); + color: rgba(0,0,0,.65) +} +.wux-popover__title { + position: relative; + min-width: 120px; + margin: 0; + padding: 5px 16px 4px; + min-height: 32px; + box-sizing: border-box; + color: rgba(0,0,0,.85); + font-weight: 500 +} +.wux-popover__title::after { + content: " "; + position: absolute; + left: 0; + bottom: 0; + right: 0; + height: 1PX; + border-bottom: 1PX solid #d9d9d9; + color: #d9d9d9; + transform-origin: 0 100%; + transform: scaleY(.5) +} +.wux-popover__inner-content { + padding: 24rpx 32rpx +} +.wux-popover__arrow { + width: 0; + height: 0; + position: absolute; + display: block; + border-color: transparent; + border-style: solid; + border-width: 16.97056274rpx +} +.wux-popover--placement-top .wux-popover__arrow, +.wux-popover--placement-topLeft .wux-popover__arrow, +.wux-popover--placement-topRight .wux-popover__arrow { + bottom: 8rpx; + border-bottom-width: 0; + border-top-color: #fff +} +.wux-popover--placement-top .wux-popover__arrow { + left: 50%; + transform: translateX(-50%) +} +.wux-popover--placement-topLeft .wux-popover__arrow { + left: 32rpx +} +.wux-popover--placement-topRight .wux-popover__arrow { + right: 32rpx +} +.wux-popover--placement-right .wux-popover__arrow, +.wux-popover--placement-rightBottom .wux-popover__arrow, +.wux-popover--placement-rightTop .wux-popover__arrow { + left: 8rpx; + border-left-width: 0; + border-right-color: #fff +} +.wux-popover--placement-right .wux-popover__arrow { + top: 50%; + transform: translateY(-50%) +} +.wux-popover--placement-rightTop .wux-popover__arrow { + top: 24rpx +} +.wux-popover--placement-rightBottom .wux-popover__arrow { + bottom: 24rpx +} +.wux-popover--placement-bottom .wux-popover__arrow, +.wux-popover--placement-bottomLeft .wux-popover__arrow, +.wux-popover--placement-bottomRight .wux-popover__arrow { + top: 8rpx; + border-top-width: 0; + border-bottom-color: #fff +} +.wux-popover--placement-bottom .wux-popover__arrow { + left: 50%; + transform: translateX(-50%) +} +.wux-popover--placement-bottomLeft .wux-popover__arrow { + left: 32rpx +} +.wux-popover--placement-bottomRight .wux-popover__arrow { + right: 32rpx +} +.wux-popover--placement-left .wux-popover__arrow, +.wux-popover--placement-leftBottom .wux-popover__arrow, +.wux-popover--placement-leftTop .wux-popover__arrow { + right: 8rpx; + border-right-width: 0; + border-left-color: #fff +} +.wux-popover--placement-left .wux-popover__arrow { + top: 50%; + transform: translateY(-50%) +} +.wux-popover--placement-leftTop .wux-popover__arrow { + top: 24rpx +} +.wux-popover--placement-leftBottom .wux-popover__arrow { + bottom: 24rpx +} \ No newline at end of file diff --git a/components/popup/index.js b/components/popup/index.js new file mode 100644 index 0000000..c80ba39 --- /dev/null +++ b/components/popup/index.js @@ -0,0 +1,81 @@ +import { VantComponent } from '../common/component'; +import { transition } from '../mixins/transition'; +VantComponent({ + classes: [ + 'enter-class', + 'enter-active-class', + 'enter-to-class', + 'leave-class', + 'leave-active-class', + 'leave-to-class', + 'close-icon-class' + ], + mixins: [transition(false)], + props: { + round: Boolean, + closeable: Boolean, + customStyle: String, + overlayStyle: String, + transition: { + type: String, + observer: 'observeClass' + }, + zIndex: { + type: Number, + value: 29 + }, + overlay: { + type: Boolean, + value: true + }, + closeIcon: { + type: String, + value: 'cross' + }, + closeIconPosition: { + type: String, + value: 'top-right' + }, + closeOnClickOverlay: { + type: Boolean, + value: true + }, + position: { + type: String, + value: 'center', + observer: 'observeClass' + }, + safeAreaInsetBottom: { + type: Boolean, + value: true + }, + safeAreaInsetTop: { + type: Boolean, + value: false + } + }, + created() { + this.observeClass(); + }, + methods: { + onClickCloseIcon() { + this.$emit('close'); + }, + onClickOverlay() { + this.$emit('click-overlay'); + if (this.data.closeOnClickOverlay) { + this.$emit('close'); + } + }, + observeClass() { + const { transition, position } = this.data; + const updateData = { + name: transition || position + }; + if (transition === 'none') { + updateData.duration = 0; + } + this.setData(updateData); + } + } +}); diff --git a/components/popup/index.json b/components/popup/index.json new file mode 100644 index 0000000..88a6eab --- /dev/null +++ b/components/popup/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-overlay": "../overlay/index" + } +} diff --git a/components/popup/index.wxml b/components/popup/index.wxml new file mode 100644 index 0000000..992d2a7 --- /dev/null +++ b/components/popup/index.wxml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/components/popup/index.wxss b/components/popup/index.wxss new file mode 100644 index 0000000..60e6e5d --- /dev/null +++ b/components/popup/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-popup{position:fixed;box-sizing:border-box;max-height:100%;overflow-y:auto;transition-timing-function:ease;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;background-color:#fff;background-color:var(--popup-background-color,#fff)}.van-popup--center{top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:20px;border-radius:var(--popup-round-border-radius,20px)}.van-popup--top{top:0;left:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 20px 20px;border-radius:0 0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px)}.van-popup--right{top:50%;right:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:20px 0 0 20px;border-radius:var(--popup-round-border-radius,20px) 0 0 var(--popup-round-border-radius,20px)}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:20px 20px 0 0;border-radius:var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0 0}.van-popup--left{top:50%;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 20px 20px 0;border-radius:0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{position:absolute;z-index:1;z-index:var(--popup-close-icon-z-index,1);color:#969799;color:var(--popup-close-icon-color,#969799);font-size:18px;font-size:var(--popup-close-icon-size,18px)}.van-popup__close-icon--top-left{top:16px;top:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{top:16px;top:var(--popup-close-icon-margin,16px);right:16px;right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:16px;bottom:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{right:16px;right:var(--popup-close-icon-margin,16px);bottom:16px;bottom:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)} \ No newline at end of file diff --git a/components/radio-group/index.js b/components/radio-group/index.js new file mode 100644 index 0000000..2fa6c25 --- /dev/null +++ b/components/radio-group/index.js @@ -0,0 +1,34 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + field: true, + relation: { + name: 'radio', + type: 'descendant', + current: 'radio-group', + linked(target) { + this.updateChild(target); + }, + }, + props: { + value: { + type: null, + observer: 'updateChildren' + }, + disabled: { + type: Boolean, + observer: 'updateChildren' + } + }, + methods: { + updateChildren() { + (this.children || []).forEach((child) => this.updateChild(child)); + }, + updateChild(child) { + const { value, disabled } = this.data; + child.setData({ + value, + disabled: disabled || child.data.disabled + }); + } + } +}); diff --git a/components/radio-group/index.json b/components/radio-group/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/radio-group/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/radio-group/index.wxml b/components/radio-group/index.wxml new file mode 100644 index 0000000..4fa864c --- /dev/null +++ b/components/radio-group/index.wxml @@ -0,0 +1 @@ + diff --git a/components/radio-group/index.wxss b/components/radio-group/index.wxss new file mode 100644 index 0000000..99694d6 --- /dev/null +++ b/components/radio-group/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; \ No newline at end of file diff --git a/components/radio/index.js b/components/radio/index.js new file mode 100644 index 0000000..228523f --- /dev/null +++ b/components/radio/index.js @@ -0,0 +1,48 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + field: true, + relation: { + name: 'radio-group', + type: 'ancestor', + current: 'radio', + }, + classes: ['icon-class', 'label-class'], + props: { + name: null, + value: null, + disabled: Boolean, + useIconSlot: Boolean, + checkedColor: String, + labelPosition: { + type: String, + value: 'right' + }, + labelDisabled: Boolean, + shape: { + type: String, + value: 'round' + }, + iconSize: { + type: null, + value: 20 + } + }, + methods: { + emitChange(value) { + const instance = this.parent || this; + instance.$emit('input', value); + instance.$emit('change', value); + }, + onChange() { + if (!this.data.disabled) { + this.emitChange(this.data.name); + } + }, + onClickLabel() { + const { disabled, labelDisabled, name } = this.data; + if (!disabled && !labelDisabled) { + this.emitChange(name); + } + } + } +}); diff --git a/components/radio/index.json b/components/radio/index.json new file mode 100644 index 0000000..0a336c0 --- /dev/null +++ b/components/radio/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/components/radio/index.wxml b/components/radio/index.wxml new file mode 100644 index 0000000..e6b47cd --- /dev/null +++ b/components/radio/index.wxml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/radio/index.wxss b/components/radio/index.wxss new file mode 100644 index 0000000..96c81f0 --- /dev/null +++ b/components/radio/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-radio{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{-webkit-flex:none;flex:none}.van-radio__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;border:1px solid #c8c9cc;border:1px solid var(--radio-border-color,#c8c9cc);font-size:20px;font-size:var(--radio-size,20px);transition-duration:.2s;transition-duration:var(--radio-transition-duration,.2s)}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--radio-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--radio-checked-icon-color,#1989fa)}.van-radio__icon--disabled{background-color:#ebedf0;background-color:var(--radio-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:#c8c9cc;color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;margin-left:10px;margin-left:var(--radio-label-margin,10px);color:#323233;color:var(--radio-label-color,#323233);line-height:20px;line-height:var(--radio-size,20px)}.van-radio__label--left{float:left;margin:0 10px 0 0;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:#c8c9cc;color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0} \ No newline at end of file diff --git a/components/rate/index.js b/components/rate/index.js new file mode 100644 index 0000000..4efefda --- /dev/null +++ b/components/rate/index.js @@ -0,0 +1,80 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + field: true, + classes: ['icon-class'], + props: { + value: { + type: Number, + observer(value) { + if (value !== this.data.innerValue) { + this.setData({ innerValue: value }); + } + } + }, + readonly: Boolean, + disabled: Boolean, + allowHalf: Boolean, + size: null, + icon: { + type: String, + value: 'star' + }, + voidIcon: { + type: String, + value: 'star-o' + }, + color: { + type: String, + value: '#ffd21e' + }, + voidColor: { + type: String, + value: '#c7c7c7' + }, + disabledColor: { + type: String, + value: '#bdbdbd' + }, + count: { + type: Number, + value: 5, + observer(value) { + this.setData({ innerCountArray: Array.from({ length: value }) }); + }, + }, + gutter: null, + touchable: { + type: Boolean, + value: true + } + }, + data: { + innerValue: 0, + innerCountArray: Array.from({ length: 5 }), + }, + methods: { + onSelect(event) { + const { data } = this; + const { score } = event.currentTarget.dataset; + if (!data.disabled && !data.readonly) { + this.setData({ innerValue: score + 1 }); + this.$emit('input', score + 1); + this.$emit('change', score + 1); + } + }, + onTouchMove(event) { + const { touchable } = this.data; + if (!touchable) + return; + const { clientX } = event.touches[0]; + this.getRect('.van-rate__icon', true).then((list) => { + const target = list + .sort(item => item.right - item.left) + .find(item => clientX >= item.left && clientX <= item.right); + if (target != null) { + this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target })); + } + }); + } + } +}); diff --git a/components/rate/index.json b/components/rate/index.json new file mode 100644 index 0000000..0a336c0 --- /dev/null +++ b/components/rate/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/components/rate/index.wxml b/components/rate/index.wxml new file mode 100644 index 0000000..58eee5c --- /dev/null +++ b/components/rate/index.wxml @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/components/rate/index.wxss b/components/rate/index.wxss new file mode 100644 index 0000000..6fd3435 --- /dev/null +++ b/components/rate/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-rate{display:-webkit-inline-flex;display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{position:relative;padding:0 2px;padding:0 var(--rate-horizontal-padding,2px)}.van-rate__icon{display:block;height:1em;font-size:20px;font-size:var(--rate-icon-size,20px)}.van-rate__icon--half{position:absolute;top:0;width:.5em;overflow:hidden;left:2px;left:var(--rate-horizontal-padding,2px)} \ No newline at end of file diff --git a/components/refresh-view/index.js b/components/refresh-view/index.js new file mode 100644 index 0000000..c20345c --- /dev/null +++ b/components/refresh-view/index.js @@ -0,0 +1,91 @@ +// components/swiperefreshlayout/swiperefreshlayout.js +Component({ + options: { + multipleSlots: true + }, + properties: { + height: { + type: Number, + value: 800 + }, + threshold: { // 下拉刷新阈值,下拉距离超过该值触发刷新 + type: Number, + value: 30 + }, + color: { // 下拉刷新进度条颜色 + type: String, + value: 'black' + }, + backgroundColor: { // 下拉刷新圆圈背景颜色 + type: String, + value: 'white' + }, + loadMoreEnable: { // 是否开启上拉加载 + type: Boolean, + value: true + }, + refreshing: { + type: Boolean, + value: false, + observer(value) { + this.setRefresh(false) + } + } + }, + /** + * 组件的初始数据 + */ + data: { + progressBarHeight: '', // 下拉刷新圆圈高度 + rotate: '', + scrollTop: true, // 当前是否处于顶部 + triggered: false // 当前下拉刷新状态,true表示下拉刷新已经被触发,false表示下拉刷新未被触发 + }, + + lifetimes: { + attached: function() { + // 在组件实例进入页面节点树时执行 + this.setData({ progressBarHeight: this.rpx2px(80) }); + } + }, + /** + * 组件的方法列表 + */ + methods: { + _scroll: function(e) { + // console.log(e); + if (e.detail.scrollTop <= 50) { + // 滚动到顶部 + this.setData({ scrollTop: true }); + } else { + this.setData({ scrollTop: false }); + } + }, + /** + * 滚动到底部 + */ + _scrollToLower: function(e) { + if (this.properties.loadMoreEnable) { + this.triggerEvent('loadmore'); + } + }, + /** + * 设置刷新状态 + */ + setRefresh: function(refreshing) { + if (this.data.triggered != refreshing) { + if (refreshing) { + // 触发刷新 + this.triggerEvent('refresh'); + } + this.setData({ triggered: refreshing }); + } + }, + /** + * rpx转px + */ + rpx2px: function(rpx) { + return rpx / 750 * wx.getSystemInfoSync().windowWidth; + } + } +}) \ No newline at end of file diff --git a/components/refresh-view/index.json b/components/refresh-view/index.json new file mode 100644 index 0000000..e8cfaaf --- /dev/null +++ b/components/refresh-view/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/components/refresh-view/index.wxml b/components/refresh-view/index.wxml new file mode 100644 index 0000000..eaab87e --- /dev/null +++ b/components/refresh-view/index.wxml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/components/refresh-view/index.wxss b/components/refresh-view/index.wxss new file mode 100644 index 0000000..21617e0 --- /dev/null +++ b/components/refresh-view/index.wxss @@ -0,0 +1,78 @@ +/* components/swiperefreshlayout/swiperefreshlayout.wxss */ + +.scroll-container { + width: 100%; + height: 100%; +} + +.view-container { + display: flex; + flex-direction: column; +} + +.view-refresh-content { + width: 100%; + height: 100%; + position: absolute; + z-index: 8; +} + +.circle-progress-bar { + width: 80rpx; + height: 80rpx; + align-self: center; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + box-shadow: 0 0 18rpx #ccc; + /* position: fixed; */ + /* 这里margin-top没有取80rpx是为了防止露出阴影部分 */ + margin-top: -90rpx; + z-index: 12; +} + +@font-face { + font-family: "iconfont"; + src: url('//at.alicdn.com/t/font_1677220_3np58ejrjzs.eot?t=1585209535266'); /* IE9 */ + src: url('//at.alicdn.com/t/font_1677220_3np58ejrjzs.eot?t=1585209535266#iefix') format('embedded-opentype'), + /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAK8AAsAAAAABmgAAAJwAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcApwgRABNgIkAwgLBgAEIAWEbQcxG7cFyA4lQRHBTO0GAEwE4Ro5m+QJQLJiXUBZV1VXWUtoNEpSbBSTrL6f9nMP9VCOPrGEelL58u6L7nazhknCu3noy9AmCRoNfOLe8f/VeRfIfEC5rLlo0aQuoC4OpADHWhRZkUTeMHaBSzhOoNEoj6L9oYlpqFRY4wJxRlMEqMyFFIVl64XamqVF3FamPl1Jn8Ct8PvxRygqSWoyq+TQ6UEZer5n7BF5o9qwnLdszOcAW0XGMlCIY7WpA0oEY5RoTJWaBPsqDL5nqsq3iL0aBfvrrPxmMAxF9yR2JbeaTXBbXU0Cm6NuIybPZbPH8vkThcJJ2Oi5OO6bu9rsnb08B3X0XO54aeRkIx0/eXIt2Xxf4E3de/DwfINUHpwobf17ua+xD0zrPV9Gb6oLH/Jdfv78+Q6QZ8iHv6MHoPqXz/KWIgSvZv9+TzV0/K9vKuD19ebTMFD9K9DPA+r37Q7+kbhnQ9GlljkVVVzbmkyeu6xRIyrY1+lnrK7nhnKhXs8IT52RFFm9aaLQllGjyQpq1dtCoyXDq5t0YUpEacCiXYDQ7gNJq6fI2n0RhfaNGr3+Uas9StDoRLRs2WQ2tOp+hgJHmYhpokmOTR0rr44KJ1GJmwLLSkPmLLKYFiVBX6CYHUYb2RwzYgklxDkllDkWGQKnoWk6xGWOjhL3qZy7bX4/rXuTT3IsqLaHQQIOyQhRGqGROGzUb89Vlz4/CSniTALWUlfjnYWYGK13Isgn0IMYVtm96u7llZgERQjHUQTFOCzEEBiETCYH4dYP0iEJ56OOSLja+O1mtK/Kt77G+rod0MjSp7D7ZnVn1biQ0mwAAA==') format('woff2'), + url('//at.alicdn.com/t/font_1677220_3np58ejrjzs.woff?t=1585209535266') format('woff'), + url('//at.alicdn.com/t/font_1677220_3np58ejrjzs.ttf?t=1585209535266') format('truetype'), + /* chrome, + firefox, + opera, + Safari, + Android, + iOS 4.2+ */ url('//at.alicdn.com/t/font_1677220_3np58ejrjzs.svg?t=1585209535266#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-shuaxin:before { + content: "\e6c2"; +} + +.loading { + width: 36rpx; + height: 36rpx; + border-radius: 50%; + border-bottom: 5rpx solid transparent; + animation: loading 1.5s infinite; +} + +@keyframes loading { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/components/refresh-view/scroll.wxs b/components/refresh-view/scroll.wxs new file mode 100644 index 0000000..83e1237 --- /dev/null +++ b/components/refresh-view/scroll.wxs @@ -0,0 +1,124 @@ +/** + * 下拉刷新的控制 + */ +var startmark = 0; // 开始触摸屏幕的位置 +var newmark = 0; // 当前移动到的位置 +var maxDistance = 75; // 下拉最大距离(单位px) +var triggered = false; // 当前下拉刷新状态,true表示下拉刷新已经被触发,false表示下拉刷新未被触发 + +/** + * 手指触摸动作开始 + */ +var touchStart = function(e, instance) { + var scrollTop = e.instance.getDataset().scrolltop; + // 当前处于顶部并且没有处于刷新状态 + if (scrollTop && !triggered) { + startmark = e.touches[0].pageY; + } else { + return; + } +} + +/** + * 手指触摸后移动 + */ +var touchMove = function(e, instance) { + var scrollTop = e.instance.getDataset().scrolltop; + var circleProgressBarHeight = e.instance.getDataset().progressbarheight; + // 当前处于顶部并且没有处于刷新状态 + if (scrollTop && !triggered) { + newmark = e.touches[0].pageY; + if (newmark < startmark) { + // 向上滑动 + instance.selectComponent('.circle-progress-bar').setStyle({ 'transform': 'none' }) + instance.selectComponent('.icon-shuaxin').setStyle({ 'transform': 'none', 'opacity': 0 }) + } else if (newmark - startmark > maxDistance + circleProgressBarHeight) { + // 达到最大滑动距离 + instance.selectComponent('.circle-progress-bar').setStyle({ + 'transform': 'translateY(' + (maxDistance + circleProgressBarHeight) + 'px)' + }); + instance.selectComponent('.icon-shuaxin').setStyle({ + 'transform': 'rotate(270deg)', + 'opacity': 1 + }); + } else { + // 向下滑动,未到达最大滑动距离 + instance.selectComponent('.circle-progress-bar').setStyle({ + 'transform': 'translateY(' + (newmark - startmark) + 'px)' + }); + // 计算加载进度条的透明度,当滑动距离为最大滑动距离的一半时opacity为1 + var opacity = 0; + if (newmark - startmark <= (maxDistance + circleProgressBarHeight) / 2) { + opacity = 1 * (newmark - startmark) / (maxDistance + circleProgressBarHeight); + } else { + opacity = 1; + } + instance.selectComponent('.icon-shuaxin').setStyle({ + 'transform': 'rotate(' + 270 * (newmark - startmark) / (maxDistance + circleProgressBarHeight) + 'deg)', + 'opacity': opacity + }); + } + } else { + return + } +} + +/** + * 手指触摸动作结束 + */ +var touchEnd = function(e, instance) { + var scrollTop = e.instance.getDataset().scrolltop; + var threshold = e.instance.getDataset().threshold; + // 当前处于顶部并且没有处于刷新状态 + if (scrollTop && !triggered) { + if (newmark - startmark < (threshold + 40)) { + // 滑动距离未达到阈值(这里的40为加载圈高度),回到原位 + startmark = 0; + newmark = 0; + instance.selectComponent('.circle-progress-bar').setStyle({ + 'transform': 'none', + 'opacity': 0, + 'transition-duration': '0.6s' + }); + } else { + // 滑动距离达到阈值,触发刷新 + startmark = 0; + newmark = 0; + instance.selectComponent('.circle-progress-bar').setStyle({ + 'transform': 'none', + 'opacity': 0 + }); + instance.callMethod('setRefresh', true); + } + } else { + return; + } +} + +/** + * 手指触摸动作被打断,如来电提醒,弹窗 + */ +var touchCancel = function(e, instance) { + // 回到原位 + startmark = 0; + newmark = 0; + instance.selectComponent('.circle-progress-bar').setStyle({ + 'transform': 'none', + 'opacity': 0 + }); +} + +/** + * 刷新状态变化监听 + */ +var refreshStateChange = function(newValue, oldValue, ownerInstance, ins) { + triggered = newValue; +} + +module.exports = { + touchStart: touchStart, + touchMove: touchMove, + touchEnd: touchEnd, + touchCancel: touchCancel, + refreshStateChange: refreshStateChange +} \ No newline at end of file diff --git a/components/row/index.js b/components/row/index.js new file mode 100644 index 0000000..72d6006 --- /dev/null +++ b/components/row/index.js @@ -0,0 +1,40 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'col', + type: 'descendant', + current: 'row', + linked(target) { + if (this.data.gutter) { + target.setGutter(this.data.gutter); + } + } + }, + props: { + gutter: { + type: Number, + observer: 'setGutter' + } + }, + data: { + viewStyle: '', + }, + mounted() { + if (this.data.gutter) { + this.setGutter(); + } + }, + methods: { + setGutter() { + const { gutter } = this.data; + const margin = `-${Number(gutter) / 2}px`; + const viewStyle = gutter + ? `margin-right: ${margin}; margin-left: ${margin};` + : ''; + this.setData({ viewStyle }); + this.getRelationNodes('../col/index').forEach(col => { + col.setGutter(this.data.gutter); + }); + } + } +}); diff --git a/components/row/index.json b/components/row/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/row/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/row/index.wxml b/components/row/index.wxml new file mode 100644 index 0000000..ab8fcf5 --- /dev/null +++ b/components/row/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/components/row/index.wxss b/components/row/index.wxss new file mode 100644 index 0000000..32a098b --- /dev/null +++ b/components/row/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-row:after{display:table;clear:both;content:""} \ No newline at end of file diff --git a/components/search/index.js b/components/search/index.js new file mode 100644 index 0000000..931dd6c --- /dev/null +++ b/components/search/index.js @@ -0,0 +1,73 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + field: true, + classes: ['field-class', 'input-class', 'cancel-class'], + props: { + label: String, + focus: Boolean, + error: Boolean, + disabled: Boolean, + readonly: Boolean, + inputAlign: String, + showAction: Boolean, + useActionSlot: Boolean, + useLeftIconSlot: Boolean, + useRightIconSlot: Boolean, + leftIcon: { + type: String, + value: 'search' + }, + rightIcon: String, + placeholder: String, + placeholderStyle: String, + actionText: { + type: String, + value: '取消' + }, + background: { + type: String, + value: '#ffffff' + }, + maxlength: { + type: Number, + value: -1 + }, + shape: { + type: String, + value: 'square' + }, + clearable: { + type: Boolean, + value: true + } + }, + methods: { + onChange(event) { + this.setData({ value: event.detail }); + this.$emit('change', event.detail); + }, + onCancel() { + /** + * 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效 + * https://github.com/youzan/@vant/weapp/issues/1768 + */ + setTimeout(() => { + this.setData({ value: '' }); + this.$emit('cancel'); + this.$emit('change', ''); + }, 200); + }, + onSearch() { + this.$emit('search', this.data.value); + }, + onFocus() { + this.$emit('focus'); + }, + onBlur() { + this.$emit('blur'); + }, + onClear() { + this.$emit('clear'); + }, + } +}); diff --git a/components/search/index.json b/components/search/index.json new file mode 100644 index 0000000..b4cfe91 --- /dev/null +++ b/components/search/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-field": "../field/index" + } +} diff --git a/components/search/index.wxml b/components/search/index.wxml new file mode 100644 index 0000000..bc04664 --- /dev/null +++ b/components/search/index.wxml @@ -0,0 +1,26 @@ + + + + + {{ label }} + + + + + + + + + + + {{ actionText }} + + \ No newline at end of file diff --git a/components/search/index.wxss b/components/search/index.wxss new file mode 100644 index 0000000..d7d5f23 --- /dev/null +++ b/components/search/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-search{-webkit-align-items:center;align-items:center;box-sizing:border-box;padding:10px 12px;padding:var(--search-padding,8px 12px)}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{-webkit-flex:1;flex:1;padding-left:8px;padding-left:var(--padding-xs,8px);border-radius:2px;border-radius:var(--border-radius-sm,2px);background-color:#f7f8fa;background-color:var(--search-background-color,#f7f8fa)}.van-search__content--round{border-radius:17px;border-radius:calc(var(--search-input-height, 34px)/2)}.van-search__label{padding:0 5px;padding:var(--search-label-padding,0 5px);font-size:14px;font-size:var(--search-label-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-label-color,#323233)}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#969799;color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{padding:0 8px;padding:var(--search-action-padding,0 8px);font-size:14px;font-size:var(--search-action-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-action-text-color,#323233)}.van-search__action--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)} \ No newline at end of file diff --git a/components/segment/index.js b/components/segment/index.js new file mode 100644 index 0000000..a92f3e8 --- /dev/null +++ b/components/segment/index.js @@ -0,0 +1,92 @@ +import baseComponent from '../helpers/baseComponent' +import classNames from '../helpers/classNames' + +baseComponent({ + properties: { + prefixCls: { + type: String, + value: 'wux-segment', + }, + theme: { + type: String, + value: 'balanced', + }, + defaultCurrent: { + type: Number, + value: 0, + }, + current: { + type: Number, + value: 0, + observer(newVal) { + if (this.data.controlled) { + this.setData({ + activeKey: newVal, + }) + } + }, + }, + values: { + type: Array, + value: [], + }, + disabled: { + type: Boolean, + value: false, + }, + controlled: { + type: Boolean, + value: false, + }, + }, + data: { + activeKey: 0, + }, + computed: { + classes: ['prefixCls, theme, disabled', function(prefixCls, theme, disabled) { + const wrap = classNames(prefixCls, { + [`${prefixCls}--${theme}`]: theme, + [`${prefixCls}--disabled`]: disabled, + }) + const item = `${prefixCls}__item` + + return { + wrap, + item, + } + }], + }, + methods: { + onTap(e) { + if (this.data.disabled) return + this.setActiveKey(e.currentTarget.dataset.index) + }, + emitEvent(key) { + this.triggerEvent('change', { + key, + values: this.data.values, + }) + }, + setActiveKey(activeKey) { + if (this.data.activeKey !== activeKey) { + if (!this.data.controlled) { + this.setData({ + activeKey, + }) + } + } + + this.emitEvent(activeKey) + }, + }, + attached() { + const { defaultCurrent, current, controlled } = this.data + const activeKey = controlled ? current : defaultCurrent + + if (this.data.activeKey !== activeKey) { + this.setData({ + activeKey, + }) + } + }, +}) diff --git a/components/segment/index.json b/components/segment/index.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/segment/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/segment/index.wxml b/components/segment/index.wxml new file mode 100644 index 0000000..b2513e3 --- /dev/null +++ b/components/segment/index.wxml @@ -0,0 +1,5 @@ + + + {{ item }} + + \ No newline at end of file diff --git a/components/segment/index.wxss b/components/segment/index.wxss new file mode 100644 index 0000000..c9d2338 --- /dev/null +++ b/components/segment/index.wxss @@ -0,0 +1,113 @@ +.wux-segment { + display: -ms-flexbox; + display: flex; + border-radius: 6rpx; + overflow: hidden; + min-height: 60rpx; + opacity: 1; +} +.wux-segment--disabled { + opacity: .3 +} +.wux-segment__item { + display: -ms-flexbox; + display: flex; + -ms-flex: 1; + flex: 1; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-align: center; + align-items: center; + color: #33cd5f; + font-size: 28rpx; + line-height: 1; + transition: background .3s; + position: relative; + border: 2rpx solid #33cd5f; + width: 100%; + box-sizing: border-box; + border-left-width: 0 +} +.wux-segment__item:first-child { + border-left-width: 2rpx; + border-radius: 6rpx 0 0 6rpx +} +.wux-segment__item:last-child { + border-radius: 0 6rpx 6rpx 0 +} +.wux-segment__item--current { + background: #33cd5f; + color: #fff +} +.wux-segment--light .wux-segment__item { + color: #ddd; + border-color: #ddd +} +.wux-segment--light .wux-segment__item--current { + background: #ddd; + color: #fff +} +.wux-segment--stable .wux-segment__item { + color: #ddd; + border-color: #ddd +} +.wux-segment--stable .wux-segment__item--current { + background: #ddd; + color: #fff +} +.wux-segment--positive .wux-segment__item { + color: #008aff; + border-color: #008aff +} +.wux-segment--positive .wux-segment__item--current { + background: #008aff; + color: #fff +} +.wux-segment--calm .wux-segment__item { + color: #11c1f3; + border-color: #11c1f3 +} +.wux-segment--calm .wux-segment__item--current { + background: #11c1f3; + color: #fff +} +.wux-segment--assertive .wux-segment__item { + color: #ef473a; + border-color: #ef473a +} +.wux-segment--assertive .wux-segment__item--current { + background: #ef473a; + color: #fff +} +.wux-segment--balanced .wux-segment__item { + color: #33cd5f; + border-color: #33cd5f +} +.wux-segment--balanced .wux-segment__item--current { + background: #33cd5f; + color: #fff +} +.wux-segment--energized .wux-segment__item { + color: #ffc900; + border-color: #ffc900 +} +.wux-segment--energized .wux-segment__item--current { + background: #ffc900; + color: #fff +} +.wux-segment--royal .wux-segment__item { + color: #886aea; + border-color: #886aea +} +.wux-segment--royal .wux-segment__item--current { + background: #886aea; + color: #fff +} +.wux-segment--dark .wux-segment__item { + color: #444; + border-color: #444 +} +.wux-segment--dark .wux-segment__item--current { + background: #444; + color: #fff +} \ No newline at end of file diff --git a/components/sidebar-item/index.js b/components/sidebar-item/index.js new file mode 100644 index 0000000..a3e02ca --- /dev/null +++ b/components/sidebar-item/index.js @@ -0,0 +1,34 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + classes: [ + 'active-class', + 'disabled-class', + ], + relation: { + type: 'ancestor', + name: 'sidebar', + current: 'sidebar-item', + }, + props: { + dot: Boolean, + info: null, + title: String, + disabled: Boolean + }, + methods: { + onClick() { + const { parent } = this; + if (!parent || this.data.disabled) { + return; + } + const index = parent.children.indexOf(this); + parent.setActive(index).then(() => { + this.$emit('click', index); + parent.$emit('change', index); + }); + }, + setActive(selected) { + return this.setData({ selected }); + } + } +}); diff --git a/components/sidebar-item/index.json b/components/sidebar-item/index.json new file mode 100644 index 0000000..bf0ebe0 --- /dev/null +++ b/components/sidebar-item/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-info": "../info/index" + } +} diff --git a/components/sidebar-item/index.wxml b/components/sidebar-item/index.wxml new file mode 100644 index 0000000..fb84180 --- /dev/null +++ b/components/sidebar-item/index.wxml @@ -0,0 +1,11 @@ + + + + + + {{ title }} + + + \ No newline at end of file diff --git a/components/sidebar-item/index.wxss b/components/sidebar-item/index.wxss new file mode 100644 index 0000000..8c4797e --- /dev/null +++ b/components/sidebar-item/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-sidebar-item{display:block;box-sizing:border-box;overflow:hidden;word-wrap:break-word;border-left:3px solid transparent;-webkit-user-select:none;user-select:none;padding:24rpx 12px 24rpx 8px;padding:var(--sidebar-padding,24rpx 12px 24rpx 8px);font-size:14px;font-size:var(--sidebar-font-size,14px);line-height:24px;line-height:var(--sidebar-line-height,24px);color:#323233;color:var(--sidebar-text-color,#323233);background-color:#f7f8fa;background-color:var(--sidebar-background-color,#f7f8fa)}.van-sidebar-item__text{position:relative;display:inline-block}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:#f2f3f5;background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{color:#323233;color:var(--sidebar-selected-text-color,#323233);font-weight:500;font-weight:var(--sidebar-selected-font-weight,500);border-color:#008AFF;border-color:var(--sidebar-selected-border-color,#008AFF)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:#fff;background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:#c8c9cc;color:var(--sidebar-disabled-text-color,#c8c9cc)} \ No newline at end of file diff --git a/components/sidebar/index.js b/components/sidebar/index.js new file mode 100644 index 0000000..008fe99 --- /dev/null +++ b/components/sidebar/index.js @@ -0,0 +1,41 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'sidebar-item', + type: 'descendant', + current: 'sidebar', + linked() { + this.setActive(this.data.activeKey); + }, + unlinked() { + this.setActive(this.data.activeKey); + } + }, + props: { + activeKey: { + type: Number, + value: 0, + observer: 'setActive' + } + }, + beforeCreate() { + this.currentActive = -1; + }, + methods: { + setActive(activeKey) { + const { children, currentActive } = this; + if (!children.length) { + return Promise.resolve(); + } + this.currentActive = activeKey; + const stack = []; + if (currentActive !== activeKey && children[currentActive]) { + stack.push(children[currentActive].setActive(false)); + } + if (children[activeKey]) { + stack.push(children[activeKey].setActive(true)); + } + return Promise.all(stack); + } + } +}); diff --git a/components/sidebar/index.json b/components/sidebar/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/sidebar/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/sidebar/index.wxml b/components/sidebar/index.wxml new file mode 100644 index 0000000..96b11c7 --- /dev/null +++ b/components/sidebar/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/components/sidebar/index.wxss b/components/sidebar/index.wxss new file mode 100644 index 0000000..f59766e --- /dev/null +++ b/components/sidebar/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-sidebar{width:100%} \ No newline at end of file diff --git a/components/skeleton-avatar/index.js b/components/skeleton-avatar/index.js new file mode 100644 index 0000000..f541b28 --- /dev/null +++ b/components/skeleton-avatar/index.js @@ -0,0 +1,48 @@ +import classNames from '../common/classNames' + +Component({ + properties: { + prefixCls: { + type: String, + value: 'wux-skeleton-avatar', + }, + size: { + type: String, + value: 'default', + }, + shape: { + type: String, + value: 'circle', + }, + }, + data: { + active: true, + classes: null + }, + lifetimes: { + attached: function () { + this.setData({ + classes: this.initwrap(this.data.prefixCls, this.data.active, this.data.size, this.data.shape) + }) + } + }, + methods: { + initwrap: function (prefixCls, active, size, shape) { + const wrap = classNames(prefixCls, { + [`${prefixCls}--active`]: active, + [`${prefixCls}--${size}`]: size, + [`${prefixCls}--${shape}`]: shape, + }) + return { + wrap, + } + }, + updated(active) { + if (this.data.active !== active) { + this.setData({ + active + }) + } + }, + }, +}) \ No newline at end of file diff --git a/components/skeleton-avatar/index.json b/components/skeleton-avatar/index.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/skeleton-avatar/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/skeleton-avatar/index.wxml b/components/skeleton-avatar/index.wxml new file mode 100644 index 0000000..eae9f02 --- /dev/null +++ b/components/skeleton-avatar/index.wxml @@ -0,0 +1 @@ + diff --git a/components/skeleton-avatar/index.wxss b/components/skeleton-avatar/index.wxss new file mode 100644 index 0000000..0875329 --- /dev/null +++ b/components/skeleton-avatar/index.wxss @@ -0,0 +1,69 @@ +.wux-skeleton-avatar { + display: inline-block; + vertical-align: top; + background: #f2f2f2; + width: 80rpx; + height: 80rpx; + line-height: 80rpx +} +.wux-skeleton-avatar--tag { + width: 32rpx; + height: 32rpx; + line-height: 64rpx +} +.wux-skeleton-avatar--small { + width: 64rpx; + height: 64rpx; + line-height: 64rpx +} +.wux-skeleton-avatar--large { + width: 96rpx; + height: 96rpx; + line-height: 96rpx +} +.wux-skeleton-avatar--page { + width: 220rpx; + height: 220rpx; + line-height: 220rpx +} + +.wux-skeleton-avatar--title { + width: 100%; + height: 120rpx; + line-height: 120rpx +} + +.wux-skeleton-avatar--tab { + width: 100%; + height: 60rpx; + line-height: 60rpx +} + +.wux-skeleton-avatar--full { + width: 100%; + height: 240rpx; + line-height: 240rpx +} + +.wux-skeleton-avatar--circle { + border-radius: 50% +} +.wux-skeleton-avatar--rounded { + border-radius: 8rpx +} +.wux-skeleton-avatar--square { + border-radius: 0 +} +.wux-skeleton-avatar--active { + background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%); + animation: loading 1.4s ease infinite; + background-size: 400% 100% +} +@keyframes loading { + 0% { + background-position: 100% 50% + } + 100% { + background-position: 0 50% + } +} \ No newline at end of file diff --git a/components/skeleton-paragraph/index.js b/components/skeleton-paragraph/index.js new file mode 100644 index 0000000..0bc8d0c --- /dev/null +++ b/components/skeleton-paragraph/index.js @@ -0,0 +1,63 @@ +import classNames from '../common/classNames' + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + prefixCls: { + type: String, + value: 'wux-skeleton-paragraph', + }, + rows: { + type: Number, + value: 3, + }, + rounded: { + type: Boolean, + value: true, + }, + widths: { + type: Array, + value: [], + } + }, + data: { + active: true, + rowList: [], + }, + lifetimes: { + attached: function () { + this.updateRows() + this.setData({ + classes: this.initwrap(this.data.prefixCls, this.data.active, this.data.rounded) + }) + } + }, + methods: { + initwrap: function (prefixCls, active, rounded) { + const wrap = classNames(prefixCls, { + [`${prefixCls}--active`]: active, + [`${prefixCls}--rounded`]: rounded, + }) + const row = `${prefixCls}__row` + return { + wrap, + row, + } + }, + updated(active) { + if (this.data.active !== active) { + this.setData({ + active, + }) + } + }, + updateRows(rows = this.data.rows) { + this.setData({ + rowList: [...Array(rows)].map((_, index) => index), + }) + }, + } +}) \ No newline at end of file diff --git a/components/skeleton-paragraph/index.json b/components/skeleton-paragraph/index.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/skeleton-paragraph/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/skeleton-paragraph/index.wxml b/components/skeleton-paragraph/index.wxml new file mode 100644 index 0000000..2ea00af --- /dev/null +++ b/components/skeleton-paragraph/index.wxml @@ -0,0 +1,5 @@ + + + + + diff --git a/components/skeleton-paragraph/index.wxss b/components/skeleton-paragraph/index.wxss new file mode 100644 index 0000000..5702cd7 --- /dev/null +++ b/components/skeleton-paragraph/index.wxss @@ -0,0 +1,41 @@ +.wux-skeleton-paragraph { + position: relative; + overflow: hidden +} +.wux-skeleton-paragraph__row { + height: 32rpx; + background: #f2f2f2; + width: 100%; + margin-top: 32rpx +} +.wux-skeleton-paragraph__row:first-child { + margin-top: 0 +} +.wux-skeleton-paragraph__row:nth-child(4n+1) { + width: 80% +} +.wux-skeleton-paragraph__row:nth-child(4n+2) { + width: 100% +} +.wux-skeleton-paragraph__row:nth-child(4n+3) { + width: 70% +} +.wux-skeleton-paragraph__row:nth-child(4n+4) { + width: 85% +} +.wux-skeleton-paragraph--rounded .wux-skeleton-paragraph__row { + border-radius: 8rpx +} +.wux-skeleton-paragraph--active .wux-skeleton-paragraph__row { + background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%); + animation: loading 1.4s ease infinite; + background-size: 400% 100% +} +@keyframes loading { + 0% { + background-position: 100% 50% + } + 100% { + background-position: 0 50% + } +} \ No newline at end of file diff --git a/components/skeleton/index.js b/components/skeleton/index.js new file mode 100644 index 0000000..17dfd1e --- /dev/null +++ b/components/skeleton/index.js @@ -0,0 +1,50 @@ +import classNames from '../common/classNames' + +Component({ + properties: { + prefixCls: { + type: String, + value: 'wux-skeleton', + }, + active: { + type: Boolean, + value: true, + observer: 'updated', + }, + }, + data: { + classes: null + }, + lifetimes: { + // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 + attached: function () { + this.setData({ + classes: this.initwrap(this.data.prefixCls, this.data.active) + }) + } + }, + methods: { + initwrap: function(prefixCls, active){ + const wrap = classNames(prefixCls, { + [`${prefixCls}--active`]: active, + }) + return { + wrap, + } + }, + updated(active = this.data.active) { + const avatar = this.getRelationNodes('../skeleton-avatar/index') + const paragraph = this.getRelationNodes('../skeleton-paragraph/index') + if (avatar && avatar.length > 0) { + avatar.forEach((element) => { + element.updated(active) + }) + } + if (paragraph && paragraph.length > 0) { + paragraph.forEach((element) => { + element.updated(active) + }) + } + }, + }, +}) diff --git a/components/skeleton/index.json b/components/skeleton/index.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/skeleton/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/skeleton/index.wxml b/components/skeleton/index.wxml new file mode 100644 index 0000000..2cf2c40 --- /dev/null +++ b/components/skeleton/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/components/skeleton/index.wxss b/components/skeleton/index.wxss new file mode 100644 index 0000000..1498f39 --- /dev/null +++ b/components/skeleton/index.wxss @@ -0,0 +1,4 @@ +.wux-skeleton { + position: relative; + width: 100% +} \ No newline at end of file diff --git a/components/step/index.js b/components/step/index.js new file mode 100644 index 0000000..323a281 --- /dev/null +++ b/components/step/index.js @@ -0,0 +1,43 @@ +Component({ + /** + * 组件的属性列表 + */ + externalClasses: [ + 'l-class', + 'l-step-class', + 'l-title-class', + 'l-describe-class', + 'l-line-class' + ], + options: { + multipleSlots: true // 在组件定义时的选项中启用多slot支持 + }, + relations: { + '../steps/index': { + type: 'parent' + }, + }, + properties: { + icon: String, + title: String, + describe: String, + iconSize: { + type: Number, + value: 24 + }, + iconColor: String, + custom: Boolean + }, + + /** + * 组件的方法列表 + */ + methods: { + // 与父组件通信并绑定相关配置数据 + updateDataChange(options) { + this.setData({ + ...options + }) + } + } +}) \ No newline at end of file diff --git a/components/step/index.json b/components/step/index.json new file mode 100644 index 0000000..d538b90 --- /dev/null +++ b/components/step/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon":"../icon/index" + } +} \ No newline at end of file diff --git a/components/step/index.wxml b/components/step/index.wxml new file mode 100644 index 0000000..610be19 --- /dev/null +++ b/components/step/index.wxml @@ -0,0 +1,69 @@ + + + + + + + + + + {{index+1}} + + + + + + {{title}} + + + + {{describe}} + + + + + + + + + var setStatus = function (activeIndex, index, status) { + if (activeIndex === index) { + return status || 'process' + } else if (activeIndex > index) { + return 'finish' + } else { + return 'wait' + } + } + + var statusStyle = function (activeIndex, index, color, status) { + if (activeIndex === index) { + return status === 'error' ? '' : ('background-color:' + color) + } else if (activeIndex > index) { + return ('border-color:' + color + ';color:' + color) + } else { + return '' + } + } + + var dotStyle = function (activeIndex, index, color) { + if (activeIndex >= index) { + return ('background-color:' + color) + } else { + return '' + } + } + + module.exports = { + setStatus: setStatus, + statusStyle: statusStyle, + dotStyle: dotStyle + } + \ No newline at end of file diff --git a/components/step/index.wxss b/components/step/index.wxss new file mode 100644 index 0000000..2fc14c6 --- /dev/null +++ b/components/step/index.wxss @@ -0,0 +1 @@ +.step{display:flex;position:relative}.step-custom{z-index:2}.step-row{flex-direction:column;align-items:center}.step-column{flex-direction:row;padding-left:30rpx;box-sizing:border-box}.step-container{display:flex;justify-content:center;z-index:2;align-items:center}.step-container-row{width:70rpx;height:40rpx}.step-container-column{height:60rpx;width:40rpx}.step-icon{width:40rpx;height:40rpx;display:flex;align-items:center;justify-content:center;font-size:22rpx;transition:.5s;box-sizing:border-box}.step-process{color:#fff;background-color:#008AFF;border-radius:50%}.step-error{background-color:#fff;border:1px solid #f4516c;color:#f4516c;border-radius:50%}.step-finish{background-color:#fff;color:#008AFF;border:1px solid #008AFF;border-radius:50%}.step-wait{background-color:#fff;color:#c4c9d2;border:1px solid #c4c9d2;border-radius:50%}.step-dot{width:24rpx;height:24rpx;border-radius:50%;transition:.5s}.step-dot-process{background-color:#008AFF}.step-dot-wait{background-color:#c4c9d2}.step-dot-error{background-color:#f4516c}.step-dot-finish{background-color:#008AFF}.step-line{background:#c4c9d2;background: linear-gradient(to bottom, #c4c9d2, #c4c9d2 7.5px, transparent 7.5px, transparent);transition:.5s;position:absolute;z-index:0}.step-line-row{height:2rpx;width:100%;left:50%;top:18rpx}.step-line-column{width:2rpx;height:100%;top:20rpx;left:48rpx}.step-line-wait{background-color:#e8e8e8}.step-line-finish{background-color:#008AFF}.step-content{display:flex;flex-direction:column}.step-content-row{align-items:center;width:100%}.step-content-column{margin-left:15rpx}.step-title{color:#595959;font-size:26rpx;line-height:40rpx;margin:10rpx 0}.step-title-process{color:#333;font-size:28rpx;line-height:40rpx;margin:10rpx 0}.step-describe{color:#999999;font-size:22rpx}@font-face{font-family:iconfont;src:url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAK8AAsAAAAABpQAAAJvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgp8gQsBNgIkAwwLCAAEIAWEbQc2G9EFyK4wbuGJaCgrSmkBCSe/ZeUtviBzEXztx/bd3f+oNEiuzaerJhKN6WQSJFqlZELxTOZqTS9l0hsflgVC/bD3z/dzv8lMXAksyeryeByfVkhgV93EvwdIwC+b/hetH5jPyAA+z+X0JtCBXONbltMcw496AcYBBbYnRoEEXEQBcAqyOwK15PsEmg2KiewMTy6yCoWzLBD3lqGwilJKUaRqo1C37C3iRaUxPaUnPMffj18LUUFSZc7a3bshnfV++DD/2GVISBPo4QoZU5hCXLeWThULiSvWbCrpb64VIS2VhYlVpqU+6B8vETWnsxWM0XLiI19G8OGABDKoy5VBzDRje98gRHertt+2fLx2cdC6ZJwcnK226Ifh0uzy4vzK8sLSytxprqHAHexGbz8/6za6C3ePjwW29viP3ailnm7Zz+SntAd5IV0IBHuvvy3Xd/41thTw/osdBRahcefh4Gepwb5iah13LrrKV9mRrBsIJKhCjvrnxLq9Trf0wb2ERn0TIg0GcmSNhsjCTqHSYgm1RutoNmnkcIseUrEoTZiwRRA63SBp94as0zNZ2BdU+v2h1hnFaHYczWe2GAmrakCiQqiDmgdLEz73vFSVdM+jkXUVWdTG/DLK0MpCOpGqVkfQR7nEhjBnZIg4cCk8GCaPoesKCKSwUaOESRS0J5O87UUJTXisyjYJKQjSAVUesGgEHw+Hk6ra5+chQ5ZLIXsEDfllSApZ44O0hBRAjph8SPAoz4RyDBmEcICTBA8YJrOQyyWAoH2WDWlIgjmhEGiXdAdx1JTY3uL93xFo5kzMkSJHUT+g+5BNxVpWMAYAAA==') format('woff2')}.iconfont{font-family:iconfont!important;font-size:24rpx;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-finish:before{content:"\e600"}.icon-error:before{content:"\e6cf"} \ No newline at end of file diff --git a/components/stepper/index.js b/components/stepper/index.js new file mode 100644 index 0000000..fa41915 --- /dev/null +++ b/components/stepper/index.js @@ -0,0 +1,184 @@ +import { VantComponent } from '../common/component'; +import { isDef } from '../common/utils'; +const LONG_PRESS_START_TIME = 600; +const LONG_PRESS_INTERVAL = 200; +// add num and avoid float number +function add(num1, num2) { + const cardinal = Math.pow(10, 10); + return Math.round((num1 + num2) * cardinal) / cardinal; +} +function equal(value1, value2) { + return String(value1) === String(value2); +} +VantComponent({ + field: true, + classes: ['input-class', 'plus-class', 'minus-class'], + props: { + value: { + type: null, + observer(value) { + if (!equal(value, this.data.currentValue)) { + this.setData({ currentValue: this.format(value) }); + } + } + }, + integer: { + type: Boolean, + observer: 'check' + }, + disabled: Boolean, + inputWidth: null, + buttonSize: null, + asyncChange: Boolean, + disableInput: Boolean, + decimalLength: { + type: Number, + value: null, + observer: 'check' + }, + min: { + type: null, + value: 1, + observer: 'check' + }, + max: { + type: null, + value: Number.MAX_SAFE_INTEGER, + observer: 'check' + }, + step: { + type: null, + value: 1 + }, + showPlus: { + type: Boolean, + value: true + }, + showMinus: { + type: Boolean, + value: true + }, + disablePlus: Boolean, + disableMinus: Boolean, + longPress: { + type: Boolean, + value: true + } + }, + data: { + currentValue: '' + }, + created() { + this.setData({ + currentValue: this.format(this.data.value) + }); + }, + methods: { + check() { + const val = this.format(this.data.currentValue); + if (!equal(val, this.data.currentValue)) { + this.setData({ currentValue: val }); + } + }, + isDisabled(type) { + if (type === 'plus') { + return (this.data.disabled || + this.data.disablePlus || + this.data.currentValue >= this.data.max); + } + return (this.data.disabled || + this.data.disableMinus || + this.data.currentValue <= this.data.min); + }, + onFocus(event) { + this.$emit('focus', event.detail); + }, + onBlur(event) { + const value = this.format(event.detail.value); + this.emitChange(value); + this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value })); + }, + // filter illegal characters + filter(value) { + value = String(value).replace(/[^0-9.-]/g, ''); + if (this.data.integer && value.indexOf('.') !== -1) { + value = value.split('.')[0]; + } + return value; + }, + // limit value range + format(value) { + value = this.filter(value); + // format range + value = value === '' ? 0 : +value; + value = Math.max(Math.min(this.data.max, value), this.data.min); + // format decimal + if (isDef(this.data.decimalLength)) { + value = value.toFixed(this.data.decimalLength); + } + return value; + }, + onInput(event) { + const { value = '' } = event.detail || {}; + // allow input to be empty + if (value === '') { + return; + } + let formatted = this.filter(value); + // limit max decimal length + if (isDef(this.data.decimalLength) && formatted.indexOf('.') !== -1) { + const pair = formatted.split('.'); + formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`; + } + this.emitChange(formatted); + }, + emitChange(value) { + if (!this.data.asyncChange) { + this.setData({ currentValue: value }); + } + this.$emit('change', value); + }, + onChange() { + const { type } = this; + if (this.isDisabled(type)) { + this.$emit('overlimit', type); + return; + } + const diff = type === 'minus' ? -this.data.step : +this.data.step; + const value = this.format(add(+this.data.currentValue, diff)); + this.emitChange(value); + this.$emit(type); + }, + longPressStep() { + this.longPressTimer = setTimeout(() => { + this.onChange(); + this.longPressStep(); + }, LONG_PRESS_INTERVAL); + }, + onTap(event) { + const { type } = event.currentTarget.dataset; + this.type = type; + this.onChange(); + }, + onTouchStart(event) { + if (!this.data.longPress) { + return; + } + clearTimeout(this.longPressTimer); + const { type } = event.currentTarget.dataset; + this.type = type; + this.isLongPress = false; + this.longPressTimer = setTimeout(() => { + this.isLongPress = true; + this.onChange(); + this.longPressStep(); + }, LONG_PRESS_START_TIME); + }, + onTouchEnd() { + if (!this.data.longPress) { + return; + } + clearTimeout(this.longPressTimer); + } + } +}); diff --git a/components/stepper/index.json b/components/stepper/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/stepper/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/stepper/index.wxml b/components/stepper/index.wxml new file mode 100644 index 0000000..9570420 --- /dev/null +++ b/components/stepper/index.wxml @@ -0,0 +1,37 @@ + + + + + + + diff --git a/components/stepper/index.wxss b/components/stepper/index.wxss new file mode 100644 index 0000000..5da5b79 --- /dev/null +++ b/components/stepper/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;box-sizing:border-box;margin:1px;vertical-align:middle;border:0;background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);color:#323233;color:var(--stepper-button-icon-color,#323233);width:28px;width:var(--stepper-input-height,28px);height:28px;height:var(--stepper-input-height,28px);padding:4px;padding:var(--padding-base,4px)}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:currentColor;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8;background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:#c8c9cc;color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa;background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:4px 0 0 4px;border-radius:var(--stepper-border-radius,4px) 0 0 var(--stepper-border-radius,4px)}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0;border-radius:0 var(--stepper-border-radius,4px) var(--stepper-border-radius,4px) 0}.van-stepper__input{display:inline-block;box-sizing:border-box;min-height:0;margin:1px;padding:1px;text-align:center;vertical-align:middle;border:0;border-width:1px 0;border-radius:0;-webkit-appearance:none;font-size:14px;font-size:var(--stepper-input-font-size,14px);color:#323233;color:var(--stepper-input-text-color,#323233);background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);width:32px;width:var(--stepper-input-width,32px);height:28px;height:var(--stepper-input-height,28px)}.van-stepper__input--disabled{color:#c8c9cc;color:var(--stepper-input-disabled-text-color,#c8c9cc);background-color:#f2f3f5;background-color:var(--stepper-input-disabled-background-color,#f2f3f5)} \ No newline at end of file diff --git a/components/steps/index.js b/components/steps/index.js new file mode 100644 index 0000000..47772cd --- /dev/null +++ b/components/steps/index.js @@ -0,0 +1,74 @@ +Component({ + externalClasses: [ + 'l-class' + ], + options: { + multipleSlots: true // 在组件定义时的选项中启用多slot支持 + }, + relations: { + '../step/index': { + type: 'child', + linked() { + this.initSteps(); + }, + unlinked() { + this.initSteps(); + } + }, + }, + + properties: { + direction: { + type: String, + value: 'row', + options: ['row', 'column'] + }, + activeIndex: { + type: Number, + value: 0 + }, + color: String, + stepMinHeight: { + type: String, + value: '120' + }, + status: { + type: String, + value: 'process', + options: ['process', 'error'] + }, + dot: Boolean + }, + + observers: { + 'activeIndex': function () { + this.initSteps() + } + }, + + /** + * 组件的初始数据 + */ + data: { + + }, + + /** + * 组件的方法列表 + */ + methods: { + initSteps() { + let steps = this.getRelationNodes('../step/index') + this.data.length = steps.length + if (this.data.length > 0) { + steps.forEach((step, index) => { + step.updateDataChange({ + index, + ...this.data, + stepsWidth: 375 + }); + }); + } + } + } +}); \ No newline at end of file diff --git a/components/steps/index.json b/components/steps/index.json new file mode 100644 index 0000000..9109978 --- /dev/null +++ b/components/steps/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "l-step":"../step/index" + } +} \ No newline at end of file diff --git a/components/steps/index.wxml b/components/steps/index.wxml new file mode 100644 index 0000000..a5bc7e6 --- /dev/null +++ b/components/steps/index.wxml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/components/steps/index.wxss b/components/steps/index.wxss new file mode 100644 index 0000000..b4df18c --- /dev/null +++ b/components/steps/index.wxss @@ -0,0 +1 @@ +.steps-container{display:flex;width:100%}.steps-container-row{flex-direction:row}.steps-container-column{flex-direction:column} \ No newline at end of file diff --git a/components/sticky/index.js b/components/sticky/index.js new file mode 100644 index 0000000..11d0c07 --- /dev/null +++ b/components/sticky/index.js @@ -0,0 +1,119 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +var component_1 = require('../common/component'); +var page_scroll_1 = require('../mixins/page-scroll'); +var ROOT_ELEMENT = '.van-sticky'; +component_1.VantComponent({ + props: { + zIndex: { + type: Number, + value: 99, + }, + offsetTop: { + type: Number, + value: 0, + observer: 'onScroll', + }, + disabled: { + type: Boolean, + observer: 'onScroll', + }, + container: { + type: null, + observer: 'onScroll', + }, + scrollTop: { + type: null, + observer: function (val) { + this.onScroll({ scrollTop: val }); + }, + }, + }, + mixins: [ + page_scroll_1.pageScrollMixin(function (event) { + if (this.data.scrollTop != null) { + return; + } + this.onScroll(event); + }), + ], + data: { + height: 0, + fixed: false, + transform: 0, + }, + mounted: function () { + this.onScroll(); + }, + methods: { + onScroll: function (_a) { + var _this = this; + var scrollTop = (_a === void 0 ? {} : _a).scrollTop; + var _b = this.data, + container = _b.container, + offsetTop = _b.offsetTop, + disabled = _b.disabled; + if (disabled) { + this.setDataAfterDiff({ + fixed: false, + transform: 0, + }); + return; + } + this.scrollTop = scrollTop || this.scrollTop; + if (typeof container === 'function') { + Promise.all([this.getRect(ROOT_ELEMENT), this.getContainerRect()]).then( + function (_a) { + var root = _a[0], + container = _a[1]; + if (offsetTop + root.height > container.height + container.top) { + _this.setDataAfterDiff({ + fixed: false, + transform: container.height - root.height, + }); + } else if (offsetTop >= root.top) { + _this.setDataAfterDiff({ + fixed: true, + height: root.height, + transform: 0, + }); + } else { + _this.setDataAfterDiff({ fixed: false, transform: 0 }); + } + } + ); + return; + } + this.getRect(ROOT_ELEMENT).then(function (root) { + if (offsetTop >= root.top) { + _this.setDataAfterDiff({ fixed: true, height: root.height }); + _this.transform = 0; + } else { + _this.setDataAfterDiff({ fixed: false }); + } + }); + }, + setDataAfterDiff: function (data) { + var _this = this; + wx.nextTick(function () { + var diff = Object.keys(data).reduce(function (prev, key) { + if (data[key] !== _this.data[key]) { + prev[key] = data[key]; + } + return prev; + }, {}); + _this.setData(diff); + _this.$emit('scroll', { + scrollTop: _this.scrollTop, + isFixed: data.fixed || _this.data.fixed, + }); + }); + }, + getContainerRect: function () { + var nodesRef = this.data.container(); + return new Promise(function (resolve) { + return nodesRef.boundingClientRect(resolve).exec(); + }); + }, + }, +}); diff --git a/components/sticky/index.json b/components/sticky/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/sticky/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/sticky/index.wxml b/components/sticky/index.wxml new file mode 100644 index 0000000..15e9f4a --- /dev/null +++ b/components/sticky/index.wxml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/components/sticky/index.wxs b/components/sticky/index.wxs new file mode 100644 index 0000000..18efe14 --- /dev/null +++ b/components/sticky/index.wxs @@ -0,0 +1,37 @@ +/* eslint-disable */ +function wrapStyle(data) { + var style = ''; + + if (data.transform) { + style += 'transform: translate3d(0, ' + data.transform + 'px, 0);'; + } + + if (data.fixed) { + style += 'top: ' + data.offsetTop + 'px;'; + } + + if (data.zIndex) { + style += 'z-index: ' + data.zIndex + ';'; + } + + return style; +} + +function containerStyle(data) { + var style = ''; + + if (data.fixed) { + style += 'height: ' + data.height + 'px;'; + } + + if (data.zIndex) { + style += 'z-index: ' + data.zIndex + ';'; + } + + return style; +} + +module.exports = { + wrapStyle: wrapStyle, + containerStyle: containerStyle +}; diff --git a/components/sticky/index.wxss b/components/sticky/index.wxss new file mode 100644 index 0000000..5269387 --- /dev/null +++ b/components/sticky/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{position:fixed;right:0;left:0} \ No newline at end of file diff --git a/components/submit-layout/index.js b/components/submit-layout/index.js new file mode 100644 index 0000000..c7b8755 --- /dev/null +++ b/components/submit-layout/index.js @@ -0,0 +1,16 @@ +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + data: { + safeBottom: app.globalData.safeBottom, + }, + lifetimes: { + attached: function () { + this.setData({ safeBottom: app.globalData.safeBottom }) + } + }, +}) \ No newline at end of file diff --git a/components/submit-layout/index.json b/components/submit-layout/index.json new file mode 100644 index 0000000..5144c0f --- /dev/null +++ b/components/submit-layout/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": { } +} \ No newline at end of file diff --git a/components/submit-layout/index.wxml b/components/submit-layout/index.wxml new file mode 100644 index 0000000..c6c23b2 --- /dev/null +++ b/components/submit-layout/index.wxml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/components/submit-layout/index.wxss b/components/submit-layout/index.wxss new file mode 100644 index 0000000..a12c39e --- /dev/null +++ b/components/submit-layout/index.wxss @@ -0,0 +1,4 @@ +.view-load { + margin-right: 12rpx; + margin-bottom: 12rpx +} \ No newline at end of file diff --git a/components/switch/index.js b/components/switch/index.js new file mode 100644 index 0000000..af301c5 --- /dev/null +++ b/components/switch/index.js @@ -0,0 +1,51 @@ +import { VantComponent } from '../common/component'; +import { BLUE, GRAY_DARK } from '../common/color'; +VantComponent({ + field: true, + classes: ['node-class'], + props: { + checked: { + type: null, + observer(value) { + const loadingColor = this.getLoadingColor(value); + this.setData({ value, loadingColor }); + } + }, + loading: Boolean, + disabled: Boolean, + activeColor: String, + inactiveColor: String, + size: { + type: String, + value: '30px' + }, + activeValue: { + type: null, + value: true + }, + inactiveValue: { + type: null, + value: false + } + }, + created() { + const { checked: value } = this.data; + const loadingColor = this.getLoadingColor(value); + this.setData({ value, loadingColor }); + }, + methods: { + getLoadingColor(checked) { + const { activeColor, inactiveColor } = this.data; + return checked ? activeColor || BLUE : inactiveColor || GRAY_DARK; + }, + onClick() { + const { activeValue, inactiveValue } = this.data; + if (!this.data.disabled && !this.data.loading) { + const checked = this.data.checked === activeValue; + const value = checked ? inactiveValue : activeValue; + this.$emit('input', value); + this.$emit('change', value); + } + } + } +}); diff --git a/components/switch/index.json b/components/switch/index.json new file mode 100644 index 0000000..01077f5 --- /dev/null +++ b/components/switch/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-loading": "../loading/index" + } +} diff --git a/components/switch/index.wxml b/components/switch/index.wxml new file mode 100644 index 0000000..31a104d --- /dev/null +++ b/components/switch/index.wxml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/components/switch/index.wxss b/components/switch/index.wxss new file mode 100644 index 0000000..f454ae5 --- /dev/null +++ b/components/switch/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-switch{position:relative;display:block;box-sizing:initial;width:2em;width:var(--switch-width,2em);height:1em;height:var(--switch-height,1em);background-color:#fff;background-color:var(--switch-background-color,#fff);border:1px solid rgba(0,0,0,.1);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:1em;border-radius:var(--switch-node-size,1em);transition:background-color .3s;transition:background-color var(--switch-transition-duration,.3s)}.van-switch__node{position:absolute;top:0;left:0;border-radius:100%;z-index:1;z-index:var(--switch-node-z-index,1);width:1em;width:var(--switch-node-size,1em);height:1em;height:var(--switch-node-size,1em);background-color:#fff;background-color:var(--switch-node-background-color,#fff);box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));transition:-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05),-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05),-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05)}.van-switch__loading{position:absolute!important;top:25%;left:25%;width:50%;height:50%}.van-switch--on{background-color:#1989fa;background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em);-webkit-transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:.4;opacity:var(--switch-disabled-opacity,.4)} \ No newline at end of file diff --git a/components/tab/index.js b/components/tab/index.js new file mode 100644 index 0000000..79a3c23 --- /dev/null +++ b/components/tab/index.js @@ -0,0 +1,59 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'tabs', + type: 'ancestor', + current: 'tab', + }, + props: { + dot: { + type: Boolean, + observer: 'update' + }, + info: { + type: null, + observer: 'update' + }, + title: { + type: String, + observer: 'update' + }, + disabled: { + type: Boolean, + observer: 'update' + }, + titleStyle: { + type: String, + observer: 'update' + }, + name: { + type: [Number, String], + value: '', + } + }, + data: { + active: false + }, + methods: { + getComputedName() { + if (this.data.name !== '') { + return this.data.name; + } + return this.index; + }, + updateRender(active, parent) { + const { data: parentData } = parent; + this.inited = this.inited || active; + this.setData({ + active, + shouldRender: this.inited || !parentData.lazyRender, + shouldShow: active || parentData.animated + }); + }, + update() { + if (this.parent) { + this.parent.updateTabs(); + } + } + } +}); diff --git a/components/tab/index.json b/components/tab/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/tab/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/tab/index.wxml b/components/tab/index.wxml new file mode 100644 index 0000000..0428200 --- /dev/null +++ b/components/tab/index.wxml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/components/tab/index.wxss b/components/tab/index.wxss new file mode 100644 index 0000000..76ddf06 --- /dev/null +++ b/components/tab/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';:host{-webkit-flex-shrink:0;flex-shrink:0;width:100%}.van-tab__pane,:host{box-sizing:border-box}.van-tab__pane{overflow-y:auto;-webkit-overflow-scrolling:touch}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible} \ No newline at end of file diff --git a/components/tabbar-item/index.js b/components/tabbar-item/index.js new file mode 100644 index 0000000..3555a26 --- /dev/null +++ b/components/tabbar-item/index.js @@ -0,0 +1,48 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + info: null, + name: null, + icon: String, + dot: Boolean + }, + relation: { + name: 'tabbar', + type: 'ancestor', + current: 'tabbar-item', + }, + data: { + active: false + }, + methods: { + onClick() { + if (this.parent) { + this.parent.onChange(this); + } + this.$emit('click'); + }, + updateFromParent() { + const { parent } = this; + if (!parent) { + return; + } + const index = parent.children.indexOf(this); + const parentData = parent.data; + const { data } = this; + const active = (data.name || index) === parentData.active; + const patch = {}; + if (active !== data.active) { + patch.active = active; + } + if (parentData.activeColor !== data.activeColor) { + patch.activeColor = parentData.activeColor; + } + if (parentData.inactiveColor !== data.inactiveColor) { + patch.inactiveColor = parentData.inactiveColor; + } + return Object.keys(patch).length > 0 + ? this.set(patch) + : Promise.resolve(); + } + } +}); diff --git a/components/tabbar-item/index.json b/components/tabbar-item/index.json new file mode 100644 index 0000000..16f174c --- /dev/null +++ b/components/tabbar-item/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-info": "../info/index" + } +} diff --git a/components/tabbar-item/index.wxml b/components/tabbar-item/index.wxml new file mode 100644 index 0000000..f2d399b --- /dev/null +++ b/components/tabbar-item/index.wxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/tabbar-item/index.wxss b/components/tabbar-item/index.wxss new file mode 100644 index 0000000..35d3e71 --- /dev/null +++ b/components/tabbar-item/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;height:100%;color:#646566;color:var(--tabbar-item-text-color,#646566);font-size:12px;font-size:var(--tabbar-item-font-size,12px);line-height:1;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{position:relative;font-size:18px;font-size:var(--tabbar-item-icon-size,18px)}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:#1989fa;color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px} \ No newline at end of file diff --git a/components/tabbar/index.js b/components/tabbar/index.js new file mode 100644 index 0000000..620936f --- /dev/null +++ b/components/tabbar/index.js @@ -0,0 +1,61 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + relation: { + name: 'tabbar-item', + type: 'descendant', + current: 'tabbar', + linked(target) { + target.parent = this; + target.updateFromParent(); + }, + unlinked() { + this.updateChildren(); + } + }, + props: { + active: { + type: null, + observer: 'updateChildren' + }, + activeColor: { + type: String, + observer: 'updateChildren' + }, + inactiveColor: { + type: String, + observer: 'updateChildren' + }, + fixed: { + type: Boolean, + value: true + }, + border: { + type: Boolean, + value: true + }, + zIndex: { + type: Number, + value: 1 + }, + safeAreaInsetBottom: { + type: Boolean, + value: true + } + }, + methods: { + updateChildren() { + const { children } = this; + if (!Array.isArray(children) || !children.length) { + return Promise.resolve(); + } + return Promise.all(children.map((child) => child.updateFromParent())); + }, + onChange(child) { + const index = this.children.indexOf(child); + const active = child.data.name || index; + if (active !== this.data.active) { + this.$emit('change', active); + } + } + } +}); diff --git a/components/tabbar/index.json b/components/tabbar/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/tabbar/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/tabbar/index.wxml b/components/tabbar/index.wxml new file mode 100644 index 0000000..96b0508 --- /dev/null +++ b/components/tabbar/index.wxml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/components/tabbar/index.wxss b/components/tabbar/index.wxss new file mode 100644 index 0000000..4824e24 --- /dev/null +++ b/components/tabbar/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:100rpx;height:var(--tabbar-height, 100rpx);background-color:#fff;background-color:var(--tabbar-background-color,#fff)}.van-tabbar--fixed{position:fixed;bottom:0;left:0} \ No newline at end of file diff --git a/components/table/index.js b/components/table/index.js new file mode 100644 index 0000000..5a19139 --- /dev/null +++ b/components/table/index.js @@ -0,0 +1,112 @@ +Component({ + /** + * 外部样式类 + */ + externalClasses: ['header-row-class-name', 'row-class-name', 'cell-class-name'], + /** + * 组件样式隔离 + */ + options: { + addGlobalClass: true, + multipleSlots: true // 支持多个slot + }, + /** + * 组件的属性列表 + */ + properties: { + data: { + type: Array, + value: [] + }, + headers: { + type: Array, + value: [] + }, + // table的高度, 溢出可滚动 + height: { + type: Number || String, + value: 'auto' + }, + width: { + type: Number || String, + value: '100%' + }, + // 单元格的宽度 + tdWidth: { + type: Number, + value: 35 + }, + // 固定表头 thead达到Header的位置时就应该被fixed了 + offsetTop: { + type: Number, + value: 150 + }, + // 是否带有纵向边框 + stripe: { + type: Boolean, + value: false + }, + // 是否带有纵向边框 + border: { + type: Boolean, + value: true + }, + msg: { + type: String, + value: '暂无数据~' + } + }, + /** + * 组件的初始数据 + */ + data: { + scrolWidth: '100%' + }, + /** + * 组件的监听属性 + */ + observers: { + // 在 numberA 或者 numberB 被设置时,执行这个函数 + 'headers': function headers(_headers) { + var reducer = function reducer(accumulator, currentValue) { + return accumulator + Number(currentValue.width) + } + var scrolWidth = _headers.reduce(reducer, 0) + this.setData({ scrolWidth: scrolWidth }) + } + }, + /** + * 组件的方法列表 + */ + methods: { + onRowClick: function(e) { + var row = this.data.data[e.currentTarget.dataset.row] + this.triggerEvent('rowClick', row) + }, + onCellClick: function(e){ + this.triggerEvent('cellClick', e) + }, + onHeaderClick: function(e){ + var index = e.currentTarget.dataset.index + var item = this.data.headers[index] + if(!item.sort){ + return + } + for (let mk = 0; mk < this.data.headers.length; mk++) { + if(mk !== index && this.data.headers[mk].sort){ + this.data.headers[mk].sort = 1 + } else if(mk === index && this.data.headers[mk].sort){ + if(this.data.headers[mk].sort == 1){ + this.data.headers[mk].sort = 2 + } else if(this.data.headers[mk].sort == 2){ + this.data.headers[mk].sort = 3 + } else if(this.data.headers[mk].sort == 3){ + this.data.headers[mk].sort = 1 + } + } + } + this.setData({headers: this.data.headers }) + this.triggerEvent('sort', { prop: item.prop, sort: this.data.headers[index].sort }) + } + } +}) \ No newline at end of file diff --git a/components/table/index.json b/components/table/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/table/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/table/index.wxml b/components/table/index.wxml new file mode 100644 index 0000000..509da53 --- /dev/null +++ b/components/table/index.wxml @@ -0,0 +1,27 @@ + + + + + {{ item.label }} + + + + + + + + + + + + {{ head["prop"] === 'index' ? (idx+1) : ( head["suffix"] ? it[head["prop"]] + head["suffix"] : it[head["prop"]] ) }} + + + + + + {{ msg }} + + + \ No newline at end of file diff --git a/components/table/index.wxss b/components/table/index.wxss new file mode 100644 index 0000000..910f390 --- /dev/null +++ b/components/table/index.wxss @@ -0,0 +1,87 @@ + +.table { + position: relative; + font-size: 28rpx; + background: #fff; + border-right:none; + /* border-radius: 8rpx; */ + overflow: hidden; +} +.thead{ + border-bottom: none; + display: flex; + justify-content: flex-start; + /* border-top-right-radius: 8rpx; + border-top-left-radius: 8rpx; */ + overflow: visible; + color: #909399; + border: 1rpx solid #f3f3f3; + box-sizing: border-box; +} +.thead .td { + font-weight: bold; + white-space:nowrap; + text-align: center; + align-items: center; + height: 80rpx; + border-right: 1rpx solid #fff; +} +.thead .td:last-child { + border-right: none; +} +.thead-border .td { + border-right: 1rpx solid #f3f3f3; +} +.thead-border .td:last-child { + border-right: none; +} +/* .tr{ + display: flex; + white-space:nowrap; +} */ +.tbody { + box-sizing: border-box; + font-size: 28rpx; + color: #666; + border: 1px solid #f3f3f3; + border-top: none; + /* border-bottom-left-radius: 8rpx; + border-bottom-right-radius: 8rpx; */ +} +.tbody-tr { + display: flex; + border-bottom: 1px solid #f3f3f3; +} +/* .tbody-tr:last-child { + border-bottom-left-radius: 8rpx; + border-bottom-right-radius: 8rpx; +} */ + +.tbody-tr-stripe { + background: #fff; + border-bottom: none; +} +.tbody-tr-stripe:nth-child(2n) { + background: #F6F6F6; +} +.tbody-tr .td { + white-space: wrap; + height: 80rpx; + /* padding: 0rpx 16rpx; */ + /* padding:20rpx 10rpx; */ + line-height: 80rpx; + text-align: center; +} + +.tbody-tr-border .td { + border-right: 1rpx solid #F6F6F6; +} +.tbody-tr-border .td:last-child { + border-right: none; +} +.no-data { + display: flex; + padding: 50rpx; + color: #666; + justify-content: center; +} \ No newline at end of file diff --git a/components/tabs/index.js b/components/tabs/index.js new file mode 100644 index 0000000..dbc1f43 --- /dev/null +++ b/components/tabs/index.js @@ -0,0 +1,274 @@ +import { VantComponent } from '../common/component'; +import { touch } from '../mixins/touch'; +import { isDef, addUnit } from '../common/utils'; +VantComponent({ + mixins: [touch], + classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'], + relation: { + name: 'tab', + type: 'descendant', + current: 'tabs', + linked(target) { + target.index = this.children.length - 1; + this.updateTabs(); + }, + unlinked() { + this.children = this.children + .map((child, index) => { + child.index = index; + return child; + }); + this.updateTabs(); + } + }, + props: { + color: { + type: String, + observer: 'setLine' + }, + sticky: Boolean, + animated: { + type: Boolean, + observer() { + this.children.forEach((child, index) => child.updateRender(index === this.data.currentIndex, this)); + } + }, + swipeable: Boolean, + lineWidth: { + type: [String, Number], + value: -1, + observer: 'setLine' + }, + lineHeight: { + type: [String, Number], + value: -1, + observer: 'setLine' + }, + titleActiveColor: String, + titleInactiveColor: String, + active: { + type: [String, Number], + value: 0, + observer(name) { + if (name !== this.getCurrentName()) { + this.setCurrentIndexByName(name); + } + } + }, + type: { + type: String, + value: 'line' + }, + border: { + type: Boolean, + value: false + }, + ellipsis: { + type: Boolean, + value: true + }, + duration: { + type: Number, + value: 0.3 + }, + zIndex: { + type: Number, + value: 1 + }, + swipeThreshold: { + type: Number, + value: 4, + observer(value) { + this.setData({ + scrollable: this.children.length > value || !this.data.ellipsis + }); + } + }, + offsetTop: { + type: Number, + value: 0 + }, + lazyRender: { + type: Boolean, + value: true + } + }, + data: { + tabs: [], + lineStyle: '', + scrollLeft: 0, + scrollable: false, + trackStyle: '', + currentIndex: null, + container: null + }, + mounted() { + wx.nextTick(() => { + this.setLine(true); + this.scrollIntoView(); + }); + }, + methods: { + updateContainer() { + this.setData({ + container: () => this.createSelectorQuery().select('.van-tabs') + }); + }, + updateTabs() { + const { children = [], data } = this; + this.setData({ + tabs: children.map((child) => child.data), + scrollable: this.children.length > data.swipeThreshold || !data.ellipsis + }); + this.setCurrentIndexByName(this.getCurrentName() || data.active); + }, + trigger(eventName, child) { + const { currentIndex } = this.data; + const currentChild = child || this.children[currentIndex]; + if (!isDef(currentChild)) { + return; + } + this.$emit(eventName, { + index: currentChild.index, + name: currentChild.getComputedName(), + title: currentChild.data.title + }); + }, + onTap(event) { + const { index } = event.currentTarget.dataset; + const child = this.children[index]; + if (child.data.disabled) { + this.trigger('disabled', child); + } + else { + this.setCurrentIndex(index); + wx.nextTick(() => { + this.trigger('click'); + }); + } + }, + // correct the index of active tab + setCurrentIndexByName(name) { + const { children = [] } = this; + const matched = children.filter((child) => child.getComputedName() === name); + if (matched.length) { + this.setCurrentIndex(matched[0].index); + } + }, + setCurrentIndex(currentIndex) { + const { data, children = [] } = this; + if (!isDef(currentIndex) || + currentIndex >= children.length || + currentIndex < 0) { + return; + } + children.forEach((item, index) => { + const active = index === currentIndex; + if (active !== item.data.active || !item.inited) { + item.updateRender(active, this); + } + }); + if (currentIndex === data.currentIndex) { + return; + } + const shouldEmitChange = data.currentIndex !== null; + this.setData({ currentIndex }); + wx.nextTick(() => { + this.setLine(); + this.scrollIntoView(); + this.updateContainer(); + this.trigger('input'); + if (shouldEmitChange) { + this.trigger('change'); + } + }); + }, + getCurrentName() { + const activeTab = this.children[this.data.currentIndex]; + if (activeTab) { + return activeTab.getComputedName(); + } + }, + setLine(skipTransition) { + if (this.data.type !== 'line') { + return; + } + const { color, duration, currentIndex, lineWidth, lineHeight } = this.data; + this.getRect('.van-tab', true).then((rects = []) => { + const rect = rects[currentIndex]; + if (rect == null) { + return; + } + const width = lineWidth !== -1 ? lineWidth : rect.width / 2; + const height = lineHeight !== -1 + ? `height: ${addUnit(lineHeight)}; border-radius: ${addUnit(lineHeight)};` + : ''; + let left = rects + .slice(0, currentIndex) + .reduce((prev, curr) => prev + curr.width, 0); + left += (rect.width - width) / 2; + const transition = skipTransition + ? '' + : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`; + this.setData({ + lineStyle: ` + ${height} + width: ${addUnit(width)}; + background-color: ${color}; + -webkit-transform: translateX(${left}px); + transform: translateX(${left}px); + ${transition} + ` + }); + }); + }, + // scroll active tab into view + scrollIntoView() { + const { currentIndex, scrollable } = this.data; + if (!scrollable) { + return; + } + Promise.all([ + this.getRect('.van-tab', true), + this.getRect('.van-tabs__nav') + ]).then(([tabRects, navRect]) => { + const tabRect = tabRects[currentIndex]; + const offsetLeft = tabRects + .slice(0, currentIndex) + .reduce((prev, curr) => prev + curr.width, 0); + this.setData({ + scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2 + }); + }); + }, + onTouchScroll(event) { + this.$emit('scroll', event.detail); + }, + onTouchStart(event) { + if (!this.data.swipeable) + return; + this.touchStart(event); + }, + onTouchMove(event) { + if (!this.data.swipeable) + return; + this.touchMove(event); + }, + // watch swipe touch end + onTouchEnd() { + if (!this.data.swipeable) + return; + const { tabs, currentIndex } = this.data; + const { direction, deltaX, offsetX } = this; + const minSwipeDistance = 50; + if (direction === 'horizontal' && offsetX >= minSwipeDistance) { + if (deltaX > 0 && currentIndex !== 0) { + this.setCurrentIndex(currentIndex - 1); + } + else if (deltaX < 0 && currentIndex !== tabs.length - 1) { + this.setCurrentIndex(currentIndex + 1); + } + } + } + } +}); diff --git a/components/tabs/index.json b/components/tabs/index.json new file mode 100644 index 0000000..19c0bc3 --- /dev/null +++ b/components/tabs/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-info": "../info/index", + "van-sticky": "../sticky/index" + } +} diff --git a/components/tabs/index.wxml b/components/tabs/index.wxml new file mode 100644 index 0000000..492ed68 --- /dev/null +++ b/components/tabs/index.wxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + {{ item.title }} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/tabs/index.wxs b/components/tabs/index.wxs new file mode 100644 index 0000000..88bcafd --- /dev/null +++ b/components/tabs/index.wxs @@ -0,0 +1,78 @@ +/* eslint-disable */ +function tabClass(active, ellipsis) { + var classes = ['tab-class']; + + if (active) { + classes.push('tab-active-class'); + } + + if (ellipsis) { + classes.push('van-ellipsis'); + } + + return classes.join(' '); +} + +function tabStyle( + active, + ellipsis, + color, + type, + disabled, + activeColor, + inactiveColor, + swipeThreshold, + scrollable +) { + var styles = []; + var isCard = type === 'card'; + // card theme color + if (color && isCard) { + styles.push('border-color:' + color); + + if (!disabled) { + if (active) { + styles.push('background-color:' + color); + } else { + styles.push('color:' + color); + } + } + } + + var titleColor = active ? activeColor : inactiveColor; + if (titleColor) { + styles.push('color:' + titleColor); + } + + if (scrollable && ellipsis) { + styles.push('flex-basis:' + 88 / swipeThreshold + '%'); + } + + return styles.join(';'); +} + +function tabCardTypeBorderStyle(color, type) { + var isCard = type === 'card'; + var styles = []; + if (isCard && color) { + styles.push('border-color:' + color); + } + return styles.join(';'); +} + +function trackStyle(data) { + if (!data.animated) { + return ''; + } + + return [ + 'transform: translate3d(' + -100 * data.currentIndex + '%, 0, 0)', + '-webkit-transition-duration: ' + data.duration + 's', + 'transition-duration: ' + data.duration + 's' + ].join(';'); +} + +module.exports.tabClass = tabClass; +module.exports.tabStyle = tabStyle; +module.exports.trackStyle = trackStyle; +module.exports.tabCardTypeBorderStyle = tabCardTypeBorderStyle; diff --git a/components/tabs/index.wxss b/components/tabs/index.wxss new file mode 100644 index 0000000..e2849f7 --- /dev/null +++ b/components/tabs/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{display:-webkit-flex;display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll{background-color:#fff;background-color:var(--tabs-nav-background-color,#fff)}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{margin:0 16px;margin:0 var(--padding-md,16px)}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:30px;height:var(--tabs-card-height,30px);border:1px solid #ee0a24;border:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24);border-radius:2px;border-radius:var(--border-radius-sm,2px)}.van-tabs__nav--card .van-tab{color:#ee0a24;color:var(--tabs-default-color,#ee0a24);height:30px;line-height:30px;line-height:calc(var(--tabs-card-height, 30px));border-right:1px solid #ee0a24;border-right:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;color:var(--white,#fff);background-color:#ee0a24;background-color:var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;height:var(--tabs-bottom-bar-height,3px);border-radius:3px;border-radius:var(--tabs-bottom-bar-height,3px);background-color:#ee0a24;background-color:var(--tabs-bottom-bar-color,#ee0a24)}.van-tabs__track{position:relative;width:100%;height:100%}.van-tabs__track--animated{display:-webkit-flex;display:flex;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-tabs__content{overflow:hidden}.van-tabs--line .van-tabs__wrap{height:90rpx;height:var(--tabs-line-height,90rpx)}.van-tabs--card .van-tabs__wrap{height:30px;height:var(--tabs-card-height,30px)}.van-tab{position:relative;-webkit-flex:1;flex:1;box-sizing:border-box;min-width:0;padding:0 5px;text-align:center;cursor:pointer;color:#646566;color:var(--tab-text-color,#646566);font-size:14px;font-size:var(--tab-font-size,14px);line-height:90rpx;line-height:var(--tabs-line-height,90rpx)}.van-tab--active{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--tab-active-text-color,#323233)}.van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab--complete{-webkit-flex:1 0 auto!important;flex:1 0 auto!important}.van-tab__title__info{top:8px!important;right:10px;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important} \ No newline at end of file diff --git a/components/tag/index.js b/components/tag/index.js new file mode 100644 index 0000000..093acb5 --- /dev/null +++ b/components/tag/index.js @@ -0,0 +1,21 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + size: String, + mark: Boolean, + color: String, + plain: Boolean, + round: Boolean, + textColor: String, + type: { + type: String, + value: 'default' + }, + closeable: Boolean + }, + methods: { + onClose() { + this.$emit('close'); + } + } +}); diff --git a/components/tag/index.json b/components/tag/index.json new file mode 100644 index 0000000..0a336c0 --- /dev/null +++ b/components/tag/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/components/tag/index.wxml b/components/tag/index.wxml new file mode 100644 index 0000000..e9749f3 --- /dev/null +++ b/components/tag/index.wxml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/components/tag/index.wxss b/components/tag/index.wxss new file mode 100644 index 0000000..211e376 --- /dev/null +++ b/components/tag/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-tag{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;line-height:normal;padding:.2em .5em;padding:var(--tag-padding,.2em .5em);color:#fff;color:var(--tag-text-color,#fff);font-size:10px;font-size:var(--tag-font-size,10px);border-radius:.2em;border-radius:var(--tag-border-radius,.2em)}.van-tag:after{border-color:currentColor;border-radius:.2em * 2;border-radius:var(--tag-border-radius,.2em) * 2}.van-tag--default{background-color:#969799;background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:#969799;color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:#ee0a24;background-color:var(--tag-dander-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:#ee0a24;color:var(--tag-dander-color,#ee0a24)}.van-tag--primary{background-color:#1989fa;background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:#1989fa;color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:#07c160;background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:#07c160;color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:#ff976a;background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:#ff976a;color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:#fff;background-color:var(--tag-plain-background-color,#fff)}.van-tag--mark{padding-right:.7em}.van-tag--mark,.van-tag--mark:after{border-radius:0 999px 999px 0;border-radius:0 var(--tag-round-border-radius,999px) var(--tag-round-border-radius,999px) 0}.van-tag--round,.van-tag--round:after{border-radius:999px;border-radius:var(--tag-round-border-radius,999px)}.van-tag--medium{font-size:12px;font-size:var(--tag-medium-font-size,12px)}.van-tag--large{font-size:14px;font-size:var(--tag-large-font-size,14px)}.van-tag__close{margin-left:2px} \ No newline at end of file diff --git a/components/textarea/index.js b/components/textarea/index.js new file mode 100644 index 0000000..03ca4ef --- /dev/null +++ b/components/textarea/index.js @@ -0,0 +1,75 @@ +Component({ + /** + * 组件样式隔离 + */ + options: { + addGlobalClass: true, + multipleSlots: true // 支持多个slot + }, + properties: { + value: { + type: String, + value: null + }, + placeholder: { + type: String, + value: '' + } + }, + /** + * 组件的初始数据 + */ + data: { + editing: false, + scroll_top: 0, + top: 0, + }, + + /** + * 组件的方法列表 + */ + methods: { + onEdit: function(e) { + this.setData({ editing: true }) + if (this.data.scroll_top > 0 || Number(e.detail.height) <= 0) { + return; + } + if(this.data.top > 0){ + that.triggerEvent('focus', that.data.top) + return + } + const res = wx.getSystemInfoSync(); + let windowHeight = res.windowHeight; + let keybordHeight = e.detail.height; + const query = wx.createSelectorQuery(); + query.select('#' + e.currentTarget.id).boundingClientRect(); + query.selectViewport().scrollOffset(); + var that = this; + query.exec(function(res) { + if (!res[0]) { + that.data.scroll_top = 0 + that.triggerEvent('focus', 0) + return; + } + let bottom = res[0].bottom; + if ((windowHeight - keybordHeight) < (bottom + 20)) { + that.data.scroll_top = bottom + 80 - windowHeight - keybordHeight + that.data.top = that.data.scroll_top + that.triggerEvent('focus', that.data.scroll_top) + } else { + that.triggerEvent('focus', 0) + that.data.scroll_top = 0 + } + }) + }, + onBlur: function(e) { + this.setData({ editing: false }) + this.data.scroll_top = 0 + this.triggerEvent('focus', 0) + }, + bindInput: function(e) { + this.setData({ value: e.detail.value }) + this.triggerEvent('change', this.data.value) + } + } +}) \ No newline at end of file diff --git a/components/textarea/index.json b/components/textarea/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/textarea/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/textarea/index.wxml b/components/textarea/index.wxml new file mode 100644 index 0000000..13f3713 --- /dev/null +++ b/components/textarea/index.wxml @@ -0,0 +1,4 @@ +{{value || placeholder }} + \ No newline at end of file diff --git a/components/textarea/index.wxss b/components/textarea/index.wxss new file mode 100644 index 0000000..4b7fd88 --- /dev/null +++ b/components/textarea/index.wxss @@ -0,0 +1,7 @@ +.textarea{ + width:100%; + height:80px; + padding:12rpx; + font-size: 14px; + border: 1rpx solid #f3f3f3; +} \ No newline at end of file diff --git a/components/transition/index.js b/components/transition/index.js new file mode 100644 index 0000000..3dd4c2e --- /dev/null +++ b/components/transition/index.js @@ -0,0 +1,15 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +var component = require('../common/component'); +var transition = require('../mixins/transition'); +component.VantComponent({ + classes: [ + 'enter-class', + 'enter-active-class', + 'enter-to-class', + 'leave-class', + 'leave-active-class', + 'leave-to-class', + ], + mixins: [transition.transition(true)], +}); diff --git a/components/transition/index.json b/components/transition/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/transition/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/transition/index.wxml b/components/transition/index.wxml new file mode 100644 index 0000000..61aceff --- /dev/null +++ b/components/transition/index.wxml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/components/transition/index.wxss b/components/transition/index.wxss new file mode 100644 index 0000000..d459f5c --- /dev/null +++ b/components/transition/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);opacity:0}.van-fade-down-enter,.van-fade-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);opacity:0}.van-fade-left-enter,.van-fade-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.van-fade-right-enter,.van-fade-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)} \ No newline at end of file diff --git a/components/tree-select/index.js b/components/tree-select/index.js new file mode 100644 index 0000000..75c01e9 --- /dev/null +++ b/components/tree-select/index.js @@ -0,0 +1,72 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + classes: [ + 'main-item-class', + 'content-item-class', + 'main-active-class', + 'content-active-class', + 'main-disabled-class', + 'content-disabled-class', + ], + props: { + items: { + type: Array, + observer: 'updateSubItems', + }, + activeId: null, + mainActiveIndex: { + type: Number, + value: 0, + observer: 'updateSubItems', + }, + height: { + type: null, + value: 300, + }, + max: { + type: Number, + value: Infinity, + }, + flex: { + type: Number, + value: 1, + }, + selectedIcon: { + type: String, + value: 'success', + }, + }, + data: { + subItems: [], + }, + methods: { + // 当一个子项被选择时 + onSelectItem(event) { + const { item } = event.currentTarget.dataset; + const isArray = Array.isArray(this.data.activeId); + // 判断有没有超出右侧选择的最大数 + const isOverMax = isArray && this.data.activeId.length >= this.data.max; + // 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件 + const isSelected = isArray + ? this.data.activeId.indexOf(item.id) > -1 + : this.data.activeId === item.id; + if (!item.disabled && (!isOverMax || isSelected)) { + this.$emit('click-item', item); + } + }, + // 当一个导航被点击时 + onClickNav(event) { + const index = event.detail; + const item = this.data.items[index]; + if (!item.disabled) { + this.$emit('click-nav', { index }); + } + }, + // 更新子项列表 + updateSubItems() { + const { items, mainActiveIndex } = this.data; + const { children = [] } = items[mainActiveIndex] || {}; + this.setData({ subItems: children }); + }, + }, +}); diff --git a/components/tree-select/index.json b/components/tree-select/index.json new file mode 100644 index 0000000..42991a2 --- /dev/null +++ b/components/tree-select/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-sidebar": "../sidebar/index", + "van-sidebar-item": "../sidebar-item/index" + } +} diff --git a/components/tree-select/index.wxml b/components/tree-select/index.wxml new file mode 100644 index 0000000..48107ee --- /dev/null +++ b/components/tree-select/index.wxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + {{ item.text }} + + + + \ No newline at end of file diff --git a/components/tree-select/index.wxs b/components/tree-select/index.wxs new file mode 100644 index 0000000..b1cbb39 --- /dev/null +++ b/components/tree-select/index.wxs @@ -0,0 +1,12 @@ +/* eslint-disable */ +var array = require('../wxs/array.wxs'); + +function isActive (activeList, itemId) { + if (array.isArray(activeList)) { + return activeList.indexOf(itemId) > -1; + } + + return activeList === itemId; +} + +module.exports.isActive = isActive; diff --git a/components/tree-select/index.wxss b/components/tree-select/index.wxss new file mode 100644 index 0000000..be009ca --- /dev/null +++ b/components/tree-select/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-tree-select{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;font-size:14px;font-size:var(--tree-select-font-size,14px)}.van-tree-select__nav{-webkit-flex:1.5;flex:1.5;background-color:#f7f8fa;background-color:var(--tree-select-nav-background-color,#f7f8fa);--sidebar-padding:12px 8px 12px 12px}.van-tree-select__nav__inner{width:100%!important;height:100%}.van-tree-select__content{-webkit-flex:2;flex:2;background-color:#fff;background-color:var(--tree-select-content-background-color,#fff)}.van-tree-select__item{position:relative;font-weight:700;padding:0 32px 0 16px;padding:0 32px 0 var(--padding-md,16px);line-height:48px;line-height:var(--tree-select-item-height,48px)}.van-tree-select__item--active{color:#008AFF;color:var(--tree-select-item-active-color,#008AFF)}.van-tree-select__item--disabled{color:#c8c9cc;color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:16px;right:var(--padding-md,16px)} \ No newline at end of file diff --git a/components/uploader/index.js b/components/uploader/index.js new file mode 100644 index 0000000..0b786fc --- /dev/null +++ b/components/uploader/index.js @@ -0,0 +1,219 @@ +import { VantComponent } from '../common/component' +import { isImageFile, isVideo, chooseFile, isPromise } from './utils' +import { chooseImageProps, chooseVideoProps } from './shared' +import { zconfig } from'../../api/ztb' +const app = getApp() + +VantComponent({ + props: Object.assign(Object.assign({ + disabled: Boolean, + multiple: Boolean, + uploadText: String, + useBeforeRead: Boolean, + afterRead: null, + beforeRead: null, + previewSize: { type: null, value: 100 }, + name: { type: [Number, String], value: '' }, + accept: { type: String, value: 'image' }, + fileList: { type: Array, value: [], observer: 'formatFileList' }, + maxSize: { type: Number, value: Number.MAX_VALUE }, + url: { type: String, value: 'uploadImage' }, + maxCount: { type: Number, value: 100 }, + deletable: { type: Boolean, value: true }, + showUpload: { type: Boolean, value: true }, + previewImage: { type: Boolean, value: true }, + previewFullImage: { type: Boolean, value: true }, + imageFit: { type: String, value: 'aspectFill' }, + uploadIcon: { type: String, value: 'photograph' } + }, chooseImageProps), chooseVideoProps), + data: { + lists: [], + isInCount: true, + taskList: [] + }, + lifetimes: { + // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 + detached: function () { + for (let i = 0; i < this.data.taskList.length; i++) { + if (this.data.taskList[index]) { + this.data.taskList[index].abort() // 取消上传任务 + } + } + } + }, + methods: { + isEmpty: function(val) { + return typeof val === 'undefined' || val === '' || val === null + }, + formatFileList() { + const { fileList = [], maxCount } = this.data; + const lists = fileList.map(item => (Object.assign(Object.assign({}, item), { + isImage: typeof item.isImage === 'undefined' ? isImageFile(item) : item.isImage + }))) + this.setData({ lists, isInCount: lists.length < maxCount }) + }, + getDetail(index) { + return { name: this.data.name, index: index == null ? this.data.fileList.length : index } + }, + startUpload() { + if (disabled) + return + const { maxCount, multiple, accept, lists, disabled } = this.data + chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length })).then(res => { + let file = null + if (isVideo(res, accept)) { + file = Object.assign({ path: res.tempFilePath }, res) + } else { + file = multiple ? res.tempFiles : res.tempFiles[0] + } + this.onBeforeRead(file) + }).catch(error => { + this.$emit('error', error) + }) + }, + onBeforeRead(file) { + const { beforeRead, useBeforeRead } = this.data + let res = true + if (typeof beforeRead === 'function') { + res = beforeRead(file, this.getDetail()) + } + if (useBeforeRead) { + res = new Promise((resolve, reject) => { + this.$emit('before-read', Object.assign(Object.assign({ file}, this.getDetail()), { callback: (ok) => { ok ? resolve() : reject() }})) + }) + } + if (!res) { + return + } + if (isPromise(res)) { + res.then((data) => this.onAfterRead(data || file)) + } else { + this.onAfterRead(file) + } + }, + onAfterRead(file) { + const { maxSize } = this.data; + const oversize = Array.isArray(file) ? file.some(item => item.size > maxSize) : file.size > maxSize + if (oversize) { + wx.showToast({ title: '图片大小超过限制!', icon: 'none' }) + this.$emit('oversize', Object.assign({ file }, this.getDetail())) + return + } + if (typeof this.data.afterRead === 'function') { + this.data.afterRead(file, this.getDetail()) + } + this.handFiles(Array.isArray(file) ? file : [file]) + }, + deleteItem(event) { + var index = event.currentTarget.dataset.index + var fsList = this.data.fileList + // 如果是正在上传的; + if (fsList[index]) { + if (fsList[index].status === 'uploading') { + if (this.data.taskList[index] && this.data.taskList[index].task) { + this.data.taskList[index].task.abort() // 取消上传任务 + } + this.data.taskList.splice(index, 1) + } + fsList.splice(index, 1) + } + this.formatFileList() + this.onUploadChange() + }, + onPreviewImage(event) { + const { index } = event.currentTarget.dataset; + const { lists } = this.data; + const item = lists[index]; + this.$emit('click-preview', Object.assign({ url: item.url || item.path }, this.getDetail(index))); + if (!this.data.previewFullImage) + return; + wx.previewImage({ + urls: lists.filter(item => item.isImage).map(item => item.url || item.path), + current: item.url || item.path, + fail() { + wx.showToast({title: '预览图片失败',icon: 'none'}) + } + }) + }, + /*********************************************************************************************************************************************/ + onUploadChange: function(){ + var fileList = this.data.fileList + var uploading = false + for (let index = 0; index < fileList.length; index++) { + const element = fileList[index] + if(element.status == 'uploading'){ + uploading = true + break + } + } + if(!uploading){ + this.$emit('file-change', Object.assign({ fileList }, this.getDetail())) + } + }, + updateFileStatus: function(path, url, status, message){ + var fsList = this.data.fileList + var index = -1 + for (let i = 0; i < fsList.length; i++) { + const element = fsList[i] + if(element.status == 'uploading' && element.path == path){ + index = i + break + } + } + if(index >= 0){ + this.setData({ ['fileList[' + index + ']']: { path, url, status, message } }) + } + }, + uploadFile: function (path) { + var that = this + var header = { ...zconfig.header, 'X-APP-ID': app.xAppId, appversion: app.version, 'Content-Type': 'multipart/form-data' } + const task = wx.uploadFile({ + url: zconfig.baseUrl + '/recycle-user-center/file-uploading/upload/image', + filePath: path, + name: 'image', + header, + success: function (result) { + var resp = null + if (!that.isEmpty(result.data)) { + resp = JSON.parse(result.data) + } + if (resp && resp.code === 0) { + that.updateFileStatus(path, resp.data, 'done', '') + } else { + that.updateFileStatus(path, null, 'failed', '上传失败') + } + that.onUploadChange() + }, + fail: function (res) { + that.updateFileStatus(path, null, 'failed', '上传失败') + that.onUploadChange() + }, + complete: function (res) { + for (let i = 0; i < that.data.taskList.length; i++) { + if (that.data.taskList[i].path === path) { + that.data.taskList.splice(i, 1); + break + } + } + } + }) + that.data.taskList.push({ path: path, task: task }) + }, + handFiles: function(fsList){ + if(!this.isEmpty(this.data.url)){ + // 进行文件上传。 + for (let i = 0; i < fsList.length; i++) { + const element = fsList[i] + element.status = 'uploading' + element.message = '上传中' + this.updateFileStatus(element.path, null, 'uploading', '上传中') + this.uploadFile(element.path) + } + const fileList = this.data.fileList + this.setData({ fileList: fileList.concat(fsList) }) + } else { + this.$emit('after-read', Object.assign({ fsList }, this.getDetail())) + } + } + } +}) \ No newline at end of file diff --git a/components/uploader/index.json b/components/uploader/index.json new file mode 100644 index 0000000..e00a588 --- /dev/null +++ b/components/uploader/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-loading": "../loading/index" + } +} diff --git a/components/uploader/index.wxml b/components/uploader/index.wxml new file mode 100644 index 0000000..617bdc6 --- /dev/null +++ b/components/uploader/index.wxml @@ -0,0 +1,31 @@ + + + + + + + {{ item.name || ('图片' + index) }} + + + {{ item.name || item.url || item.path }} + + + + + {{ item.message }} + + + + + + + + + + + + {{ uploadText }} + + + + \ No newline at end of file diff --git a/components/uploader/index.wxss b/components/uploader/index.wxss new file mode 100644 index 0000000..c3cbfd1 --- /dev/null +++ b/components/uploader/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-uploader{position:relative;display:inline-block}.van-uploader__wrapper{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:80px;height:80px;margin:0 8px 8px 0;background-color:#f7f8fa;border-radius:1px}.van-uploader__upload:active{background-color:#f2f3f5}.van-uploader__upload-icon{color:#dcdee0;font-size:24px}.van-uploader__upload-text{margin-top:8px;color:#969799;font-size:12px}.van-uploader__upload--disabled{opacity:.5;opacity:var(--uploader-disabled-opacity,.5)}.van-uploader__preview{position:relative;margin:0 12px 8px 0;cursor:pointer}.van-uploader__preview-image{display:block;width:80px;height:80px;overflow:hidden;border-radius:1px}.van-uploader__preview-delete{position:absolute;top:-8px;right:-8px;color:#969799;font-size:18px;background-color:#fff;border-radius:100%}.van-uploader__file{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;width:80px;height:80px;background-color:#f7f8fa;border-radius:1px}.van-uploader__file-icon{color:#646566;font-size:20px}.van-uploader__file-name{box-sizing:border-box;width:100%;margin-top:8px;padding:0 4px;color:#646566;font-size:12px;text-align:center}.van-uploader__mask{position:absolute;top:0;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#fff;background-color:rgba(50,50,51,.88);border-radius:1px}.van-uploader__mask-icon{font-size:22px}.van-uploader__mask-message{margin-top:6px;padding:0 4px;font-size:12px;line-height:14px}.van-uploader__loading{width:22px;height:22px;color:#fff} \ No newline at end of file diff --git a/components/uploader/shared.js b/components/uploader/shared.js new file mode 100644 index 0000000..871a07a --- /dev/null +++ b/components/uploader/shared.js @@ -0,0 +1,30 @@ +// props for choose image +export const chooseImageProps = { + sizeType: { + type: Array, + value: ['original', 'compressed'] + }, + capture: { + type: Array, + value: ['album', 'camera'] + } +}; +// props for choose video +export const chooseVideoProps = { + capture: { + type: Array, + value: ['album', 'camera'] + }, + compressed: { + type: Boolean, + value: true + }, + maxDuration: { + type: Number, + value: 60 + }, + camera: { + type: String, + value: 'back' + } +}; diff --git a/components/uploader/utils.js b/components/uploader/utils.js new file mode 100644 index 0000000..26389ac --- /dev/null +++ b/components/uploader/utils.js @@ -0,0 +1,61 @@ +const IMAGE_EXT = ['jpeg', 'jpg', 'gif', 'png', 'svg', 'webp']; +export function isImageUrl(url) { + return IMAGE_EXT.some(ext => url.indexOf(`.${ext}`) !== -1 || url.indexOf(`.${ext.toLocaleUpperCase()}`) !== -1); // 有些七牛返回来的后缀的大写,加以判断 +} +export function isImageFile(item) { + if (item.type) { + return item.type.indexOf('image') === 0; + } + if (item.path) { + return isImageUrl(item.path); + } + if (item.url) { + return isImageUrl(item.url); + } + return false; +} +export function isVideo(res, accept) { + return accept === 'video'; +} +export function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount }) { + if (accept === 'image') { + return new Promise((resolve, reject) => { + wx.chooseImage({ + count: multiple ? Math.min(maxCount, 9) : 1, + sourceType: capture, + sizeType, + success: resolve, + fail: reject + }); + }); + } + if (accept === 'video') { + return new Promise((resolve, reject) => { + wx.chooseVideo({ + sourceType: capture, + compressed, + maxDuration, + camera, + success: resolve, + fail: reject + }); + }); + } + return new Promise((resolve, reject) => { + wx.chooseMessageFile({ + count: multiple ? maxCount : 1, + type: 'file', + success: resolve, + fail: reject + }); + }); +} +export function isFunction(val) { + return typeof val === 'function'; +} +export function isObject(val) { + return val !== null && typeof val === 'object'; +} +export function isPromise(val) { + return isObject(val) && isFunction(val.then) && isFunction(val.catch); +} diff --git a/components/wxs/add-unit.wxs b/components/wxs/add-unit.wxs new file mode 100644 index 0000000..7d24fd5 --- /dev/null +++ b/components/wxs/add-unit.wxs @@ -0,0 +1,13 @@ +/* eslint-disable */ +var REGEXP = getRegExp('^\d+(\.\d+)?$'); + +function addUnit(value) { + if (value == null) { + return undefined; + } + return REGEXP.test('' + value) ? value + 'px' : value; +} + +module.exports = { + addUnit: addUnit +}; diff --git a/components/wxs/array.wxs b/components/wxs/array.wxs new file mode 100644 index 0000000..610089c --- /dev/null +++ b/components/wxs/array.wxs @@ -0,0 +1,5 @@ +function isArray(array) { + return array && array.constructor === 'Array'; +} + +module.exports.isArray = isArray; diff --git a/components/wxs/bem.wxs b/components/wxs/bem.wxs new file mode 100644 index 0000000..93b2777 --- /dev/null +++ b/components/wxs/bem.wxs @@ -0,0 +1,38 @@ +var array = require('./array.wxs'); +var object = require('./object.wxs'); +var PREFIX = 'van-'; + +function join(name, mods) { + name = PREFIX + name; + mods = mods.map(function(mod) { + return name + '--' + mod; + }); + mods.unshift(name); + return mods.join(' '); +} + +function traversing(mods, conf) { + if (!conf) { + return; + } + + if (typeof conf === 'string' || typeof conf === 'number') { + mods.push(conf); + } else if (array.isArray(conf)) { + conf.forEach(function(item) { + traversing(mods, item); + }); + } else if (typeof conf === 'object') { + object.keys(conf).forEach(function(key) { + conf[key] && mods.push(key); + }); + } +} + +function bem(name, conf) { + var mods = []; + traversing(mods, conf); + return join(name, mods); +} + +module.exports.bem = bem; diff --git a/components/wxs/memoize.wxs b/components/wxs/memoize.wxs new file mode 100644 index 0000000..261ae67 --- /dev/null +++ b/components/wxs/memoize.wxs @@ -0,0 +1,54 @@ +/** + * Simple memoize + * wxs doesn't support fn.apply, so this memoize only support up to 2 args + */ + +function isPrimitive(value) { + var type = typeof value; + return ( + type === 'boolean' || + type === 'number' || + type === 'string' || + type === 'undefined' || + value === null + ); +} + +// mock simple fn.call in wxs +function call(fn, args) { + if (args.length === 2) { + return fn(args[0], args[1]); + } + + if (args.length === 1) { + return fn(args[0]); + } + + return fn(); +} + +function serializer(args) { + if (args.length === 1 && isPrimitive(args[0])) { + return args[0]; + } + var obj = {}; + for (var i = 0; i < args.length; i++) { + obj['key' + i] = args[i]; + } + return JSON.stringify(obj); +} + +function memoize(fn) { + var cache = {}; + + return function() { + var key = serializer(arguments); + if (cache[key] === undefined) { + cache[key] = call(fn, arguments); + } + + return cache[key]; + }; +} + +module.exports.memoize = memoize; diff --git a/components/wxs/object.wxs b/components/wxs/object.wxs new file mode 100644 index 0000000..e077107 --- /dev/null +++ b/components/wxs/object.wxs @@ -0,0 +1,13 @@ +/* eslint-disable */ +var REGEXP = getRegExp('{|}|"', 'g'); + +function keys(obj) { + return JSON.stringify(obj) + .replace(REGEXP, '') + .split(',') + .map(function(item) { + return item.split(':')[0]; + }); +} + +module.exports.keys = keys; diff --git a/components/wxs/utils.wxs b/components/wxs/utils.wxs new file mode 100644 index 0000000..d5c9d8c --- /dev/null +++ b/components/wxs/utils.wxs @@ -0,0 +1,10 @@ +/* eslint-disable */ +var bem = require('./bem.wxs').bem; +var memoize = require('./memoize.wxs').memoize; +var addUnit = require('./add-unit.wxs').addUnit; + +module.exports = { + bem: memoize(bem), + memoize: memoize, + addUnit: addUnit +}; diff --git a/const/city.js b/const/city.js new file mode 100644 index 0000000..c1769a5 --- /dev/null +++ b/const/city.js @@ -0,0 +1,475 @@ +module.exports = { + list: [ + { + letter: "A", + data: [ + {name: "阿拉善盟", code: 152900, keyword: "阿拉善盟ALASHANMENG", latitude: 38.843075, longitude: 105.695683}, + {name: "鞍山市", code: 210300, keyword: "鞍山ANSHAN", latitude: 41.118744, longitude: 123.007763}, + {name: "安庆市", code: 340800, keyword: "安庆ANQING", latitude: 30.537898, longitude: 117.058739}, + {name: "安阳市", code: 410500, keyword: "安阳ANYANG", latitude: 36.110267, longitude: 114.351807}, + {name: "阿坝藏族羌族自治州", code: 513200, keyword: "阿坝藏族羌族自治州ABACANGZUQIANGZUZIZHIZHOU", latitude: 31.905763, longitude: 102.228565}, + {name: "安顺市", code: 520400, keyword: "安顺ANSHUN", latitude: 26.228595, longitude: 105.92827}, + {name: "阿里地区", code: 542500, keyword: "阿里地区ALIDIQU", latitude: 30.404557, longitude: 81.107669}, + {name: "安康市", code: 610900, keyword: "安康ANKANG", latitude: 32.70437, longitude: 109.038045}, + {name: "阿克苏地区", code: 652900, keyword: "阿克苏地区AKESUDIQU", latitude: 41.171731, longitude: 80.269846}, + {name: "阿勒泰地区", code: 654300, keyword: "阿勒泰地区ALETAIDIQU", latitude: 47.839744, longitude: 88.137915}, + {name: "阿拉尔市", code: 659002, keyword: "阿拉尔ALAER", latitude: 40.61568, longitude: 81.291737}, + {name: "澳门半岛", code: 820100, keyword: "澳门半岛AOMENBANDAO", latitude: 22.204118, longitude: 113.557519} + ] + }, + { + letter: "B", + data: [ + {name: "北京市", code: 110100, keyword: "北京BEIJING", latitude: 39.929986, longitude: 116.395645}, + {name: "保定市", code: 130600, keyword: "保定BAODING", latitude: 38.886565, longitude: 115.49481}, + {name: "包头市", code: 150200, keyword: "包头BAOTOU", latitude: 40.647119, longitude: 109.846239}, + {name: "巴彦淖尔市", code: 150800, keyword: "巴彦淖尔BAYANNEER", latitude: 40.76918, longitude: 107.423807}, + {name: "本溪市", code: 210500, keyword: "本溪BENXI", latitude: 41.325838, longitude: 123.778062}, + {name: "白山市", code: 220600, keyword: "白山BAISHAN", latitude: 41.945859, longitude: 126.435798}, + {name: "白城市", code: 220800, keyword: "白城BAICHENG", latitude: 45.621086, longitude: 122.840777}, + {name: "蚌埠市", code: 340300, keyword: "蚌埠BANGBU", latitude: 32.929499, longitude: 117.35708}, + {name: "亳州市", code: 341600, keyword: "亳州BOZHOU", latitude: 33.871211, longitude: 115.787928}, + {name: "滨州市", code: 371600, keyword: "滨州BINZHOU", latitude: 37.405314, longitude: 117.968292}, + {name: "北海市", code: 450500, keyword: "北海BEIHAI", latitude: 21.472718, longitude: 109.122628}, + {name: "百色市", code: 451000, keyword: "百色BAISE", latitude: 23.901512, longitude: 106.631821}, + {name: "白沙黎族自治县", code: 469030, keyword: "白沙黎族自治县BAISHALIZUZIZHIXIAN", latitude: 19.216056, longitude: 109.358586}, + {name: "保亭黎族苗族自治县", code: 469035, keyword: "保亭黎族苗族自治县BAOTINGLIZUMIAOZUZIZHIXIAN", latitude: 18.597592, longitude: 109.656113}, + {name: "巴中市", code: 511900, keyword: "巴中BAZHONG", latitude: 31.869189, longitude: 106.757916}, + {name: "毕节市", code: 522400, keyword: "毕节BIJIE", latitude: 27.302612, longitude: 105.300492}, + {name: "保山市", code: 530500, keyword: "保山BAOSHAN", latitude: 25.120489, longitude: 99.177996}, + {name: "宝鸡市", code: 610300, keyword: "宝鸡BAOJI", latitude: 34.364081, longitude: 107.170645}, + {name: "白银市", code: 620400, keyword: "白银BAIYIN", latitude: 36.546682, longitude: 104.171241}, + {name: "博尔塔拉蒙古自治州", code: 652700, keyword: "博尔塔拉蒙古自治州BOERTALAMENGGUZIZHIZHOU", latitude: 44.913651, longitude: 82.052436}, + {name: "巴音郭楞蒙古自治州", code: 652800, keyword: "巴音郭楞蒙古自治州BAYINGUOLENGMENGGUZIZHIZHOU", latitude: 41.771362, longitude: 86.121688} + ] + }, + { + letter: "C", + data: [ + {name: "承德市", code: 130800, keyword: "承德CHENGDE", latitude: 40.992521, longitude: 117.933822}, + {name: "沧州市", code: 130900, keyword: "沧州CANGZHOU", latitude: 38.297615, longitude: 116.863806}, + {name: "长治市", code: 140400, keyword: "长治CHANGZHI", latitude: 36.201664, longitude: 113.120292}, + {name: "赤峰市", code: 150400, keyword: "赤峰CHIFENG", latitude: 42.297112, longitude: 118.930761}, + {name: "朝阳市", code: 211300, keyword: "朝阳CHAOYANG", latitude: 41.571828, longitude: 120.446163}, + {name: "长春市", code: 220100, keyword: "长春CHANGCHUN", latitude: 43.898338, longitude: 125.313642}, + {name: "常州市", code: 320400, keyword: "常州CHANGZHOU", latitude: 31.771397, longitude: 119.981861}, + {name: "滁州市", code: 341100, keyword: "滁州CHUZHOU", latitude: 32.317351, longitude: 118.32457}, + {name: "池州市", code: 341700, keyword: "池州CHIZHOU", latitude: 30.660019, longitude: 117.494477}, + {name: "长沙市", code: 430100, keyword: "长沙CHANGSHA", latitude: 28.213478, longitude: 112.979353}, + {name: "常德市", code: 430700, keyword: "常德CHANGDE", latitude: 29.012149, longitude: 111.653718}, + {name: "郴州市", code: 431000, keyword: "郴州CHENZHOU", latitude: 25.782264, longitude: 113.037704}, + {name: "潮州市", code: 445100, keyword: "潮州CHAOZHOU", latitude: 23.661812, longitude: 116.630076}, + {name: "崇左市", code: 451400, keyword: "崇左CHONGZUO", latitude: 22.415455, longitude: 107.357322}, + {name: "澄迈县", code: 469027, keyword: "澄迈县CHENGMAIXIAN", latitude: 19.693135, longitude: 109.996736}, + {name: "昌江黎族自治县", code: 469031, keyword: "昌江黎族自治县CHANGJIANGLIZUZIZHIXIAN", latitude: 19.222483, longitude: 109.0113}, + {name: "成都市", code: 510100, keyword: "成都CHENGDU", latitude: 30.679943, longitude: 104.067923}, + {name: "楚雄彝族自治州", code: 532300, keyword: "楚雄彝族自治州CHUXIONGYIZUZIZHIZHOU", latitude: 25.066356, longitude: 101.529382}, + {name: "昌都地区", code: 542100, keyword: "昌都地区CHANGDUDIQU", latitude: 31.140576, longitude: 97.185582}, + {name: "昌吉回族自治州", code: 652300, keyword: "昌吉回族自治州CHANGJIHUIZUZIZHIZHOU", latitude: 44.007058, longitude: 87.296038} + ] + }, + { + letter: "D", + data: [ + {name: "大同市", code: 140200, keyword: "大同DATONG", latitude: 40.113744, longitude: 113.290509}, + {name: "大连市", code: 210200, keyword: "大连DALIAN", latitude: 38.94871, longitude: 121.593478}, + {name: "丹东市", code: 210600, keyword: "丹东DANDONG", latitude: 40.129023, longitude: 124.338543}, + {name: "大庆市", code: 230600, keyword: "大庆DAQING", latitude: 46.596709, longitude: 125.02184}, + {name: "大兴安岭地区", code: 232700, keyword: "大兴安岭地区DAXINGANLINGDIQU", latitude: 51.991789, longitude: 124.196104}, + {name: "东营市", code: 370500, keyword: "东营DONGYING", latitude: 37.487121, longitude: 118.583926}, + {name: "德州市", code: 371400, keyword: "德州DEZHOU", latitude: 37.460826, longitude: 116.328161}, + {name: "东莞市", code: 441900, keyword: "东莞DONGGUAN", latitude: 23.043024, longitude: 113.763434}, + {name: "儋州市", code: 469003, keyword: "儋州DANZHOU", latitude: 19.571153, longitude: 109.413973}, + {name: "东方市", code: 469007, keyword: "东方DONGFANG", latitude: 18.998161, longitude: 108.85101}, + {name: "定安县", code: 469025, keyword: "定安县DINGANXIAN", latitude: 19.490991, longitude: 110.32009}, + {name: "德阳市", code: 510600, keyword: "德阳DEYANG", latitude: 31.13114, longitude: 104.402398}, + {name: "达州市", code: 511700, keyword: "达州DAZHOU", latitude: 31.214199, longitude: 107.494973}, + {name: "大理白族自治州", code: 532900, keyword: "大理白族自治州DALIBAIZUZIZHIZHOU", latitude: 25.5969, longitude: 100.223675}, + {name: "德宏傣族景颇族自治州", code: 533100, keyword: "德宏傣族景颇族自治州DEHONGDAIZUJINGPOZUZIZHIZHOU", latitude: 24.44124, longitude: 98.589434}, + {name: "迪庆藏族自治州", code: 533400, keyword: "迪庆藏族自治州DIQINGCANGZUZIZHIZHOU", latitude: 27.831029, longitude: 99.713682}, + {name: "定西市", code: 621100, keyword: "定西DINGXI", latitude: 35.586056, longitude: 104.626638} + ] + }, + { + letter: "E", + data: [ + {name: "鄂尔多斯市", code: 150600, keyword: "鄂尔多斯EERDUOSI", latitude: 39.81649, longitude: 109.993706}, + {name: "鄂州市", code: 420700, keyword: "鄂州EZHOU", latitude: 30.384439, longitude: 114.895594}, + {name: "恩施土家族苗族自治州", code: 422800, keyword: "恩施土家族苗族自治州ENSHITUJIAZUMIAOZUZIZHIZHOU", latitude: 30.308978, longitude: 109.517433} + ] + }, + { + letter: "F", + data: [ + {name: "抚顺市", code: 210400, keyword: "抚顺FUSHUN", latitude: 41.877304, longitude: 123.92982}, + {name: "阜新市", code: 210900, keyword: "阜新FUXIN", latitude: 42.01925, longitude: 121.660822}, + {name: "阜阳市", code: 341200, keyword: "阜阳FUYANG", latitude: 32.901211, longitude: 115.820932}, + {name: "福州市", code: 350100, keyword: "福州FUZHOU", latitude: 26.047125, longitude: 119.330221}, + {name: "抚州市", code: 361000, keyword: "抚州FUZHOU", latitude: 27.954545, longitude: 116.360919}, + {name: "佛山市", code: 440600, keyword: "佛山FUSHAN", latitude: 23.035095, longitude: 113.134026}, + {name: "防城港市", code: 450600, keyword: "防城港FANGCHENGGANG", latitude: 21.617398, longitude: 108.351791} + ] + }, + { + letter: "G", + data: [ + {name: "赣州市", code: 360700, keyword: "赣州GANZHOU", latitude: 25.845296, longitude: 114.935909}, + {name: "广州市", code: 440100, keyword: "广州GUANGZHOU", latitude: 23.120049, longitude: 113.30765}, + {name: "桂林市", code: 450300, keyword: "桂林GUILIN", latitude: 25.262901, longitude: 110.26092}, + {name: "贵港市", code: 450800, keyword: "贵港GUIGANG", latitude: 23.103373, longitude: 109.613708}, + {name: "广元市", code: 510800, keyword: "广元GUANGYUAN", latitude: 32.44104, longitude: 105.819687}, + {name: "广安市", code: 511600, keyword: "广安GUANGAN", latitude: 30.463984, longitude: 106.63572}, + {name: "甘孜藏族自治州", code: 513300, keyword: "甘孜藏族自治州GANZICANGZUZIZHIZHOU", latitude: 30.055144, longitude: 101.969232}, + {name: "贵阳市", code: 520100, keyword: "贵阳GUIYANG", latitude: 26.629907, longitude: 106.709177}, + {name: "甘南藏族自治州", code: 623000, keyword: "甘南藏族自治州GANNANCANGZUZIZHIZHOU", latitude: 34.992211, longitude: 102.917442}, + {name: "果洛藏族自治州", code: 632600, keyword: "果洛藏族自治州GUOLUOCANGZUZIZHIZHOU", latitude: 34.480485, longitude: 100.223723}, + {name: "固原市", code: 640400, keyword: "固原GUYUAN", latitude: 36.021523, longitude: 106.285268} + ] + }, + { + letter: "H", + data: [ + {name: "邯郸市", code: 130400, keyword: "邯郸HANDAN", latitude: 36.609308, longitude: 114.482694}, + {name: "衡水市", code: 131100, keyword: "衡水HENGSHUI", latitude: 37.746929, longitude: 115.686229}, + {name: "呼和浩特市", code: 150100, keyword: "呼和浩特HUHEHAOTE", latitude: 40.828319, longitude: 111.660351}, + {name: "呼伦贝尔市", code: 150700, keyword: "呼伦贝尔HULUNBEIER", latitude: 49.201636, longitude: 119.760822}, + {name: "葫芦岛市", code: 211400, keyword: "葫芦岛HULUDAO", latitude: 40.74303, longitude: 120.860758}, + {name: "哈尔滨市", code: 230100, keyword: "哈尔滨HAERBIN", latitude: 45.773225, longitude: 126.657717}, + {name: "鹤岗市", code: 230400, keyword: "鹤岗HEGANG", latitude: 47.338666, longitude: 130.292472}, + {name: "黑河市", code: 231100, keyword: "黑河HEIHE", latitude: 50.25069, longitude: 127.50083}, + {name: "淮安市", code: 320800, keyword: "淮安HUAIAN", latitude: 33.606513, longitude: 119.030186}, + {name: "杭州市", code: 330100, keyword: "杭州HANGZHOU", latitude: 30.259244, longitude: 120.219375}, + {name: "湖州市", code: 330500, keyword: "湖州HUZHOU", latitude: 30.877925, longitude: 120.137243}, + {name: "合肥市", code: 340100, keyword: "合肥HEFEI", latitude: 31.866942, longitude: 117.282699}, + {name: "淮南市", code: 340400, keyword: "淮南HUAINAN", latitude: 32.642812, longitude: 117.018639}, + {name: "淮北市", code: 340600, keyword: "淮北HUAIBEI", latitude: 33.960023, longitude: 116.791447}, + {name: "黄山市", code: 341000, keyword: "黄山HUANGSHAN", latitude: 29.734435, longitude: 118.29357}, + {name: "菏泽市", code: 371700, keyword: "菏泽HEZE", latitude: 35.26244, longitude: 115.46336}, + {name: "鹤壁市", code: 410600, keyword: "鹤壁HEBI", latitude: 35.755426, longitude: 114.29777}, + {name: "黄石市", code: 420200, keyword: "黄石HUANGSHI", latitude: 30.216127, longitude: 115.050683}, + {name: "黄冈市", code: 421100, keyword: "黄冈HUANGGANG", latitude: 30.446109, longitude: 114.906618}, + {name: "衡阳市", code: 430400, keyword: "衡阳HENGYANG", latitude: 26.898164, longitude: 112.583819}, + {name: "怀化市", code: 431200, keyword: "怀化HUAIHUA", latitude: 27.557483, longitude: 109.986959}, + {name: "惠州市", code: 441300, keyword: "惠州HUIZHOU", latitude: 23.11354, longitude: 114.410658}, + {name: "河源市", code: 441600, keyword: "河源HEYUAN", latitude: 23.757251, longitude: 114.713721}, + {name: "贺州市", code: 451100, keyword: "贺州HEZHOU", latitude: 24.411054, longitude: 111.552594}, + {name: "河池市", code: 451200, keyword: "河池HECHI", latitude: 24.699521, longitude: 108.069948}, + {name: "海口市", code: 460100, keyword: "海口HAIKOU", latitude: 20.022071, longitude: 110.330802}, + {name: "红河哈尼族彝族自治州", code: 532500, keyword: "红河哈尼族彝族自治州HONGHEHANIZUYIZUZIZHIZHOU", latitude: 23.367718, longitude: 103.384065}, + {name: "汉中市", code: 610700, keyword: "汉中HANZHONG", latitude: 33.081569, longitude: 107.045478}, + {name: "海东市", code: 632100, keyword: "海东HAIDONG", latitude: 36.51761, longitude: 102.085207}, + {name: "海北藏族自治州", code: 632200, keyword: "海北藏族自治州HAIBEICANGZUZIZHIZHOU", latitude: 36.960654, longitude: 100.879802}, + {name: "黄南藏族自治州", code: 632300, keyword: "黄南藏族自治州HUANGNANCANGZUZIZHIZHOU", latitude: 35.522852, longitude: 102.0076}, + {name: "海南藏族自治州", code: 632500, keyword: "海南藏族自治州HAINANCANGZUZIZHIZHOU", latitude: 36.284364, longitude: 100.624066}, + {name: "海西蒙古族藏族自治州", code: 632800, keyword: "海西蒙古族藏族自治州HAIXIMENGGUZUCANGZUZIZHIZHOU", latitude: 37.373799, longitude: 97.342625}, + {name: "哈密地区", code: 652200, keyword: "哈密地区HAMIDIQU", latitude: 42.858596, longitude: 93.528355}, + {name: "和田地区", code: 653200, keyword: "和田地区HETIANDIQU", latitude: 37.116774, longitude: 79.930239} + ] + }, + { + letter: "J", + data: [ + {name: "晋城市", code: 140500, keyword: "晋城JINCHENG", latitude: 35.499834, longitude: 112.867333}, + {name: "晋中市", code: 140700, keyword: "晋中JINZHONG", latitude: 37.693362, longitude: 112.738514}, + {name: "锦州市", code: 210700, keyword: "锦州JINZHOU", latitude: 41.130879, longitude: 121.147749}, + {name: "吉林市", code: 220200, keyword: "吉林JILIN", latitude: 43.871988, longitude: 126.564544}, + {name: "鸡西市", code: 230300, keyword: "鸡西JIXI", latitude: 45.32154, longitude: 130.941767}, + {name: "佳木斯市", code: 230800, keyword: "佳木斯JIAMUSI", latitude: 46.81378, longitude: 130.284735}, + {name: "嘉兴市", code: 330400, keyword: "嘉兴JIAXING", latitude: 30.773992, longitude: 120.760428}, + {name: "金华市", code: 330700, keyword: "金华JINHUA", latitude: 29.102899, longitude: 119.652576}, + {name: "景德镇市", code: 360200, keyword: "景德镇JINGDEZHEN", latitude: 29.303563, longitude: 117.186523}, + {name: "九江市", code: 360400, keyword: "九江JIUJIANG", latitude: 29.71964, longitude: 115.999848}, + {name: "吉安市", code: 360800, keyword: "吉安JIAN", latitude: 27.113848, longitude: 114.992039}, + {name: "济南市", code: 370100, keyword: "济南JINAN", latitude: 36.682785, longitude: 117.024967}, + {name: "济宁市", code: 370800, keyword: "济宁JINING", latitude: 35.402122, longitude: 116.600798}, + {name: "焦作市", code: 410800, keyword: "焦作JIAOZUO", latitude: 35.234608, longitude: 113.211836}, + {name: "荆门市", code: 420800, keyword: "荆门JINGMEN", latitude: 31.042611, longitude: 112.21733}, + {name: "荆州市", code: 421000, keyword: "荆州JINGZHOU", latitude: 30.332591, longitude: 112.241866}, + {name: "江门市", code: 440700, keyword: "江门JIANGMEN", latitude: 22.575117, longitude: 113.078125}, + {name: "揭阳市", code: 445200, keyword: "揭阳JIEYANG", latitude: 23.547999, longitude: 116.379501}, + {name: "嘉峪关市", code: 620200, keyword: "嘉峪关JIAYUGUAN", latitude: 39.802397, longitude: 98.281635}, + {name: "金昌市", code: 620300, keyword: "金昌JINCHANG", latitude: 38.516072, longitude: 102.208126}, + {name: "酒泉市", code: 620900, keyword: "酒泉JIUQUAN", latitude: 39.741474, longitude: 98.508415} + ] + }, + { + letter: "K", + data: [ + {name: "开封市", code: 410200, keyword: "开封KAIFENG", latitude: 34.801854, longitude: 114.351642}, + {name: "昆明市", code: 530100, keyword: "昆明KUNMING", latitude: 25.049153, longitude: 102.714601}, + {name: "克拉玛依市", code: 650200, keyword: "克拉玛依KELAMAYI", latitude: 45.594331, longitude: 84.88118}, + {name: "克孜勒苏柯尔克孜自治州", code: 653000, keyword: "克孜勒苏柯尔克孜自治州KEZILESUKEERKEZIZIZHIZHOU", latitude: 39.750346, longitude: 76.137564} + ] + }, + { + letter: "L", + data: [ + {name: "廊坊市", code: 131000, keyword: "廊坊LANGFANG", latitude: 39.518611, longitude: 116.703602}, + {name: "临汾市", code: 141000, keyword: "临汾LINFEN", latitude: 36.099745, longitude: 111.538788}, + {name: "吕梁市", code: 141100, keyword: "吕梁LVLIANG", latitude: 37.527316, longitude: 111.143157}, + {name: "辽阳市", code: 211000, keyword: "辽阳LIAOYANG", latitude: 41.273339, longitude: 123.172451}, + {name: "辽源市", code: 220400, keyword: "辽源LIAOYUAN", latitude: 42.923303, longitude: 125.133686}, + {name: "连云港市", code: 320700, keyword: "连云港LIANYUNGANG", latitude: 34.601549, longitude: 119.173872}, + {name: "丽水市", code: 331100, keyword: "丽水LISHUI", latitude: 28.4563, longitude: 119.929576}, + {name: "六安市", code: 341500, keyword: "六安LIUAN", latitude: 31.755558, longitude: 116.505253}, + {name: "龙岩市", code: 350800, keyword: "龙岩LONGYAN", latitude: 25.078685, longitude: 117.017997}, + {name: "莱芜市", code: 371200, keyword: "莱芜LAIWU", latitude: 36.233654, longitude: 117.684667}, + {name: "临沂市", code: 371300, keyword: "临沂LINYI", latitude: 35.072409, longitude: 118.340768}, + {name: "聊城市", code: 371500, keyword: "聊城LIAOCHENG", latitude: 36.455829, longitude: 115.986869}, + {name: "洛阳市", code: 410300, keyword: "洛阳LUOYANG", latitude: 34.657368, longitude: 112.447525}, + {name: "漯河市", code: 411100, keyword: "漯河LEIHE", latitude: 33.576279, longitude: 114.046061}, + {name: "娄底市", code: 431300, keyword: "娄底LOUDI", latitude: 27.741073, longitude: 111.996396}, + {name: "柳州市", code: 450200, keyword: "柳州LIUZHOU", latitude: 24.329053, longitude: 109.422402}, + {name: "来宾市", code: 451300, keyword: "来宾LAIBIN", latitude: 23.741166, longitude: 109.231817}, + {name: "临高县", code: 469028, keyword: "临高县LINGAOXIAN", latitude: 19.805922, longitude: 109.724101}, + {name: "乐东黎族自治县", code: 469033, keyword: "乐东黎族自治县LEDONGLIZUZIZHIXIAN", latitude: 18.658614, longitude: 109.062698}, + {name: "陵水黎族自治县", code: 469034, keyword: "陵水黎族自治县LINGSHUILIZUZIZHIXIAN", latitude: 18.575985, longitude: 109.948661}, + {name: "泸州市", code: 510500, keyword: "泸州LUZHOU", latitude: 28.89593, longitude: 105.44397}, + {name: "乐山市", code: 511100, keyword: "乐山LESHAN", latitude: 29.600958, longitude: 103.760824}, + {name: "凉山彝族自治州", code: 513400, keyword: "凉山彝族自治州LIANGSHANYIZUZIZHIZHOU", latitude: 27.892393, longitude: 102.259591}, + {name: "六盘水市", code: 520200, keyword: "六盘水LIUPANSHUI", latitude: 26.591866, longitude: 104.852087}, + {name: "丽江市", code: 530700, keyword: "丽江LIJIANG", latitude: 26.875351, longitude: 100.229628}, + {name: "临沧市", code: 530900, keyword: "临沧LINCANG", latitude: 23.887806, longitude: 100.092613}, + {name: "拉萨市", code: 540100, keyword: "拉萨LASA", latitude: 29.662557, longitude: 91.111891}, + {name: "林芝地区", code: 542600, keyword: "林芝地区LINZHIDIQU", latitude: 29.666941, longitude: 94.349985}, + {name: "兰州市", code: 620100, keyword: "兰州LANZHOU", latitude: 36.064226, longitude: 103.823305}, + {name: "陇南市", code: 621200, keyword: "陇南LONGNAN", latitude: 33.39448, longitude: 104.934573}, + {name: "临夏回族自治州", code: 622900, keyword: "临夏回族自治州LINXIAHUIZUZIZHIZHOU", latitude: 35.598514, longitude: 103.215249} + ] + }, + { + letter: "M", + data: [ + {name: "牡丹江市", code: 231000, keyword: "牡丹江MUDANJIANG", latitude: 44.588521, longitude: 129.608035}, + {name: "马鞍山市", code: 340500, keyword: "马鞍山MAANSHAN", latitude: 31.688528, longitude: 118.515882}, + {name: "茂名市", code: 440900, keyword: "茂名MAOMING", latitude: 21.668226, longitude: 110.931245}, + {name: "梅州市", code: 441400, keyword: "梅州MEIZHOU", latitude: 24.304571, longitude: 116.126403}, + {name: "绵阳市", code: 510700, keyword: "绵阳MIANYANG", latitude: 31.504701, longitude: 104.705519}, + {name: "眉山市", code: 511400, keyword: "眉山MEISHAN", latitude: 30.061115, longitude: 103.84143} + ] + }, + { + letter: "N", + data: [ + {name: "南京市", code: 320100, keyword: "南京NANJING", latitude: 32.057236, longitude: 118.778074}, + {name: "南通市", code: 320600, keyword: "南通NANTONG", latitude: 32.014665, longitude: 120.873801}, + {name: "宁波市", code: 330200, keyword: "宁波NINGBO", latitude: 29.885259, longitude: 121.579006}, + {name: "南平市", code: 350700, keyword: "南平NANPING", latitude: 26.643626, longitude: 118.181883}, + {name: "宁德市", code: 350900, keyword: "宁德NINGDE", latitude: 26.656527, longitude: 119.542082}, + {name: "南昌市", code: 360100, keyword: "南昌NANCHANG", latitude: 28.689578, longitude: 115.893528}, + {name: "南阳市", code: 411300, keyword: "南阳NANYANG", latitude: 33.01142, longitude: 112.542842}, + {name: "南宁市", code: 450100, keyword: "南宁NANNING", latitude: 22.806493, longitude: 108.297234}, + {name: "内江市", code: 511000, keyword: "内江NAJIANG", latitude: 29.599462, longitude: 105.073056}, + {name: "南充市", code: 511300, keyword: "南充NANCHONG", latitude: 30.800965, longitude: 106.105554}, + {name: "怒江傈僳族自治州", code: 533300, keyword: "怒江傈僳族自治州NUJIANGLISUZUZIZHIZHOU", latitude: 25.860677, longitude: 98.859932}, + {name: "那曲地区", code: 542400, keyword: "那曲地区NAQUDIQU", latitude: 31.48068, longitude: 92.067018} + ] + }, + { + letter: "P", + data: [ + {name: "盘锦市", code: 211100, keyword: "盘锦PANJIN", latitude: 41.141248, longitude: 122.073228}, + {name: "莆田市", code: 350300, keyword: "莆田PUTIAN", latitude: 25.44845, longitude: 119.077731}, + {name: "萍乡市", code: 360300, keyword: "萍乡PINGXIANG", latitude: 27.639544, longitude: 113.859917}, + {name: "平顶山市", code: 410400, keyword: "平顶山PINGDINGSHAN", latitude: 33.745301, longitude: 113.300849}, + {name: "濮阳市", code: 410900, keyword: "濮阳PUYANG", latitude: 35.753298, longitude: 115.026627}, + {name: "攀枝花市", code: 510400, keyword: "攀枝花PANZHIHUA", latitude: 26.587571, longitude: 101.722423}, + {name: "普洱市", code: 530800, keyword: "普洱PUER", latitude: 22.788778, longitude: 100.980058}, + {name: "平凉市", code: 620800, keyword: "平凉PINGLIANG", latitude: 35.55011, longitude: 106.688911} + ] + }, + { + letter: "Q", + data: [ + {name: "秦皇岛市", code: 130300, keyword: "秦皇岛QINHUANGDAO", latitude: 39.945462, longitude: 119.604368}, + {name: "齐齐哈尔市", code: 230200, keyword: "齐齐哈尔QIQIHAER", latitude: 47.3477, longitude: 123.987289}, + {name: "七台河市", code: 230900, keyword: "七台河QITAIHE", latitude: 45.775005, longitude: 131.019048}, + {name: "衢州市", code: 330800, keyword: "衢州QUZHOU", latitude: 28.95691, longitude: 118.875842}, + {name: "泉州市", code: 350500, keyword: "泉州QUANZHOU", latitude: 24.901652, longitude: 118.600362}, + {name: "青岛市", code: 370200, keyword: "青岛QINGDAO", latitude: 36.105215, longitude: 120.384428}, + {name: "潜江市", code: 429005, keyword: "潜江QIANJIANG", latitude: 30.343116, longitude: 112.768768}, + {name: "清远市", code: 441800, keyword: "清远QINGYUAN", latitude: 23.698469, longitude: 113.040773}, + {name: "钦州市", code: 450700, keyword: "钦州QINZHOU", latitude: 21.97335, longitude: 108.638798}, + {name: "琼海市", code: 469002, keyword: "琼海QIONGHAI", latitude: 19.21483, longitude: 110.414359}, + {name: "琼中黎族苗族自治县", code: 469036, keyword: "琼中黎族苗族自治县QIONGZHONGLIZUMIAOZUZIZHIXIAN", latitude: 19.039771, longitude: 109.861849}, + {name: "黔西南布依族苗族自治州", code: 522300, keyword: "黔西南布依族苗族自治州QIANXINANBUYIZUMIAOZUZIZHIZHOU", latitude: 25.095148, longitude: 104.900558}, + {name: "黔东南苗族侗族自治州", code: 522600, keyword: "黔东南苗族侗族自治州QIANDONGNANMIAOZUDONGZUZIZHIZHOU", latitude: 26.583992, longitude: 107.985353}, + {name: "黔南布依族苗族自治州", code: 522700, keyword: "黔南布依族苗族自治州QIANNANBUYIZUMIAOZUZIZHIZHOU", latitude: 26.264536, longitude: 107.523205}, + {name: "曲靖市", code: 530300, keyword: "曲靖QUJING", latitude: 25.520758, longitude: 103.782539}, + {name: "庆阳市", code: 621000, keyword: "庆阳QINGYANG", latitude: 35.726801, longitude: 107.644227} + ] + }, + { + letter: "R", + data: [ + {name: "日照市", code: 371100, keyword: "日照RIZHAO", latitude: 35.420225, longitude: 119.50718}, + {name: "日喀则地区", code: 542300, keyword: "日喀则地区RIKAZEDIQU", latitude: 29.269023, longitude: 88.891486} + ] + }, + { + letter: "S", + data: [ + {name: "石家庄市", code: 130100, keyword: "石家庄SHIJIAZHUANG", latitude: 38.048958, longitude: 114.522082}, + {name: "朔州市", code: 140600, keyword: "朔州SHUOZHOU", latitude: 39.337672, longitude: 112.479928}, + {name: "沈阳市", code: 210100, keyword: "沈阳SHENYANG", latitude: 41.808645, longitude: 123.432791}, + {name: "四平市", code: 220300, keyword: "四平SIPING", latitude: 43.175525, longitude: 124.391382}, + {name: "松原市", code: 220700, keyword: "松原SONGYUAN", latitude: 45.136049, longitude: 124.832995}, + {name: "双鸭山市", code: 230500, keyword: "双鸭山SHUANGYASHAN", latitude: 46.655102, longitude: 131.171402}, + {name: "绥化市", code: 231200, keyword: "绥化SUIHUA", latitude: 46.646064, longitude: 126.989095}, + {name: "上海市", code: 310100, keyword: "上海SHANGHAI", latitude: 31.249162, longitude: 121.487899}, + {name: "苏州市", code: 320500, keyword: "苏州SUZHOU", latitude: 31.317987, longitude: 120.619907}, + {name: "宿迁市", code: 321300, keyword: "宿迁SUQIAN", latitude: 33.95205, longitude: 118.296893}, + {name: "绍兴市", code: 330600, keyword: "绍兴SHAOXING", latitude: 30.002365, longitude: 120.592467}, + {name: "宿州市", code: 341300, keyword: "宿州SUZHOU", latitude: 33.636772, longitude: 116.988692}, + {name: "三明市", code: 350400, keyword: "三明SANMING", latitude: 26.270835, longitude: 117.642194}, + {name: "上饶市", code: 361100, keyword: "上饶SHANGRAO", latitude: 28.457623, longitude: 117.955464}, + {name: "三门峡市", code: 411200, keyword: "三门峡SANMENXIA", latitude: 34.78332, longitude: 111.181262}, + {name: "商丘市", code: 411400, keyword: "商丘SHANGQIU", latitude: 34.438589, longitude: 115.641886}, + {name: "十堰市", code: 420300, keyword: "十堰SHIYAN", latitude: 32.636994, longitude: 110.801229}, + {name: "随州市", code: 421300, keyword: "随州SUIZHOU", latitude: 31.717858, longitude: 113.379358}, + {name: "神农架林区", code: 429021, keyword: "神农架林区SHENNONGJIALINQU", latitude: 31.595768, longitude: 110.487231}, + {name: "邵阳市", code: 430500, keyword: "邵阳SHAOYANG", latitude: 27.236811, longitude: 111.461525}, + {name: "韶关市", code: 440200, keyword: "韶关SHAOGUAN", latitude: 24.80296, longitude: 113.594461}, + {name: "深圳市", code: 440300, keyword: "深圳SHENCHOU", latitude: 22.546054, longitude: 114.025974}, + {name: "汕头市", code: 440500, keyword: "汕头SHANTOU", latitude: 23.383908, longitude: 116.72865}, + {name: "汕尾市", code: 441500, keyword: "汕尾SHANWEI", latitude: 22.778731, longitude: 115.372924}, + {name: "三亚市", code: 460200, keyword: "三亚SANYA", latitude: 18.257776, longitude: 109.522771}, + {name: "遂宁市", code: 510900, keyword: "遂宁SUINING", latitude: 30.557491, longitude: 105.564888}, + {name: "山南地区", code: 542200, keyword: "山南地区SHANNANDIQU", latitude: 29.229027, longitude: 91.750644}, + {name: "商洛市", code: 611000, keyword: "商洛SHANGLUO", latitude: 33.873907, longitude: 109.934208}, + {name: "石嘴山市", code: 640200, keyword: "石嘴山SHIZUISHAN", latitude: 39.020223, longitude: 106.379337}, + {name: "石河子市", code: 659001, keyword: "石河子SHIHEZI", latitude: 44.308259, longitude: 86.041865} + ] + }, + { + letter: "T", + data: [ + {name: "天津市", code: 120100, keyword: "天津TIANJIN", latitude: 39.14393, longitude: 117.210813}, + {name: "唐山市", code: 130200, keyword: "唐山TANGSHAN", latitude: 39.650531, longitude: 118.183451}, + {name: "太原市", code: 140100, keyword: "太原TAIYUAN", latitude: 37.890277, longitude: 112.550864}, + {name: "通辽市", code: 150500, keyword: "通辽TONGLIAO", latitude: 43.633756, longitude: 122.260363}, + {name: "铁岭市", code: 211200, keyword: "铁岭TIELING", latitude: 42.299757, longitude: 123.85485}, + {name: "通化市", code: 220500, keyword: "通化TONGHUA", latitude: 41.736397, longitude: 125.94265}, + {name: "泰州市", code: 321200, keyword: "泰州TAIZHOU", latitude: 32.476053, longitude: 119.919606}, + {name: "台州市", code: 331000, keyword: "台州TAIZHOU", latitude: 28.668283, longitude: 121.440613}, + {name: "铜陵市", code: 340700, keyword: "铜陵TONGLING", latitude: 30.94093, longitude: 117.819429}, + {name: "泰安市", code: 370900, keyword: "泰安TAIAN", latitude: 36.188078, longitude: 117.089415}, + {name: "天门市", code: 429006, keyword: "天门TIANMEN", latitude: 30.649047, longitude: 113.12623}, + {name: "屯昌县", code: 469026, keyword: "屯昌县TUNCHANGXIAN", latitude: 19.347749, longitude: 110.063364}, + {name: "铜仁市", code: 522200, keyword: "铜仁TONGREN", latitude: 27.726271, longitude: 109.196161}, + {name: "铜川市", code: 610200, keyword: "铜川TONGCHUAN", latitude: 34.908368, longitude: 108.968067}, + {name: "天水市", code: 620500, keyword: "天水TIANSHUI", latitude: 34.584319, longitude: 105.736932}, + {name: "吐鲁番地区", code: 652100, keyword: "吐鲁番地区TULUFANDIQU", latitude: 42.96047, longitude: 89.181595}, + {name: "塔城地区", code: 654200, keyword: "塔城地区TACHENGDIQU", latitude: 46.758684, longitude: 82.974881}, + {name: "图木舒克市", code: 659003, keyword: "图木舒克TUMUSHUKE", latitude: 39.889223, longitude: 79.198155} + ] + }, + { + letter: "W", + data: [ + {name: "乌海市", code: 150300, keyword: "乌海WUHAI", latitude: 39.683177, longitude: 106.831999}, + {name: "乌兰察布市", code: 150900, keyword: "乌兰察布WULANCHABU", latitude: 41.022363, longitude: 113.112846}, + {name: "无锡市", code: 320200, keyword: "无锡WUXI", latitude: 31.570037, longitude: 120.305456}, + {name: "温州市", code: 330300, keyword: "温州WENZHOU", latitude: 28.002838, longitude: 120.690635}, + {name: "芜湖市", code: 340200, keyword: "芜湖WUHU", latitude: 31.36602, longitude: 118.384108}, + {name: "潍坊市", code: 370700, keyword: "潍坊WEIFANG", latitude: 36.716115, longitude: 119.142634}, + {name: "威海市", code: 371000, keyword: "威海WEIHAI", latitude: 37.528787, longitude: 122.093958}, + {name: "武汉市", code: 420100, keyword: "武汉WUHAN", latitude: 30.581084, longitude: 114.3162}, + {name: "梧州市", code: 450400, keyword: "梧州WUZHOU", latitude: 23.485395, longitude: 111.305472}, + {name: "五指山市", code: 469001, keyword: "五指山WUZHISHAN", latitude: 18.831306, longitude: 109.51775}, + {name: "文昌市", code: 469005, keyword: "文昌WENCHANG", latitude: 19.750947, longitude: 110.780909}, + {name: "万宁市", code: 469006, keyword: "万宁WANNING", latitude: 18.839886, longitude: 110.292505}, + {name: "文山壮族苗族自治州", code: 532600, keyword: "文山壮族苗族自治州WENSHANZHUANGZUMIAOZUZIZHIZHOU", latitude: 23.401781, longitude: 104.089112}, + {name: "渭南市", code: 610500, keyword: "渭南WEINAN", latitude: 34.502358, longitude: 109.483933}, + {name: "武威市", code: 620600, keyword: "武威WUWEI", latitude: 37.933172, longitude: 102.640147}, + {name: "吴忠市", code: 640300, keyword: "吴忠WUZHONG", latitude: 37.993561, longitude: 106.208254}, + {name: "乌鲁木齐市", code: 650100, keyword: "乌鲁木齐WULUMUQI", latitude: 43.84038, longitude: 87.564988}, + {name: "五家渠市", code: 659004, keyword: "五家渠WUJIAQU", latitude: 44.368899, longitude: 87.565449} + ] + }, + { + letter: "X", + data: [ + {name: "邢台市", code: 130500, keyword: "邢台XINGTAI", latitude: 37.069531, longitude: 114.520487}, + {name: "忻州市", code: 140900, keyword: "忻州XINZHOU", latitude: 38.461031, longitude: 112.727939}, + {name: "兴安盟", code: 152200, keyword: "兴安盟XINGANMENG", latitude: 46.083757, longitude: 122.048167}, + {name: "锡林郭勒盟", code: 152500, keyword: "锡林郭勒盟XILINGUOLEMENG", latitude: 43.939705, longitude: 116.02734}, + {name: "徐州市", code: 320300, keyword: "徐州XUZHOU", latitude: 34.271553, longitude: 117.188107}, + {name: "宣城市", code: 341800, keyword: "宣城XUANCHENG", latitude: 30.951642, longitude: 118.752096}, + {name: "厦门市", code: 350200, keyword: "厦门XIAMEN", latitude: 24.489231, longitude: 118.103886}, + {name: "新余市", code: 360500, keyword: "新余XINYU", latitude: 27.822322, longitude: 114.947117}, + {name: "新乡市", code: 410700, keyword: "新乡XINXIANG", latitude: 35.307258, longitude: 113.91269}, + {name: "许昌市", code: 411000, keyword: "许昌XUCHANG", latitude: 34.02674, longitude: 113.835312}, + {name: "信阳市", code: 411500, keyword: "信阳XINYANG", latitude: 32.128582, longitude: 114.085491}, + {name: "襄阳市", code: 420600, keyword: "襄阳XIANGYANG", latitude: 32.094934, longitude: 112.176326}, + {name: "孝感市", code: 420900, keyword: "孝感XIAOGAN", latitude: 30.927955, longitude: 113.935734}, + {name: "咸宁市", code: 421200, keyword: "咸宁XIANNING", latitude: 29.880657, longitude: 114.300061}, + {name: "仙桃市", code: 429004, keyword: "仙桃XIANTAO", latitude: 30.293966, longitude: 113.387448}, + {name: "湘潭市", code: 430300, keyword: "湘潭XIANGTAN", latitude: 27.835095, longitude: 112.935556}, + {name: "湘西土家族苗族自治州", code: 433100, keyword: "湘西土家族苗族自治州XIANGXITUJIAZUMIAOZUZIZHIZHOU", latitude: 28.317951, longitude: 109.745746}, + {name: "西双版纳傣族自治州", code: 532800, keyword: "西双版纳傣族自治州XISHUANGBANNADAIZUZIZHIZHOU", latitude: 22.009433, longitude: 100.803038}, + {name: "西安市", code: 610100, keyword: "西安XIAN", latitude: 34.2778, longitude: 108.953098}, + {name: "咸阳市", code: 610400, keyword: "咸阳XIANYANG", latitude: 34.345373, longitude: 108.707509}, + {name: "西宁市", code: 630100, keyword: "西宁XINING", latitude: 36.640739, longitude: 101.767921}, + {name: "香港岛", code: 810100, keyword: "香港岛XIANGGANGDAO", latitude: 22.293586, longitude: 114.186124} + ] + }, + { + letter: "Y", + data: [ + {name: "阳泉市", code: 140300, keyword: "阳泉YANGQUAN", latitude: 37.869529, longitude: 113.569238}, + {name: "运城市", code: 140800, keyword: "运城YUNCHENG", latitude: 35.038859, longitude: 111.006854}, + {name: "营口市", code: 210800, keyword: "营口YINGKOU", latitude: 40.668651, longitude: 122.233391}, + {name: "延边朝鲜族自治州", code: 222400, keyword: "延边朝鲜族自治州YANBIANCHAOXIANZUZIZHIZHOU", latitude: 42.896414, longitude: 129.485902}, + {name: "伊春市", code: 230700, keyword: "伊春YICHUN", latitude: 47.734685, longitude: 128.910766}, + {name: "盐城市", code: 320900, keyword: "盐城YANCHENG", latitude: 33.379862, longitude: 120.148872}, + {name: "扬州市", code: 321000, keyword: "扬州YANGZHOU", latitude: 32.408505, longitude: 119.427778}, + {name: "鹰潭市", code: 360600, keyword: "鹰潭YINGTAN", latitude: 28.24131, longitude: 117.03545}, + {name: "宜春市", code: 360900, keyword: "宜春YICHUN", latitude: 27.81113, longitude: 114.400039}, + {name: "烟台市", code: 370600, keyword: "烟台YANTAI", latitude: 37.536562, longitude: 121.309555}, + {name: "宜昌市", code: 420500, keyword: "宜昌YICHANG", latitude: 30.732758, longitude: 111.310981}, + {name: "岳阳市", code: 430600, keyword: "岳阳YUEYANG", latitude: 29.378007, longitude: 113.146196}, + {name: "益阳市", code: 430900, keyword: "益阳YIYANG", latitude: 28.588088, longitude: 112.366547}, + {name: "永州市", code: 431100, keyword: "永州YONGZHOU", latitude: 26.435972, longitude: 111.614648}, + {name: "阳江市", code: 441700, keyword: "阳江YANGJIANG", latitude: 21.871517, longitude: 111.97701}, + {name: "云浮市", code: 445300, keyword: "云浮YUNFU", latitude: 22.937976, longitude: 112.050946}, + {name: "玉林市", code: 450900, keyword: "玉林YULIN", latitude: 22.643974, longitude: 110.151676}, + {name: "宜宾市", code: 511500, keyword: "宜宾YIBIN", latitude: 28.769675, longitude: 104.633019}, + {name: "雅安市", code: 511800, keyword: "雅安YAAN", latitude: 29.999716, longitude: 103.009356}, + {name: "玉溪市", code: 530400, keyword: "玉溪YUXI", latitude: 24.370447, longitude: 102.545068}, + {name: "延安市", code: 610600, keyword: "延安YANAN", latitude: 36.60332, longitude: 109.50051}, + {name: "榆林市", code: 610800, keyword: "榆林YULIN", latitude: 38.279439, longitude: 109.745926}, + {name: "玉树藏族自治州", code: 632700, keyword: "玉树藏族自治州YUSHUCANGZUZIZHIZHOU", latitude: 33.00624, longitude: 97.013316}, + {name: "银川市", code: 640100, keyword: "银川YINCHUAN", latitude: 38.502621, longitude: 106.206479}, + {name: "伊犁哈萨克自治州", code: 654000, keyword: "伊犁哈萨克自治州YILIHASAKEZIZHIZHOU", latitude: 43.922248, longitude: 81.297854} + ] + }, + { + letter: "Z", + data: [ + {name: "张家口市", code: 130700, keyword: "张家口ZHANGJIAKOU", latitude: 40.811188, longitude: 114.893782}, + {name: "镇江市", code: 321100, keyword: "镇江ZHENJIANG", latitude: 32.204409, longitude: 119.455835}, + {name: "舟山市", code: 330900, keyword: "舟山ZHOUSHAN", latitude: 30.03601, longitude: 122.169872}, + {name: "漳州市", code: 350600, keyword: "漳州ZHANGZHOU", latitude: 24.517065, longitude: 117.676205}, + {name: "淄博市", code: 370300, keyword: "淄博ZIBO", latitude: 36.804685, longitude: 118.059134}, + {name: "枣庄市", code: 370400, keyword: "枣庄ZAOZHUANG", latitude: 34.807883, longitude: 117.279305}, + {name: "郑州市", code: 410100, keyword: "郑州ZHENGZHOU", latitude: 34.75661, longitude: 113.649644}, + {name: "周口市", code: 411600, keyword: "周口ZHOUKOU", latitude: 33.623741, longitude: 114.654102}, + {name: "驻马店市", code: 411700, keyword: "驻马店ZHUMADIAN", latitude: 32.983158, longitude: 114.049154}, + {name: "株洲市", code: 430200, keyword: "株洲ZHUZHOU", latitude: 27.827433, longitude: 113.131695}, + {name: "张家界市", code: 430800, keyword: "张家界ZHANGJIAJIE", latitude: 29.124889, longitude: 110.48162}, + {name: "珠海市", code: 440400, keyword: "珠海ZHUHAI", latitude: 22.256915, longitude: 113.562447}, + {name: "湛江市", code: 440800, keyword: "湛江ZHANJIANG", latitude: 21.257463, longitude: 110.365067}, + {name: "肇庆市", code: 441200, keyword: "肇庆ZHAOQING", latitude: 23.078663, longitude: 112.479653}, + {name: "中山市", code: 442000, keyword: "中山ZHONGSHAN", latitude: 22.545178, longitude: 113.42206}, + {name: "重庆市", code: 500100, keyword: "重庆ZHONGQING", latitude: 29.544606, longitude: 106.530635}, + {name: "自贡市", code: 510300, keyword: "自贡ZIGONG", latitude: 29.359157, longitude: 104.776071}, + {name: "资阳市", code: 512000, keyword: "资阳ZIYANG", latitude: 30.132191, longitude: 104.63593}, + {name: "遵义市", code: 520300, keyword: "遵义ZUNYI", latitude: 27.699961, longitude: 106.93126}, + {name: "昭通市", code: 530600, keyword: "昭通ZHAOTONG", latitude: 27.340633, longitude: 103.725021}, + {name: "张掖市", code: 620700, keyword: "张掖ZHANGYE", latitude: 38.93932, longitude: 100.459892}, + {name: "中卫市", code: 640500, keyword: "中卫ZHONGWEI", latitude: 37.521124, longitude: 105.196754} + ] + } + ] +} \ No newline at end of file diff --git a/libs/md5.min.js b/libs/md5.min.js new file mode 100644 index 0000000..1456fcc --- /dev/null +++ b/libs/md5.min.js @@ -0,0 +1,2 @@ +!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((c=d(d(t,n),d(e,u)))<<(f=o)|c>>>32-f,r);var c,f}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function h(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return a(i(h(t=r(n)),8*t.length));var t}function u(n,t){return function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16 { + query.push(key + '=' + params[key]) + }) + query = url + query.join('&') + let sign = md5(query + sk) + return new Promise(function (resolve, reject) { + wx.request({ + url: `https://apis.map.qq.com${query}&sig=${sign}`, + success: res => { + if(res.statusCode == 200 && res.data && res.data.status == 0){ + resolve(res.data) + } else { + reject('数据错误') + } + }, + fail: err => { + reject('网络异常') + } + }) + }) +} + +function geocoder(latitude, longitude){ + let params = { location: `${latitude},${longitude}`, key } + return request(params, '/ws/geocoder/v1?') +} + +/** + * @param {*} keyword 用户输入的关键词(希望获取后续提示的关键词)必填 + * @param {*} region 限制城市范围:根据城市名称限制地域范围, 如,仅获取“广州市”范围内的提示内容 + * @param {*} latitude 定位坐标,传入后,若用户搜索关键词为类别词(如酒店、餐馆时),与此坐标距离近的地点将靠前显示,格式: location=lat,lng + * @param {*} longitude 定位坐标,传入后,若用户搜索关键词为类别词(如酒店、餐馆时),与此坐标距离近的地点将靠前显示,格式: location=lat,lng + */ +function suggestion(keyword, region, location){ + let params = { keyword, region, location: `${location.latitude},${location.longitude}`, region_fix: 1, page_size: 20, get_subpois: 0, key } + return request(params, '/ws/place/v1/suggestion?') +} + +//https://apis.map.qq.com/ws/place/v1/explore +function explore(location, radius, num, size){ + let params = { boundary: `nearby(${location.latitude},${location.longitude},${radius})`, page_index: num, page_size: size, key } + return request(params, '/ws/place/v1/explore?') +} +//骑行(bicycling)路线规划 +function bicycling(from, to){ + let params = { from: `${from.latitude},${from.longitude}`, to: `${to.latitude},${to.longitude}`, key } + return request(params, '/ws/direction/v1/bicycling?') +} +// 步行(walking)路线规划 +function walking(from, to){ + let params = { from: `${from.latitude},${from.longitude}`, to: `${to.latitude},${to.longitude}`, key } + return request(params, '/ws/direction/v1/walking?') +} +// 驾车(driving)路线规划;waypoints:途经点,格式:lat1,lng1;lat2,lng2;… 最大支持16个>>waypoints=39.951004,116.571980 +function driving(from, to, waypoints){ + let params = { from: `${from.latitude},${from.longitude}`, to: `${to.latitude},${to.longitude}`, key } + if(waypoints && Array.isArray(waypoints)){ + var points = '' + for (let index = 0; index < waypoints.length; index++) { + if(index == 0){ + points += waypoints[index].latitude + ',' + waypoints[index].longitude + } else { + points += ';' + waypoints[index].latitude + ',' + waypoints[index].longitude + } + params.waypoints = points + } + } + return request(params, '/ws/direction/v1/driving?') +} + +module.exports = { + key: key, + geocoder: geocoder, + suggestion: suggestion, + explore: explore, + bicycling: bicycling, + walking: walking, + driving: driving +} diff --git a/pages/elements/agent-item/index.js b/pages/elements/agent-item/index.js new file mode 100644 index 0000000..e2eab19 --- /dev/null +++ b/pages/elements/agent-item/index.js @@ -0,0 +1,55 @@ +const util = require('../../../utils/util') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + item: { type: Object, value: null } + }, + data: { + cateIndex: 0 + }, + methods: { + lookItem: function (e) { + wx.navigateTo({ url: `/xtends/proxysell/factory-detail/index?id=${this.data.item.paperMillId}`}) + }, + unflodItem: function(){ + this.setData({ ['item.fold']: !this.data.item.fold }) + }, + checkTag: function(e){ + var cateIndex = -1 + if(util.isEmpty(this.data.cateIndex)){ + cateIndex = e.currentTarget.dataset.ck + } else if(this.data.cateIndex != e.currentTarget.dataset.ck){ + cateIndex = e.currentTarget.dataset.ck + } + if(cateIndex >= 0){ + this.setData({ cateIndex }) + } + }, + saleGood: function(e){ + if (!app.userInfo) { + wx.navigateTo({ url: '/pages/login/index' }) + return + } + if(!this.data.item.isOperations){ + util.showToast(this.data.item.manageNotifyMessage) + return + } + if(util.isEmpty(this.data.cateIndex)){ + util.showToast('请选择一个纸品') + return + } + if(util.isEmpty(this.data.item.paperCategoryList[this.data.cateIndex].unitPrice)){ + util.showToast('该纸品暂无报价,无法卖货') + return + } + var categoryId = this.data.item.paperCategoryList[this.data.cateIndex].categoryId + wx.navigateTo({ url: '/xtends/proxysell/appointment/index?id=' + this.data.item.paperMillId + '&categoryId=' + categoryId }) + } + } + +}) \ No newline at end of file diff --git a/pages/elements/agent-item/index.json b/pages/elements/agent-item/index.json new file mode 100644 index 0000000..1d2b28b --- /dev/null +++ b/pages/elements/agent-item/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-button": "/components/button/index", + "van-image": "/components/image/index" + } +} \ No newline at end of file diff --git a/pages/elements/agent-item/index.wxml b/pages/elements/agent-item/index.wxml new file mode 100644 index 0000000..338aa28 --- /dev/null +++ b/pages/elements/agent-item/index.wxml @@ -0,0 +1,84 @@ + + + + + + + {{item.name}} + + {{item.locProvinceName + item.locCityName + item.locDistrictName}} + | + 已代卖:{{item.cumulativeWeight}}吨 + | + 昨日排队:{{item.yesterdayTotalQuantity}}辆 + 昨日排队:-- + + + + 代卖费: + {{formate.formatePrice(item.proxypaySurcharge)}} + + + 纸厂账期: + {{item.foreignPaybackIntever}}天 + + + + + + + + + + {{cateItem.categoryName}} + + {{priceItem(cateItem)}} + (已含补贴{{formate.formatePrice(cateItem.publicSubsidies)}}) + + 暂无报价 + + + 价格更新:{{item.priceDate}} + + + {{formate.formatePrice(cateItem.floatingPrice)}} + 较昨日 + + + + {{formate.formatePrice(-cateItem.floatingPrice)}} + 较昨日 + + + - + - + + + + + + + + 我要卖货 + + + + {{item.fold ? '点击收起' : '查看全部' }}({{item.paperCategoryList.length}}) + + + + + + + + + + function priceItem(item) { + if(item.publicSubsidies && Number(item.publicSubsidies) > 0){ + var price = parseFloat(item.unitPrice) + parseFloat(item.publicSubsidies) + return (parseFloat(price) * 1000).toFixed(1) + '元/吨' + } + return (parseFloat(item.unitPrice) * 1000).toFixed(1) + '元/吨' + } + module.exports = priceItem; + \ No newline at end of file diff --git a/pages/elements/agent-item/index.wxss b/pages/elements/agent-item/index.wxss new file mode 100644 index 0000000..521af89 --- /dev/null +++ b/pages/elements/agent-item/index.wxss @@ -0,0 +1,31 @@ +/* pages/mall/shops/index.wxss */ +.item-content { + background: rgba(255, 255, 255, 1); + padding: 32rpx; +} + +.item-cate { + flex: 5; + padding: 10rpx 30rpx; + border-radius: 10rpx; + border: 1rpx solid #f3f3f3; + background-color: #f3f3f3; +} + +.cate-tag { + background-color: #e6f7ff; + border: 1rpx solid #1890ff; +} + +.image-load { + width: 54px; + height: 54px; + display: flex; + align-items: center; + justify-content: center; +} + +.transform { + transform-origin: 50% 50%; + transform: rotate(180deg); +} diff --git a/pages/elements/chain-item/index.js b/pages/elements/chain-item/index.js new file mode 100644 index 0000000..95f8a8c --- /dev/null +++ b/pages/elements/chain-item/index.js @@ -0,0 +1,64 @@ +const util = require('../../../utils/util') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + item: { type: Object, value: null }, + frist: { type: Boolean, value: true } + }, + data: { + cateIndex: 0 + }, + methods: { + lookItem: function (e) { + wx.navigateTo({ url: `/xtends/proxysell/factory-detail/index?id=${this.data.item.paperMillId}`}) + }, + unflodItem: function(){ + this.setData({ ['item.fold']: !this.data.item.fold }) + }, + checkTag: function(e){ + var cateIndex = -1 + if(util.isEmpty(this.data.cateIndex)){ + cateIndex = e.currentTarget.dataset.ck + } else if(this.data.cateIndex != e.currentTarget.dataset.ck){ + cateIndex = e.currentTarget.dataset.ck + } + if(cateIndex >= 0){ + this.setData({ cateIndex }) + } + this.data.item.cateIndex = e.currentTarget.dataset.ck + var that = this + wx.navigateTo({ + url: `/pages/process/order-appointment/index?type=1&id=${this.data.item.supplyChainId}`, + success: function(res) { + res.eventChannel.emit('onParam', that.data.item) + } + }) + }, + saleGood: function(e){ + if (!app.userInfo) { + wx.navigateTo({ url: '/pages/login/index' }) + return + } + if(!this.data.item.isOperations){ + util.showToast(this.data.item.manageNotifyMessage) + return + } + if(util.isEmpty(this.data.cateIndex)){ + util.showToast('请选择一个纸品') + return + } + if(util.isEmpty(this.data.item.paperCategoryList[this.data.cateIndex].unitPrice)){ + util.showToast('该纸品暂无报价,无法卖货') + return + } + var categoryId = this.data.item.paperCategoryList[this.data.cateIndex].categoryId + wx.navigateTo({ url: '/xtends/proxysell/appointment/index?id=' + this.data.item.paperMillId + '&categoryId=' + categoryId }) + } + } + +}) \ No newline at end of file diff --git a/pages/elements/chain-item/index.json b/pages/elements/chain-item/index.json new file mode 100644 index 0000000..1d2b28b --- /dev/null +++ b/pages/elements/chain-item/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-button": "/components/button/index", + "van-image": "/components/image/index" + } +} \ No newline at end of file diff --git a/pages/elements/chain-item/index.wxml b/pages/elements/chain-item/index.wxml new file mode 100644 index 0000000..7199d77 --- /dev/null +++ b/pages/elements/chain-item/index.wxml @@ -0,0 +1,76 @@ + + + + + + + + {{item.paperMillName}} + + {{item.locDetail}} + | + 已代卖:{{item.volumeOfAgentSold}}吨 + | + 昨日排队:{{item.numberOfLinedUpYesterday}}辆 + 昨日排队:-- + + + + 代卖费: + {{formate.formatePrice(item.priceOfAgentSold)}} + + + 纸厂账期: + {{item.accountPeriod}}天 + + + + + + + + + + {{cateItem.displayName}} + + {{formate.formatePrice(cateItem.purchasePrice)}} + + 暂无报价 + + + 价格更新:{{cateItem.informationTime}} + + + {{formate.formatePrice(cateItem.floatingPrice)}} + 较昨日 + + + + {{formate.formatePrice(-cateItem.floatingPrice)}} + 较昨日 + + + - + - + + + + + + + {{item.fold ? '点击收起' : '查看全部' }}({{item.agentPaperCategoryList.length}}) + + + + + + + function priceItem(item) { + if(item.publicSubsidies && Number(item.publicSubsidies) > 0){ + var price = parseFloat(item.unitPrice) + parseFloat(item.publicSubsidies) + return (parseFloat(price) * 1000).toFixed(1) + '元/吨' + } + return (parseFloat(item.unitPrice) * 1000).toFixed(1) + '元/吨' + } + module.exports = priceItem; + \ No newline at end of file diff --git a/pages/elements/chain-item/index.wxss b/pages/elements/chain-item/index.wxss new file mode 100644 index 0000000..521af89 --- /dev/null +++ b/pages/elements/chain-item/index.wxss @@ -0,0 +1,31 @@ +/* pages/mall/shops/index.wxss */ +.item-content { + background: rgba(255, 255, 255, 1); + padding: 32rpx; +} + +.item-cate { + flex: 5; + padding: 10rpx 30rpx; + border-radius: 10rpx; + border: 1rpx solid #f3f3f3; + background-color: #f3f3f3; +} + +.cate-tag { + background-color: #e6f7ff; + border: 1rpx solid #1890ff; +} + +.image-load { + width: 54px; + height: 54px; + display: flex; + align-items: center; + justify-content: center; +} + +.transform { + transform-origin: 50% 50%; + transform: rotate(180deg); +} diff --git a/pages/elements/order-item/index.js b/pages/elements/order-item/index.js new file mode 100644 index 0000000..73f3de6 --- /dev/null +++ b/pages/elements/order-item/index.js @@ -0,0 +1,23 @@ +// pages/element-items/station-item.js +Component({ + /** + * 组件的属性列表 + */ + properties: { + + }, + + /** + * 组件的初始数据 + */ + data: { + + }, + + /** + * 组件的方法列表 + */ + methods: { + + } +}) diff --git a/pages/elements/order-item/index.json b/pages/elements/order-item/index.json new file mode 100644 index 0000000..7efff18 --- /dev/null +++ b/pages/elements/order-item/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/elements/order-item/index.wxml b/pages/elements/order-item/index.wxml new file mode 100644 index 0000000..cee8169 --- /dev/null +++ b/pages/elements/order-item/index.wxml @@ -0,0 +1,2 @@ + +pages/element-items/station-item.wxml diff --git a/pages/elements/order-item/index.wxss b/pages/elements/order-item/index.wxss new file mode 100644 index 0000000..0768314 --- /dev/null +++ b/pages/elements/order-item/index.wxss @@ -0,0 +1 @@ +/* pages/element-items/station-item.wxss */ \ No newline at end of file diff --git a/pages/elements/station-item/index.js b/pages/elements/station-item/index.js new file mode 100644 index 0000000..5be9ca2 --- /dev/null +++ b/pages/elements/station-item/index.js @@ -0,0 +1,20 @@ +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + item: { type: Object, value: null }, + type: { type: Number, value: 0 } + }, + methods: { + lookItem: function(){ + console.log(this.data.type) + if(Number(this.data.type) == 1) { + wx.redirectTo({ url: `/pages/process/station-info/index?id=${this.data.item.id}` }) + } else { + wx.navigateTo({ url: `/pages/process/station-info/index?id=${this.data.item.id}` }) + } + } + } +}) diff --git a/pages/elements/station-item/index.json b/pages/elements/station-item/index.json new file mode 100644 index 0000000..bf0260b --- /dev/null +++ b/pages/elements/station-item/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "van-cell": "/components/cell/index", + "van-image": "/components/image/index" + } +} \ No newline at end of file diff --git a/pages/elements/station-item/index.wxml b/pages/elements/station-item/index.wxml new file mode 100644 index 0000000..8973729 --- /dev/null +++ b/pages/elements/station-item/index.wxml @@ -0,0 +1,35 @@ + + + + + + + + {{item.name}} + {{item.distance}}km + + + + {{item.locDetail}} + + 月出货量:{{item.categoryProductionCapacityPerMonth}}吨 + 出货品类:{{categoryString(item.mainCategoryList)}} + 最近出货:{{item.recentlyShipmentsPaperMill}} + + + + + + function categoryString(mainCategoryList) { + var cate = '' + for (var index = 0; index < mainCategoryList.length; index++) { + if(index == 0){ + cate = mainCategoryList[index] + } else { + cate += '、' + mainCategoryList[index] + } + } + return cate + } + module.exports = categoryString + \ No newline at end of file diff --git a/pages/elements/station-item/index.wxss b/pages/elements/station-item/index.wxss new file mode 100644 index 0000000..0768314 --- /dev/null +++ b/pages/elements/station-item/index.wxss @@ -0,0 +1 @@ +/* pages/element-items/station-item.wxss */ \ No newline at end of file diff --git a/pages/formate.wxs b/pages/formate.wxs new file mode 100644 index 0000000..41c37be --- /dev/null +++ b/pages/formate.wxs @@ -0,0 +1,162 @@ +function isEmpty(val) { + return typeof val === 'undefined' || val === '' || val === null +} + +function formatTime(time) { + if (isEmpty(time)) { + return '' + } + var minute = 60 * 1000 + var just = 3 * 60 * 1000 + var onehour = 60 * 60 * 1000 + var oneday = 24 * 60 * 60 * 1000 + time = time.replace(getRegExp('/\s/g', 'g'), '') + var datetime = getDate(time.trim()) + var gap = getDate().getTime() - datetime.getTime() + + if (gap > oneday) { + return time.substring(0, 10) + } else if (gap > onehour) { + return parseInt(gap / onehour) + '小时前' + } else if (gap > onehour) { + return parseInt(gap / onehour) + '小时前' + } else if (gap > just) { + return parseInt(gap / minute) + '分钟前' + } else { + return '刚刚更新' + } +} + +function formateDate(datetime) { + if (isEmpty(datetime)) { + return '' + } + var date = getDate(datetime.trim()) + var today = getDate() + var dayCode = 24 * 60 * 60 * 1000 + var week = '' + if (date.getTime() === today.getTime()) { + week = '(今天)' + } else if (date.getTime() === today.getTime() + dayCode) { + week = '(明天)' + } else if (date.getTime() === today.getTime() - dayCode) { + week = '(昨天)' + } else if (date.getTime() === today.getTime() + dayCode * 2) { + week = '(后天)' + } else { + week = ['(周日)', '(周一)', '(周二)', '(周三)', '(周四)', '(周五)', '(周六)'][date.getDay()] + } + if (isEmpty(week)) { + week = '' + } + return datetime + week +} + +function formateAmount(amount, fix) { + if (isEmpty(amount)) { + return '' + } + if(!fix){ + fix = 2 + } + return Number(amount).toFixed(fix) +} + +function formateWeight(weight, fixed) { + if(!fixed){ + fixed = 2 + } + return (parseFloat(weight) / 1000).toFixed(fixed) +} + +function formateWeight3 (value) { + return (parseFloat(value) / 1000).toFixed(1) + '吨' +} + +function formatePrice(weight) { + return (parseFloat(weight) * 1000).toFixed(0) +} + +function maxWeight(fweight, sweight) { + if(fweight && sweight){ + if(fweight > sweight){ + return fweight + } + return sweight + } + if(sweight){ + return sweight + } + return '- -' +} + +function minWeight(fweight, sweight) { + if(fweight && sweight){ + if(fweight < sweight){ + return fweight + } + return sweight + } + if(fweight){ + return fweight + } + return '- -' +} + +function numberFormat (value) { + if (value || value == 0) { + return Number(value).toFixed(2) + } + return '' +} + +function substring(str, start, end){ + if(str){ + return str.substring(start, end) + } + return '' +} + +function formateDrice (value) { + if (value || value == 0) { + return (parseFloat(value) * 1000).toFixed(0) + } + return '- -' +} + +function formateDescripe (value) { + if (typeof(value) == 'number') { + return value + '%' + } + return '- -' +} + +function formatePrice (value) { + if (value || value == 0) { + return parseFloat(value).toFixed(1) + '元/吨' + } + return '' +} + +function summaryNumber (value) { + if (isEmpty(value)) { + return '- -' + } + return Number(value).toFixed(2) +} + +module.exports = { + numberFormat: numberFormat, + formateAmount: formateAmount, + summaryNumber: summaryNumber, + formatePrice: formatePrice, + formateWeight3: formateWeight3, + formateWeight: formateWeight, + formatTime: formatTime, + formateDate: formateDate, + maxWeight: maxWeight, + minWeight: minWeight, + substring: substring, + formateDescripe: formateDescripe, + formateDrice: formateDrice +} \ No newline at end of file diff --git a/pages/fragments/manager/index.js b/pages/fragments/manager/index.js new file mode 100644 index 0000000..b102c0d --- /dev/null +++ b/pages/fragments/manager/index.js @@ -0,0 +1,85 @@ +import { getChainList } from "../../../api/chain" +const math = require('../../../utils/math') +const util = require('../../../utils/util') +const event = require('../../../utils/event') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + /** 页面的初始数据 */ + data: { + firstShow: false, + userInfo: null, + menuList: [ + {url: '/pages/home/factory-list/index', text: '供应商管理', icon: '/assets/image/supplier-icon.png'}, + {url: '/pages/home/factory-list/index', text: '订单审核', icon: '/assets/image/order-check-icon.png'}, + {url: '/pages/home/factory-list/index', text: '在线对账', icon: '/assets/image/reconciliation-icon.png'} + ], + loading: true, + requesting: false, + finished: false, + dataList: [], + form: { + pageNum: 1, + pageSize: 10 + } + }, + lifetimes: { + attached: function () { + event.on('EventMessage', this, this.onEvent) + }, + detached: function () { + event.remove('EventMessage', this) + } + }, + methods: { + onRestart: function () { + if(!this.data.firstShow) { + this.setData({height: app.globalData.windowHeight - app.globalData.safeBottom - 100, userInfo: app.userInfo }) + this.data.form.storeId = app.userInfo.storeBaseInfo.id + this.fetchChainList() + } + // this.fetchStatisticsInfo() + this.data.firstShow = true + }, + onEvent: function (message) { + if (message.what == 888) { + } + }, + fetchStatisticsInfo: function(loading){ + getBalanceInfo().then(result => { + if(result.data){ + result.data.accountMoney = math.minus(result.data.accountMoney, result.data.frozenMoney) + this.setData({ banlanceInfo: result.data }) + } + }).catch(err => { + if(loading){ + wx.hideLoading() + } + }) + }, + fetchChainList: function(){ + if (this.data.requesting || this.data.finished) { + return + } + this.data.requesting = true + getChainList(this.data.form).then(result => { + if (result.data && result.data.records && result.data.records.length) { + var respList = result.data.records + let nowList = `dataList[${this.data.dataList.length}]` + var num = this.data.form.pageNum + var finished = ((num - 1) * this.data.form.pageSize + respList.length) >= result.data.total + this.setData({ [nowList]: respList, ['form.pageNum']: (num + 1), finished, requesting: false, loading: false }) + } else { + this.setData({ finished: true, requesting: false, loading: false }) + } + }).catch(err => { + this.setData({ requesting: false, loading: false }) + util.showToast(err) + }) + } + } +}) \ No newline at end of file diff --git a/pages/fragments/manager/index.json b/pages/fragments/manager/index.json new file mode 100644 index 0000000..756fac6 --- /dev/null +++ b/pages/fragments/manager/index.json @@ -0,0 +1,15 @@ +{ + "component": true, + "usingComponents": { + "van-image": "/components/image/index", + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index", + "van-cell": "/components/cell/index", + "van-button": "/components/button/index", + "van-info": "/components/info/index", + "van-icon": "/components/icon/index", + "van-divider": "/components/divider/index", + "van-loading": "/components/loading/index", + "chain-item": "/pages/elements/chain-item/index" + } +} \ No newline at end of file diff --git a/pages/fragments/manager/index.wxml b/pages/fragments/manager/index.wxml new file mode 100644 index 0000000..17e046b --- /dev/null +++ b/pages/fragments/manager/index.wxml @@ -0,0 +1,58 @@ + + + + + + 本月交易额(元) + + + 128,0393.00 + + + 本月订单 + 3笔 + + + 应收账款(元) + 8,0393.00 + + + + 常用功能 + + + + + + + + + 我的店铺 + + + + 废纸君的废纸店铺 + + 去分享 + + + + + + + + {{loading? '正在加载' : '暂无数据'}} + + + + + + + + + + {{finished?'到底啦~':'加载中...'}} + + + + \ No newline at end of file diff --git a/pages/fragments/manager/index.wxss b/pages/fragments/manager/index.wxss new file mode 100644 index 0000000..0e998ca --- /dev/null +++ b/pages/fragments/manager/index.wxss @@ -0,0 +1,12 @@ +/* pages/index/index.wxss */ +.menu:active { + opacity: .5 +} + +.name{ + overflow: hidden; + text-overflow:ellipsis; + white-space: nowrap; + color:white; + margin-left:32rpx; +} \ No newline at end of file diff --git a/pages/fragments/package-station/index.js b/pages/fragments/package-station/index.js new file mode 100644 index 0000000..d5fc5c5 --- /dev/null +++ b/pages/fragments/package-station/index.js @@ -0,0 +1,66 @@ +const math = require('../../../utils/math') +const event = require('../../../utils/event') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + /** 页面的初始数据 */ + data: { + firstShow: false, + userInfo: null, + menuList: [ + {url: '/pages/home/factory-list/index', text: '在线对账', icon: '/assets/image/reconciliation-icon.png'} + ], + tabIndex: 0, + tabList: [ + {id: 0, name: '全部', badge: 0, status: '' }, + {id: 1, name: '待预约', badge: 0, status: 1 }, + {id: 2, name: '待上传', badge: 0, status: 2 }, + {id: 3, name: '待审核', badge: 0, status: 3 }, + {id: 3, name: '待结算', badge: 0, status: 3 }, + {id: 3, name: '已完成', badge: 0, status: 3 } + ] + }, + lifetimes: { + attached: function () { + event.on('EventMessage', this, this.onEvent) + }, + detached: function () { + event.remove('EventMessage', this) + } + }, + methods: { + onRestart: function () { + if(!this.data.firstShow) { + this.setData({height: app.globalData.windowHeight - app.globalData.safeBottom - 100, userInfo: app.userInfo }) + } + // this.fetchStatisticsInfo() + this.data.firstShow = true + }, + onEvent: function (message) { + if (message.what == 888) { + } + }, + fetchStatisticsInfo: function(loading){ + getBalanceInfo().then(result => { + if(result.data){ + result.data.accountMoney = math.minus(result.data.accountMoney, result.data.frozenMoney) + this.setData({ banlanceInfo: result.data }) + } + if(loading){ + wx.hideLoading() + } + }).catch(err => { + if(loading){ + wx.hideLoading() + } + }) + }, + menuClick: function(e){ + + } + } +}) \ No newline at end of file diff --git a/pages/fragments/package-station/index.json b/pages/fragments/package-station/index.json new file mode 100644 index 0000000..5d53620 --- /dev/null +++ b/pages/fragments/package-station/index.json @@ -0,0 +1,14 @@ +{ + "component": true, + "usingComponents": { + "van-image": "/components/image/index", + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index", + "van-cell": "/components/cell/index", + "van-cell-group": "/components/cell-group/index", + "van-info": "/components/info/index", + "van-tabs": "/components/tabs/index", + "van-tab": "/components/tab/index", + "van-icon": "/components/icon/index" + } +} \ No newline at end of file diff --git a/pages/fragments/package-station/index.wxml b/pages/fragments/package-station/index.wxml new file mode 100644 index 0000000..8a46191 --- /dev/null +++ b/pages/fragments/package-station/index.wxml @@ -0,0 +1,32 @@ + + + + + + + + {{userInfo.storeBaseInfo.name || ''}} + + + {{userInfo.nickname || userInfo.realName}} + {{userInfo.mobile}} + + + + 其他工具 + + + + + + + + + + + + + sss + + + \ No newline at end of file diff --git a/pages/fragments/package-station/index.wxss b/pages/fragments/package-station/index.wxss new file mode 100644 index 0000000..0e998ca --- /dev/null +++ b/pages/fragments/package-station/index.wxss @@ -0,0 +1,12 @@ +/* pages/index/index.wxss */ +.menu:active { + opacity: .5 +} + +.name{ + overflow: hidden; + text-overflow:ellipsis; + white-space: nowrap; + color:white; + margin-left:32rpx; +} \ No newline at end of file diff --git a/pages/fragments/source-list/index.js b/pages/fragments/source-list/index.js new file mode 100644 index 0000000..6f81137 --- /dev/null +++ b/pages/fragments/source-list/index.js @@ -0,0 +1,100 @@ +import { getStationList } from "../../../api/ztb" +const util = require('../../../utils/util') +const event = require('../../../utils/event') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + properties: { + cityName: { type: String, value: '' } + }, + /** 页面的初始数据 */ + data: { + firstShow: false, + active: 0, + loading: true, + requesting: false, + finished: false, + stationList: [], + form: { + pageNum: 1, + pageSize: 10 + } + }, + lifetimes: { + attached: function () { + event.on('EventMessage', this, this.onEvent) + }, + detached: function () { + event.remove('EventMessage', this) + } + }, + methods: { + onRestart: function () { + if(!this.data.firstShow) { + this.setData({ + height: app.globalData.safeFragmentHeight - 190, + customHeight: app.globalData.customHeight, + customWidth: app.globalData.Custom.left, + StatusBar: app.globalData.StatusBar || 40, + }) + } + this.data.firstShow = true + }, + onEvent: function (message) { + if(message.what == 444){ + this.data.form.locCityId = app.nowCity.cityCode + if(app.nowLocation){ + this.data.form.personalLatitude = app.nowLocation.latitude + this.data.form.personalLongitude = app.nowLocation.longitude + } + this.setData({ cityName: app.nowCity.cityName, stationList: [], ['form.pageNum']: 1, loading: true, finished: false }) + this.fetchSationList() + } + }, + gridTap: function(e){ + if(e.currentTarget.id == 'city'){ + wx.navigateTo({url: `/pages/home/city-select/index` }) + } + }, + onTabChange: function({detail}){ + if(this.data.active == detail.index){ + return + } + this.data.active = detail.index + if(this.data.active == 1 && this.data.stationList.length <= 0){ + if(app.nowCity){ + this.data.form.locCityId = app.nowCity.cityCode + } + if(app.nowLocation){ + this.data.form.personalLatitude = app.nowLocation.latitude + this.data.form.personalLongitude = app.nowLocation.longitude + } + this.fetchSationList() + } + }, + fetchSationList: function(){ + if (this.data.requesting || this.data.finished) { + return + } + this.data.requesting = true + getStationList(this.data.form).then(result => { + if (result.data && result.data.records && result.data.records.length) { + var respList = result.data.records + let nowList = `stationList[${this.data.stationList.length}]` + var num = this.data.form.pageNum + var finished = ((num - 1) * this.data.form.pageSize + respList.length) >= result.data.total + this.setData({ [nowList]: respList, ['form.pageNum']: (num + 1), finished, requesting: false, loading: false }) + } else { + this.setData({ finished: true, requesting: false, loading: false }) + } + }).catch(err => { + this.setData({ requesting: false, loading: false }) + util.showToast(err) + }) + } + } +}) \ No newline at end of file diff --git a/pages/fragments/source-list/index.json b/pages/fragments/source-list/index.json new file mode 100644 index 0000000..ce95102 --- /dev/null +++ b/pages/fragments/source-list/index.json @@ -0,0 +1,10 @@ +{ + "component": true, + "usingComponents": { + "van-tabs": "/components/tabs/index", + "van-tab": "/components/tab/index", + "van-divider": "/components/divider/index", + "van-loading": "/components/loading/index", + "station-item": "/pages/elements/station-item/index" + } +} \ No newline at end of file diff --git a/pages/fragments/source-list/index.wxml b/pages/fragments/source-list/index.wxml new file mode 100644 index 0000000..8969a9c --- /dev/null +++ b/pages/fragments/source-list/index.wxml @@ -0,0 +1,38 @@ + + + + + + + {{cityName || '未知'}} + + + + + + + + 内容 1 + + + + + + + + {{loading? '正在加载' : '暂无数据'}} + + + + + + + + + + {{finished?'到底啦~':'加载中...'}} + + + + 内容 3 + \ No newline at end of file diff --git a/pages/fragments/source-list/index.wxss b/pages/fragments/source-list/index.wxss new file mode 100644 index 0000000..0e998ca --- /dev/null +++ b/pages/fragments/source-list/index.wxss @@ -0,0 +1,12 @@ +/* pages/index/index.wxss */ +.menu:active { + opacity: .5 +} + +.name{ + overflow: hidden; + text-overflow:ellipsis; + white-space: nowrap; + color:white; + margin-left:32rpx; +} \ No newline at end of file diff --git a/pages/fragments/store-list/index.js b/pages/fragments/store-list/index.js new file mode 100644 index 0000000..6add719 --- /dev/null +++ b/pages/fragments/store-list/index.js @@ -0,0 +1,65 @@ +const math = require('../../../utils/math') +const event = require('../../../utils/event') +const app = getApp() + +Component({ + options: { + addGlobalClass: true, + multipleSlots: true + }, + + /** 页面的初始数据 */ + data: { + firstShow: false, + height: app.globalData.safeFragmentHeight - 100, + + banlanceInfo: {accountMoney: 0, frozenMoney: 0} + }, + lifetimes: { + attached: function () { + event.on('EventMessage', this, this.onEvent) + }, + detached: function () { + event.remove('EventMessage', this) + } + }, + methods: { + onRestart: function () { + if(!this.data.firstShow) { + this.setData({ + height: app.globalData.safeFragmentHeight - 100, + customHeight: app.globalData.customHeight, + customWidth: app.globalData.Custom.left, + StatusBar: app.globalData.StatusBar || 40, + }) + } + // this.fetchStatisticsInfo() + this.data.firstShow = true + }, + onEvent: function (message) { + if (message.what == 888) { + } + }, + fetchStatisticsInfo: function(loading){ + getBalanceInfo().then(result => { + if(result.data){ + result.data.accountMoney = math.minus(result.data.accountMoney, result.data.frozenMoney) + this.setData({ banlanceInfo: result.data }) + } + if(loading){ + wx.hideLoading() + } + }).catch(err => { + if(loading){ + wx.hideLoading() + } + }) + }, + menuClick: function(e){ + + }, + agentList: function (e) { + + } + } +}) \ No newline at end of file diff --git a/pages/fragments/store-list/index.json b/pages/fragments/store-list/index.json new file mode 100644 index 0000000..b869717 --- /dev/null +++ b/pages/fragments/store-list/index.json @@ -0,0 +1,11 @@ +{ + "component": true, + "usingComponents": { + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index", + "van-cell": "/components/cell/index", + "van-cell-group": "/components/cell-group/index", + "van-info": "/components/info/index", + "van-icon": "/components/icon/index" + } +} \ No newline at end of file diff --git a/pages/fragments/store-list/index.wxml b/pages/fragments/store-list/index.wxml new file mode 100644 index 0000000..589d549 --- /dev/null +++ b/pages/fragments/store-list/index.wxml @@ -0,0 +1,12 @@ + + + + + 输入店铺信息 + + + + + + + \ No newline at end of file diff --git a/pages/fragments/store-list/index.wxss b/pages/fragments/store-list/index.wxss new file mode 100644 index 0000000..9c1e74c --- /dev/null +++ b/pages/fragments/store-list/index.wxss @@ -0,0 +1,4 @@ +/* pages/index/index.wxss */ +.top-bg{ + background-image: linear-gradient(127deg, rgba(0,122,255,0.67) 0%, rgba(13,100,227,0.95) 100%); +} diff --git a/pages/home/city-select/index.js b/pages/home/city-select/index.js new file mode 100644 index 0000000..62f0e72 --- /dev/null +++ b/pages/home/city-select/index.js @@ -0,0 +1,163 @@ +const util = require('../../../utils/util') +const event = require('../../../utils/event') +const storage = require('../../../utils/storage') +const city = require("../../../const/city.js") +const app = getApp() +var hotList = [] + +Page({ + data: { + type: 0, + value: '', + height: app.globalData.fragmentHeight - 100, + nowCity: null,//当前定位城市 + localCity: null,//当前定位城市 + hotCity: [], // 热门城市 + lists:[],//城市列表 + searchResult:[],//查找列表 + titleHeight: 240, + indexHeight: 0, + itemHeight: 0, + scrollViewId: '', // scroll-view滚动到的子元素的id 锚点 + touchmove: false, // 是否在索引表上滑动 + touchmoveIndex: -1 + }, + onLoad: function (options) { + if(options.type){ + if(Number(options.type) === 1){ + util.showToast('请选择一个城市,方便查看情报信息') + } + this.data.type = Number(options.type) + } + var height = app.globalData.fragmentHeight - 100 + this.data.indexHeight = height - 48 + if(this.data.indexHeight >= 1200){ + this.data.indexHeight = 1200 + } + var titleHeight = this.px2rpx(app.globalData.CustomBar) + 116 + var itemHeight = parseInt(this.data.indexHeight / 24) + var localCity = null + if(app.nowLocation && !util.isEmpty(app.nowLocation.cityName)){ + localCity = app.nowLocation + } + var nowCity = null + if(app.nowCity){ + nowCity = app.nowCity.cityName + } + var hotstring = storage.get('ztb-hot-list') + if(!util.isEmpty(hotstring)){ + hotList = JSON.parse(hotstring) + } + this.setData({ height, itemHeight, indexHeight: this.data.indexHeight, titleHeight, localCity, nowCity, lists: city.list, hotCity: hotList, type: this.data.type }) + }, + onChange({detail}){ + this.setData({ value: detail },()=>{ + this.searchCity() + }) + }, + closeInput(e){ + this.setData({ value: '' }) + }, + searchCity(){ + let result = [] + city.list.forEach((item1, index1) => { + item1.data.forEach((item2, index2) => { + if (item2.keyword.indexOf(this.data.value.toLocaleUpperCase()) !== -1) { + result.push(item2) + } + }) + }) + this.setData({ searchResult: result }) + }, + rpx2px: function(rpx) { + return rpx / 750 * app.globalData.windowWidth + }, + px2rpx: function(px) { + return px * 750 / app.globalData.windowWidth + }, + touchStart: function(e) { + this.setData({ touchmove: true }) + let pageY = this.px2rpx(e.touches[0].pageY) + let index = Math.floor((pageY - this.data.titleHeight) / this.data.itemHeight) + let item = this.data.lists[index] + if (item) { + this.setData({ scrollViewId: item.letter == '#' ? 'E_' : item.letter, touchmoveIndex: index }) + } + }, + touchMove: function(e) { + let pageY = this.px2rpx(e.touches[0].pageY) + let index = Math.floor((pageY - this.data.titleHeight) / this.data.itemHeight) + let item = this.data.lists[index] + if (item) { + this.setData({ scrollViewId: item.letter, touchmoveIndex: index }) + } + }, + touchEnd: function() { + this.setData({ touchmove: false, touchmoveIndex: -1 }) + }, + lookNow: function(){ + var latitude = parseFloat(app.nowLocation.latitude.toFixed(6)) + var longitude = parseFloat(app.nowLocation.longitude.toFixed(6)) + this.selectCity({code: app.nowLocation.cityCode, name:app.nowLocation.cityName, latitude, longitude }) + }, + lookItem: function(e){ + var item = null + if(util.isEmpty(this.data.value)){ + if(!util.isEmpty(e.currentTarget.dataset.page)){ + item = this.data.lists[e.currentTarget.dataset.page].data[e.currentTarget.dataset.index] + } else { + item = this.data.hotCity[e.currentTarget.dataset.index] + } + } else { + item = this.data.searchResult[e.currentTarget.dataset.index] + } + if(this.data.type == 2){ + const channel = this.getOpenerEventChannel() + channel.emit('onCallback', { what: 120, detail: item }) + wx.navigateBack() + return + } + this.selectCity(item) + }, + selectCity: function(item){ + if(app.nowCity) { + if(app.nowCity.cityCode == item.code){ + wx.navigateBack() + return + } + app.nowCity.cityName = item.name.replace('市', '') + app.nowCity.cityCode = item.code + if(item.latitude){ + app.nowCity.latitude = item.latitude + app.nowCity.longitude = item.longitude + } + } else { + app.nowCity = { cityName: item.name.replace('市', ''), cityCode: item.code } + if(item.latitude){ + app.nowCity.latitude = item.latitude + app.nowCity.longitude = item.longitude + } + } + var flag = false + for (let index = 0; index < hotList.length; index++) { + if(hotList[index].code == item.code){ + flag = true + break + } + } + if(!flag){ + hotList.push(item) + storage.put('ztb-hot-list', JSON.stringify(hotList)) + } + // storage.put('ztb-now-city', JSON.stringify(app.nowCity)) + event.emit('EventMessage', { what: 444, desc: 'nowCity' }) + wx.navigateBack() + }, + onShareAppMessage: function () { + return { + title: '查看附近纸厂车辆排队和扣点', + imageUrl: 'https://pic.imgdb.cn/item/61bc42cd2ab3f51d9161074e.png', + path: `pages/index/index` + } + } +}) \ No newline at end of file diff --git a/pages/home/city-select/index.json b/pages/home/city-select/index.json new file mode 100644 index 0000000..b9ea1f3 --- /dev/null +++ b/pages/home/city-select/index.json @@ -0,0 +1,8 @@ +{ + "usingComponents": { + "van-search": "/components/search/index", + "van-button": "/components/button/index", + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index" + } +} \ No newline at end of file diff --git a/pages/home/city-select/index.wxml b/pages/home/city-select/index.wxml new file mode 100644 index 0000000..d4993c9 --- /dev/null +++ b/pages/home/city-select/index.wxml @@ -0,0 +1,57 @@ + + 城市选择 + + + + + + + + {{item.name}} + + + + + + 当前城市: + {{nowCity || '暂无'}} + + + + + 定位城市: + {{localCity.cityName}} + 暂无定位城市 + + + + + 历史城市 + + + + {{item.name}} + + + + + + + + {{pageItem.letter}} + + {{item.name}} + + + + + + + + {{item.letter}} + +{{lists[touchmoveIndex].letter}} \ No newline at end of file diff --git a/pages/home/city-select/index.wxss b/pages/home/city-select/index.wxss new file mode 100644 index 0000000..d44fbe1 --- /dev/null +++ b/pages/home/city-select/index.wxss @@ -0,0 +1,29 @@ +.list-bar{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + z-index: 19; + position: absolute; + right: 0; + width: 60rpx; +} +.list-text{ + font-size: 22rpx; +} +.list-alert{ + position: absolute; + z-index: 20; + width: 160rpx; + height: 160rpx; + left: 50%; + top: 50%; + margin-left: -80rpx; + margin-top: -80rpx; + border-radius: 80rpx; + text-align: center; + line-height: 160rpx; + font-size: 70rpx; + color: #fff; + background-color: rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/pages/home/info/index.js b/pages/home/info/index.js new file mode 100644 index 0000000..c301731 --- /dev/null +++ b/pages/home/info/index.js @@ -0,0 +1,13 @@ +const app = getApp() + +Page({ + data: { + avatarUrl: '/assets/image/ygImg.png', //用户头像 + userInfo: null + }, + onLoad: function (options) { + if(app.userInfo){ + this.setData({ userInfo: app.userInfo, avatarUrl: app.userInfo.avatarUrl || '/assets/image/ygImg.png' }) + } + } +}) \ No newline at end of file diff --git a/pages/home/info/index.json b/pages/home/info/index.json new file mode 100644 index 0000000..997df63 --- /dev/null +++ b/pages/home/info/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "van-image": "/components/image/index" + } +} \ No newline at end of file diff --git a/pages/home/info/index.wxml b/pages/home/info/index.wxml new file mode 100644 index 0000000..36cdf49 --- /dev/null +++ b/pages/home/info/index.wxml @@ -0,0 +1,11 @@ + + 个人中心 + + + + + + {{userInfo.packageFactoryName || ''}} + {{userInfo.realName || ''}} + + diff --git a/pages/home/info/index.wxss b/pages/home/info/index.wxss new file mode 100644 index 0000000..9ac4df0 --- /dev/null +++ b/pages/home/info/index.wxss @@ -0,0 +1,16 @@ +/* pages/home/info/index.wxss */ +.wux-badge { + width: 130rpx; + height: 130rpx; + position: absolute; + z-index: 10; + left: 32rpx; +} + +.header-box { + width: 100%; + background: rgba(255, 255, 255, 1); + /* box-shadow: 0px 0px 15px -6px rgba(0, 0, 0, 0.32); + border-radius: 6px; */ +} + \ No newline at end of file diff --git a/pages/html/agreement/index.js b/pages/html/agreement/index.js new file mode 100644 index 0000000..3205296 --- /dev/null +++ b/pages/html/agreement/index.js @@ -0,0 +1,5 @@ +Page({ + data: { + + } +}) \ No newline at end of file diff --git a/pages/html/agreement/index.json b/pages/html/agreement/index.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/html/agreement/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/html/agreement/index.wxml b/pages/html/agreement/index.wxml new file mode 100644 index 0000000..9e7e867 --- /dev/null +++ b/pages/html/agreement/index.wxml @@ -0,0 +1,61 @@ + + 用户服务协议 + + + +       在此特别提醒您(用户)在注册成为用户之前,请认真阅读本《用户注册及使用App隐私协议》(以下简称“协议”),确保您充分理解本协议中各条款。请您审慎阅读并选择接受或不接受本协议。除非您接受本协议所有条款,否则您无权注册、登录或使用本协议所涉服务。您的注册、登录、使用等行为将视为对本协议的接受,并同意接受本协议各项条款的约束。本协议约定广州千鸟电商科技有限公司(以下简称“千鸟电商”)与用户之间关于纸通宝APP服务(以下简称“服务”)的权利义务。用户,是指注册、登录、使用本服务的个人或组织。本协议可由千鸟电商随时更新,更新后的协议条款一旦公布即代替原来的协议条款,恕不再另行通知,用户可在本App中查阅最新版协议条款。在修改协议条款后,如果用户不接受修改后的条款,请立即停止使用千鸟电商提供的服务,用户继续使用千鸟电商提供的服务将被视为接受修改后的协议。 +一、服务条款的确认和接纳 +   1.1纸通宝的各项在线服务的所有权和运作权归千鸟电商所有。您同意本协议所有条款并完成注册程序,才能成为纸通宝的正式用户。 +   1.2注册成功后,您与纸通宝之间自动形成协议关系,您应当受本协议的约束,您在使用特殊的服务或产品时,应当同意接受相关协议后方能使用。 +   1.3由于互联网高速发展,您与纸通宝签署的本协议列明的条款并不能完整罗列并覆盖您与纸通宝所有权利与义务,现有的约定也不能保证完全符合未来发展的需求。因此,纸通宝隐私政策、交易规则均为本协议的补充协议,与本协议不可分割且具有同等法律效力。如您使用纸通宝服务,视为您同意上述补充协议。 +二、服务内容 +   纸通宝通过互联网依法为您提供废纸交易等服务,您在完全同意本协议及纸通宝规定的情况下,方有权使用纸通宝的相关服务。 +三、账号注册、使用、管理、注销 +   3.1您应本着诚信向纸通宝提供注册资料,保证其提供的注册资料真实、准确、完整、合法有效,注册资料如有变动的,应及时更新其注册资料。纸通宝将依法不时地对您的信息进行检查核实,您应当配合提供最新、真实、完整、有效的信息。否则,您需承担因此引起的相应责任及后果,并且纸通宝保留终止您使用纸通宝各项服务的权利。 +   3.2 用户对通过其账户所进行的操作(包括但不限于在线发布信息、询/报价、采购产品、订购服务、信息浏览及披露信息等)依法享有权利并自行承担责任,且账号仅限于用户自身进行使用,不得给予任何第三方使用且不能以任何方式转让、赠与或继承,否则由此造成的损失由用户自行承担,且纸通宝保留暂停或终止服务的权利。 +   3.3 在完成注册时,您应当按纸通宝服务相应提示准确完整地提供并及时更新您的信息,以使之真实、及时,完整和准确。在国家法律法规有明确规定要求纸通宝作为平台服务提供者必须对用户(如卖家等)的信息进行核实的情况下,纸通宝将依法不时地对您的信息进行检查核实,您应当配合提供最新、真实、完整、有效的信息。 +   3.4在用户注册及使用本服务时,纸通宝服务需要搜集能识别用户身份的个人信息以便纸通宝服务可以在必要时联系用户,或为用户提供更好的使用体验。纸通宝服务搜集的信息包括但不限于用户的姓名、地址;纸通宝服务同意对这些信息的使用将受限于第三条用户个人隐私信息保护的约束。 +   3.5您应谨慎合理的保存、使用密码,且勿将密码告知他人。账户因您主动泄露或因您遭受他人攻击、诈骗等行为导致的损失及后果,纸通宝并不承担责任,您应通过司法、行政等救济途径向侵权行为人追偿。 +   3.6您遗忘或丢失在纸通宝注册的密码时,可通过注册手机验证码找回密码,也可与纸通宝客服人员取得联系,在提供相关证明资料并经纸通宝审核确认后,可找回密码。 +   3.7存在如下情形,纸通宝有权终止本协议: +    (1)用户违反本协议累计达到3次的; +    (2)其他法律法规规定及纸通宝认为需要终止的情形。 +    (3)协议终止后,纸通宝有权继续保存您的注册信息及在纸通宝平台上的所有交易信息,并有权视情况删除尚未交易的物品,及未实际履行交易信息。 +四、使用规则 +   4.1、本条所述内容是指用户使用纸通宝App的过程中所制作、上载、复制、发布、传播的任何内容,包括但不限于账号头像、名称、用户说明等注册信息及认证资料,或文字、语音、图片、视频、图文等发送、回复或自动回复消息和相关链接页面,以及其他使用账号或本服务所产生的内容。 +   4.2、用户不得利用纸通宝App账号或本服务制作、上传、复制、发布、传播如下法律、法规和政策禁止的内容: +    (1) 反对宪法所确定的基本原则的; +    (2) 危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的; +    (3) 损害国家荣誉和利益的; +    (4) 煽动民族仇恨、民族歧视,破坏民族团结的; +    (5) 破坏国家宗教政策,宣扬邪教和封建迷信的; +    (6) 散布谣言,扰乱社会秩序,破坏社会稳定的; +    (7) 散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的; +    (8) 侮辱或者诽谤他人,侵害他人合法权益的; +    (9) 含有法律、行政法规禁止的其他内容的信息。 +   4.3、用户在本服务中或通过本服务所传送、发布的任何内容并不反映或代表,也不得被视为反映或代表千鸟电商的观点、立场或政策,千鸟电商对此不承担任何责任。 +   4.4、用户不得利用纸通宝App账号或本服务进行如下行为: +    (1) 提交、发布虚假信息,或盗用他人头像或资料,冒充、利用他人名义的; +    (2) 虚构事实、隐瞒真相以误导、欺骗他人的; +    (3) 利用技术手段批量建立虚假账号的; +    (4) 利用纸通宝App账号或本服务从事任何违法犯罪活动的; +    (5) 制作、发布与以上行为相关的方法、工具,或对此类方法、工具进行运营或传播,无论这些行为是否为商业目的; +    (6) 其他违反法律法规规定、侵犯其他用户合法权益、干扰纸通宝App正常运营或千鸟电商未明示授权的行为。 +   4.5、用户须对利用纸通宝App账号或本服务传送信息的真实性、合法性、无害性、准确性、有效性等全权负责,与用户所传播的信息相关的任何法律责任由用户自行承担,与千鸟电商无关。如因此给千鸟电商或第三方造成损害的,用户应当依法予以赔偿。 +五、用户个人隐私信息保护 +   5.1、如果千鸟电商发现或收到他人举报或投诉用户违反本协议约定的,千鸟电商有权不经通知随时对相关内容,包括但不限于用户资料、发布记录进行审查、删除,并视情节轻重对违规账号处以包括但不限于警告、账号封禁、设备封禁、功能封禁的处罚,且通知用户处理结果。 +   5.2、因违反用户协议被封禁的用户,可以自行与千鸟电商联系。其中,被实施功能封禁的用户会在封禁期届满后自动恢复被封禁功能。被封禁用户可提交申诉,千鸟电商将对申诉进行审查,并自行合理判断决定是否变更处罚措施。 +   5.3、用户理解并同意,千鸟电商有权依合理判断对违反有关法律法规或本协议规定的行为进行处罚,对违法违规的任何用户采取适当的法律行动,并依据法律法规保存有关信息向有关部门报告等,用户应承担由此而产生的一切法律责任。 +   5.4、用户理解并同意,因用户违反本协议约定,导致或产生的任何第三方主张的任何索赔、要求或损失,包括合理的律师费,用户应当赔偿千鸟电商与合作公司、关联公司,并使之免受损害。 + 六、责任限制及不承诺担保 +   6.1、纸通宝平台上展示的全部信息、资料、货物和服务,均由商家自行提供的。 除非另有明确的书面说明,纸通宝不对平台上的信息、资料、货物和服务作任何形式的、明示或默示的声明或担保(根据中华人民共和国法律另有规定的以外)。 如因不可抗力或其它无法控制的原因导致网上交易无法完成或丢失有关的信息、记录等,纸通宝会合理地尽力协助处理善后事宜。 +   6.2、如买卖双方在交易过程中发生纠纷,在当事人自愿平等的前提下,买卖双方可提出要求“纸通宝”协助调解。“纸通宝”会在查明事实、分清是非的基础上,严格遵守国家法律法规来给出建议。经调解达成的协议具有法律效力,但纸通宝对此协议内容不承担任何法律责任。 + 七、其他 +    1、千鸟电商郑重提醒用户注意本协议中免除千鸟电商责任和限制用户权利的条款,请用户仔细阅读,自主考虑风险。未成年人应在法定监护人的陪同下阅读本协议。 +    2、本协议的效力、解释及纠纷的解决,适用于中华人民共和国法律。若用户和千鸟电商之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户同意将纠纷或争议提交千鸟电商住所地有管辖权的人民法院管辖。 +    3、本协议的任何条款无论因何种原因无效或不具可执行性,其余条款仍有效,对双方具有约束力。 +  + + 广州千鸟电商科技有限公司 + 发布日期:2020年8月4日 + \ No newline at end of file diff --git a/pages/html/agreement/index.wxss b/pages/html/agreement/index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/pages/login/index.js b/pages/login/index.js new file mode 100644 index 0000000..f982f2a --- /dev/null +++ b/pages/login/index.js @@ -0,0 +1,143 @@ +import Dialog from '../../components/dialog/dialog' +import { config, wechatApplet, phoneWechat } from "../../api/user" +import { zconfig, loginToken } from "../../api/ztb" +import { hconfig, getUserInfo, getIntentById } from "../../api/chain" +const util = require('../../utils/util') +const storage = require('../../utils/storage') +const app = getApp() + +Page({ + data: { + logining: false, + checked: false, + metaData: null, + code: null + }, + /************************************** 初始化登录流程 ********************************************/ + onLoad: function (options) { + app.globalData.keyboardHeight = storage.get('keyboardHeight') || 0 + if(options.code){ + this.data.code = options.code + } + this.data.checked = storage.get('ztb-merchant-check') || false + this.setData({checked: this.data.checked}) + app.globalData.token = app.globalData.token || storage.get('Authorization') + if(this.data.code){ + this.fetchIntent(this.data.code) + } else if(!util.isEmpty(app.globalData.token)){ + this.setData({ loging: true}) + this.fetchUserInfo(app.globalData.token) + } else if(this.data.checked){ + var that = this + wx.login({ + success: res => { + that.wechatLogin(res.code) + } + }) + } + }, + wechatLogin: util.throttle(function(code){ + wechatApplet({ authCode: code, authMethod: 'WeChatMiniProgram' }).then(result => { + if(result.code == 0 && result.data.token){ + app.globalData.token = result.data.token + this.fetchUserInfo(app.globalData.token) + } else if(result.data.tmpAuthToken){ + storage.put('tmpAuthToken', result.data.tmpAuthToken, 98) + } + }) + }), + /************************************** 获取用户信息,进行登录 ********************************************/ + fetchUserInfo: function(authorization){ + config.header = { 'Authorization': 'QNT ' + authorization } + loginToken({loginToken: authorization}).then(result => { + zconfig.header = { 'Authorization': 'QNT ' + result.data.token } + hconfig.header = { 'Authorization': 'QNT ' + result.data .token} + getUserInfo(result.data).then(result => { + app.userInfo = result.data + app.globalData.token = authorization + storage.put('Authorization', authorization) + if(app.userInfo.agentBaseInfo){ + wx.redirectTo({ url: '/pages/merchant/index' }) + } else if(app.userInfo.packerBaseInfo){ + wx.redirectTo({ url: '/pages/station/index' }) + } else if(this.data.metaData){ + + } else { + this.setData({ loging: false }) + Dialog.alert({ title: '温馨提示', message: '您暂未开通纸通宝商家版服务,请联系企业管理员开通或在线开通。' }).then(() => {}) + } + }).catch(err => { + if(err.code == 200101){ + util.showToast('获取用户信息失败,请注册登录') + this.setData({ loging: false }) + } else { + util.showToast(err) + this.setData({ loging: false}) + } + config.header = null + storage.remove('Authorization') + }) + }).catch(err => { + if(err !== null && err instanceof Object) { + util.showToast('服务器错误') + } else { + util.showToast(err) + } + config.header = null + storage.remove('Authorization') + this.setData({ loging: false}) + }) + }, + checkAgreement: function(){ + if(!this.data.checked){ + util.showToast('请阅读并同意《用户服务协议》和《隐私协议》') + return + } + }, + /************************************** 注册流程 ********************************************/ + onGotPhoneNumber: function (e) { + storage.put('ztb-merchant-check', true) + // 这里根据用户点击, 判断一下, 如果点击了取消, 将触发下面方法 + if(e.detail.errMsg == 'getPhoneNumber:fail user deny'){ + util.showToast('请您授权手机号,以便提供更好服务') + return + } + this.setData({ logining: true }) + phoneWechat({ encryptedData: e.detail.encryptedData, iv: e.detail.iv }).then(result => { + app.globalData.token = result.data.token + this.fetchUserInfo(app.globalData.token) + }).catch(error => { + this.setData({ logining: false }) + if(typeof(error) == 'string'){ + util.showToast(error) + } else if (error && error.data) { + util.showToast(error.message) + } + }) + }, + readAgreement: function () { + if(this.data.loging){ + return + } + wx.navigateTo({ url: '/pages/html/agreement/index' }) + }, + /************************************** 二维码流程 ********************************************/ + fetchIntent: function(eventId){ + this.setData({ loging: true}) + getIntentById(eventId).then(result => { + this.data.code = null + if(result.data.redirectUrl == '/page/pound/index'){ + if(!util.isEmpty(app.globalData.token)){ + this.fetchUserInfo(app.globalData.token) + } + } else { + this.setData({ loging: false}) + } + }).catch(err => { + this.setData({ loging: false}) + }) + }, + onChange({detail}) { + this.setData({ checked: detail }) + } +}) \ No newline at end of file diff --git a/pages/login/index.json b/pages/login/index.json new file mode 100644 index 0000000..cf6a453 --- /dev/null +++ b/pages/login/index.json @@ -0,0 +1,7 @@ +{ + "usingComponents": { + "van-button": "/components/button/index", + "van-dialog": "/components/dialog/index", + "van-checkbox": "/components/checkbox/index" + } +} \ No newline at end of file diff --git a/pages/login/index.wxml b/pages/login/index.wxml new file mode 100644 index 0000000..d1ec7f0 --- /dev/null +++ b/pages/login/index.wxml @@ -0,0 +1,27 @@ + + + 纸掌柜 + + + + 提供合规和金融的废纸云ERP + + + + + 微信一键登录 + 微信一键登录 + + + + + 已阅读并同意 + 《用户服务协议》 + + 《隐私协议》 + + + \ No newline at end of file diff --git a/pages/login/index.wxss b/pages/login/index.wxss new file mode 100644 index 0000000..d29d929 --- /dev/null +++ b/pages/login/index.wxss @@ -0,0 +1,3 @@ +page { + background-color: #fff; +} \ No newline at end of file diff --git a/pages/merchant/index.js b/pages/merchant/index.js new file mode 100644 index 0000000..f3fe2b6 --- /dev/null +++ b/pages/merchant/index.js @@ -0,0 +1,112 @@ +const wxmap = require('../../libs/wxmap.js') +const app = getApp() + +Page({ + data: { + safeBottom: app.globalData.safeBottom, + fHeight: app.globalData.safeFragmentHeight, + tabList: [ + { value: 'source', badge: 0, name: '首页', blue: '/assets/icon/mall-blue.png', gray: '/assets/icon/mall-gray.png' }, + { value: 'manager', badge: 0, name: '纸掌柜', blue: '/assets/icon/store-blue.png', gray: '/assets/icon/store-gray.png' }, + { value: 'package', badge: 0, name: '我的', blue: '/assets/icon/home-blue.png', gray: '/assets/icon/home-gray.png' } + ], + tabIndex: 0, + cityName: '', + }, + onLoad: function (options) { + if (options.url) { + var path = options.url + if (options.key && options.value) { + path += '?' + options.key + '=' + options.value + } + wx.navigateTo({ url: path }) + } + const fHeight = (app.globalData.safeFragmentHeight + app.globalData.statusBarHeight) - 100 + this.setData({ + fHeight: fHeight, + safeBottom: app.globalData.safeBottom, + cityName: this.data.cityName, + customHeight: app.globalData.customHeight, + customWidth: app.globalData.Custom.left, + StatusBar: app.globalData.StatusBar || 40, + }) + this.locationing() + }, + /********************************************************getLocation**************************************************************/ + locationing: function() { + var that = this + wx.getLocation({ + type: 'gcj02', + success (res) { + app.nowLocation = res + wxmap.geocoder(app.nowLocation.latitude, app.nowLocation.longitude).then(resp => { + app.nowLocation.cityName = resp.result.address_component.city.replace('市', '') + app.nowLocation.cityCode = resp.result.ad_info.city_code.replace('156', '') + app.nowLocation.address = resp.result.address + app.nowLocation.districtCode = resp.result.ad_info.adcode + if(!app.nowCity){ + app.nowCity = { cityName: app.nowLocation.cityName, cityCode: app.nowLocation.cityCode } + app.nowCity.latitude = parseFloat(app.nowLocation.latitude.toFixed(6)) + app.nowCity.longitude = parseFloat(app.nowLocation.longitude.toFixed(6)) + that.setData({ cityName: app.nowLocation.cityName }) + } + }) + }, + fail (e){ + if (e && (e.errCode == 2 || e.errCode == 404)) { + Dialog.alert({ title: '温馨提示', message: '位置信息获取失败,请检查手机“位置信息”是否未开启' }).then(() => {}) + } else if (e && ((e.errMsg.indexOf('getLocation:fail auth deny') != -1) || (e.errMsg.indexOf('system permission denied') != -1))) { + wx.getSetting({ + success(res){ + if(res && (res.authSetting["scope.userLocation"] !== undefined && res.authSetting["scope.userLocation"] !==true)){ + that.detectSettings() + } else { + Dialog.alert({ title: '温馨提示', message: '位置信息获取失败,请检查微信是否有定位权限' }).then(() => {}) + } + } + }) + } else if (e && e.errMsg.indexOf('getLocation:fail connect ETIMEDOUT') != -1) { + Dialog.alert({ title: '温馨提示', message: '位置信息获取失败,请检查网络是否连接' }).then(() => {}) + } + } + }) + }, + detectSettings: function(){ + var message = '小程序没有定位权限,无法提供您周边的纸厂报价和相关信息服务,请前往设置微信小程序的定位权限。' + Dialog.confirm({ title: '温馨提示', message, confirmButtonText: '前往设置' }).then(() => { + wx.openSetting({ + success(result){ + if(result && (result.authSetting["scope.userLocation"] !== undefined && result.authSetting["scope.userLocation"] === true)){ + this.locationing() + } + } + }) + }) + }, + /********************************************************Tabbar*************************************************************/ + onTabClick: function(e){ + if(this.data.tabIndex == e.currentTarget.dataset.index){ + return + } + this.setData({ tabIndex: e.currentTarget.dataset.index }) + this.onShow() + }, + stopTouchMove: function(e){ + return false + }, + onShow: function () { + var pageView = this.selectComponent('#' + this.data.tabList[this.data.tabIndex].value) + if (pageView && pageView.onRestart) { + pageView.onRestart() + } + }, + onShareAppMessage: function (e) { + console.log(e) + return { + title: '纸通宝工厂版——', + path: 'pages/login/index?qrcode=562333739288498176', + imageUrl: '/assets/image/icon_logo.png', + success: function (res) {} + } + } +}) \ No newline at end of file diff --git a/pages/merchant/index.json b/pages/merchant/index.json new file mode 100644 index 0000000..16b03d1 --- /dev/null +++ b/pages/merchant/index.json @@ -0,0 +1,10 @@ +{ + "usingComponents": { + "source": "/pages/fragments/source-list/index", + "manager": "/pages/fragments/manager/index", + "package": "/pages/fragments/package-station/index", + "van-icon": "/components/icon/index", + "van-tabbar": "/components/tabbar/index", + "van-tabbar-item": "/components/tabbar-item/index" + } +} \ No newline at end of file diff --git a/pages/merchant/index.wxml b/pages/merchant/index.wxml new file mode 100644 index 0000000..acd63ae --- /dev/null +++ b/pages/merchant/index.wxml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + {{item.name}} + + + \ No newline at end of file diff --git a/pages/merchant/index.wxss b/pages/merchant/index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/pages/process/order-appointment/index.js b/pages/process/order-appointment/index.js new file mode 100644 index 0000000..a00cd26 --- /dev/null +++ b/pages/process/order-appointment/index.js @@ -0,0 +1,351 @@ +import { getVehicleList } from "../../../api/ztb" +const util = require('../../../utils/util') +const math = require('../../../utils/math') +const app = getApp() + +Page({ + + /** + * 页面的初始数据 + */ + data: { + height: app.globalData.fragmentHeight, + safeBottom: app.globalData.safeBottom, + keyboardHeight: 0, + form: { + paperCategoryId: '', + unitPrice: '' + }, + timeList: [], + cateName: '', + factoryDetail: null, + vehicleList: [{}], + plateList: [], + vateList: [], + cateList: [], + plateNumber: '', + plateString: '', + vindex: -1, + requesting: false, + columns: [], + toolbar: '', + toolId: '', + visible: false, + code: '', + editing: false, + focusTop: '100%', // 输入框获取焦点时的top值 + platform: false, // 机型 + domHeight: 'auto', // dom元素高度 + focusTime: 0 // 获取焦点的时间 yiling 20200408 14:43:56 + }, + onLoad: function (options) { + if(Number(options.type) == 1){ + let channel = this.getOpenerEventChannel() + let that = this + channel.once('onParam', function (data) { + that.initForm(data) + }) + } else if(options.orderId){ + // wx.showLoading({ title: '加载中', mask: true }) + // getProxyOrderInfo(options.orderId).then(result => { + // this.setData({ form: result.data, cateName: result.data.paperCategory, safeBottom: app.globalData.safeBottom, + // ['form.totalEstimatedWeight']: math.divide(result.data.estimatedWeight, 1000) + // }) + // wx.hideLoading() + // }).catch(err => { + // wx.hideLoading() + // util.showToast(err) + // }) + } + var day = new Date() + for (let i = 0; i < 7; i++) { + day.setDate(day.getDate() + (i > 1 ? 1 : i)) + this.data.timeList.push(util.formatDate(day, 'Y-M-D')) + } + }, + initForm: function(detail){ + for (let index = 0; index < detail.agentPaperCategoryList.length; index++) { + const element = detail.agentPaperCategoryList[index] + this.data.cateList.push(element.displayName + '(预估单价:' + element.paperMillPrice + '元/吨)') + } + var item = detail.agentPaperCategoryList[detail.cateIndex || 0] + this.setData({ + cateName: item.displayName, + millName: detail.paperMillName, + ['form.unitPrice']: item.paperMillPrice, + ['form.priceOfAgentSold']: detail.priceOfAgentSold + }) + }, + onInput: function(e){ + if(e.currentTarget.id == 'totalEstimatedWeight'){ + this.data.form.totalEstimatedWeight = e.detail + this.data.amout = 0 + if(Number(e.detail) > 0){ + this.data.amout = math.times(e.detail, this.data.form.unitPrice) + } + this.setData({ amout: this.data.amout }) + } else if(e.currentTarget.id == 'priceOfAgentSold'){ + this.data.form.priceOfAgentSold = e.detail + } + }, + onEdit: function(e){ + this.setData({ editing: true }) + }, + bindInput: function (e) { + if(!util.isEmpty(e.currentTarget.id)){ + var form_data = 'form.' + e.currentTarget.id + if(e.currentTarget.id == 'remark'){ + this.setData({ [form_data]: e.detail }) + } else { + this.setData({ [form_data]: e.detail.value }) + } + } else { + this.data.code = e.detail.value + } + }, + showKeyboard: function(e){ + var item = this.data.vehicleList[e.currentTarget.dataset.index] + this.keyboard = this.keyboard || this.selectComponent('#wux-keyboard') + this.keyboard.show(item.plateNumber, e.currentTarget.dataset.index) + }, + onPlatenumber: function({detail}){ + if(detail && detail.plateNumber){ + this.setData({ ['vehicleList[' + detail.type + '].plateNumber']: detail.plateNumber }) + } + }, + addCate: function (e) { + if(this.data.vehicleList.length >= 5){ + util.showToast('一次预约不能超过5辆车') + return + } + this.data.vehicleList.push({ plateNumber: '', driverName: '', driverPhone: '', packageNum: '' }) + this.setData({ vehicleList: this.data.vehicleList }) + }, + deleteCate: function (e) { + this.data.vehicleList.splice(e.currentTarget.dataset.index, 1) + this.setData({ vehicleList: this.data.vehicleList }) + }, + bindList: function(event){ + this.setData({ ['vehicleList[' + event.currentTarget.dataset.index + '].' + event.target.id]: event.detail.value }) + }, + showPicker: function (e) { + if(!util.isEmpty(this.data.form.activityId) && e.currentTarget.id == 'cateName'){ + return + } + this.data.toolId = e.currentTarget.id + if(e.currentTarget.id == 'deliveryTime'){ + this.setData({ visible: true, columns: this.data.timeList, toolbar: '选择到货时间' }) + } else if(e.currentTarget.id == 'cateName'){ + this.setData({ visible: true, columns: this.data.cateList, toolbar: '选择纸品' }) + } + }, + onHide: function(){ + this.setData({ visible: false }) + }, + onConfirm: function ({detail}) { + if(this.data.toolId == 'deliveryTime'){ + this.setData({ ['form.deliveryTime']: detail.value, visible: false }) + } else if(this.data.toolId == 'cateName'){ + const element = this.data.factoryDetail.paperCategoryList[detail.index] + if(element.publicSubsidies && Number(element.publicSubsidies) > 0){ + this.data.form.publicSubsidies = element.publicSubsidies + this.data.form.unitPrice = math.plus(element.unitPrice, element.publicSubsidies) + } else { + this.data.form.unitPrice = element.unitPrice + this.data.form.publicSubsidies = 0 + } + this.data.cateName = element.categoryName + this.data.form.paperCategoryId = element.categoryId + this.setData({ ['form.unitPrice']: this.data.form.unitPrice, ['form.publicSubsidies']: this.data.form.publicSubsidies, + cateName: this.data.cateName, visible: false }) + } + }, + tagChange: function(e){ + var item = this.data.vateList[e.target.dataset.index] + if(item.fold == 1){ + this.data.vateList = this.data.plateList.slice(0, 16) + // this.data.vateList.push({plateNumber: '收起', fold: 2}) + this.setData({ vateList: this.data.vateList }) + return + } + if(item.fold == 2){ + this.data.vateList = this.data.plateList.slice(0, 7) + this.data.vateList.push({plateNumber: '展开', fold: 1}) + this.setData({ vateList: this.data.vateList }) + return + } + for (let index = 0; index < this.data.vehicleList.length; index++) { + if(this.data.vehicleList[index].plateNumber == item.plateNumber){ + return + } + } + for (let index = 0; index < this.data.vehicleList.length; index++) { + if(util.isEmpty(this.data.vehicleList[index].plateNumber)){ + this.setData({ ['vehicleList[' + index+ '].plateNumber']: item.plateNumber }) + return + } + } + if(this.data.vehicleList.length >= 5){ + util.showToast('一次预约不能超过5辆车') + return + } + this.data.vehicleList.push({plateNumber: item.plateNumber}) + this.setData({ vehicleList: this.data.vehicleList }) + }, + submitForm: function (e) { + // if(!app.userInfo.isAuth) { + // Dialog.alert({ title: '温馨提示', message: '您暂未实名认证,请实名认证后提交订单。' }).then(() => { + // wx.navigateTo({ url: '/pages/setting/authory/index' }) + // }) + // return + // } + if (util.isEmpty(this.data.form.totalEstimatedWeight)) { + util.showToast('请输入预估重量') + return + } + if (Number(this.data.form.totalEstimatedWeight) <= 0) { + util.showToast('预估重量必须大于0') + return + } + if (util.isEmpty(this.data.form.deliveryTime)) { + util.showToast('请选择货到时间') + return + } + if (Number(this.data.form.priceOfAgentSold) <= 0) { + util.showToast('请输入代卖费,且大于0') + return + } + var vehicleList = [] + for (let index = 0; index < this.data.vehicleList.length; index++) { + const element = this.data.vehicleList[index] + if(!util.isEmpty(element.plateNumber)){ + vehicleList.push(element) + } + } + if (vehicleList.length < 1) { + util.showToast('请选择或者输入车牌号码') + return + } + this.data.form.carInfos = vehicleList + var that = this + wx.requestSubscribeMessage({ + tmplIds: app.tmplIds, + complete(res) { + that.submitOrder() + } + }) + }, + submitOrder: function(){ + if(this.data.requesting){ + return + } + this.data.form.totalEstimatedWeight = math.times(this.data.form.totalEstimatedWeight, 1000) + this.setData({ requesting: true }) + wx.showLoading({ title: '处理中', mask: true }) + createProxyOrder(this.data.form).then(result => { + wx.hideLoading() + wx.redirectTo({ url: '/xtends/proxysell/result/index' }) + }).catch(err => { + wx.hideLoading() + util.showToast(err) + this.data.form.totalEstimatedWeight = math.divide(this.data.form.totalEstimatedWeight, 1000) + this.setData({ requesting: false }) + }) + }, + /************************************** TextArea ********************************************/ + handleEvaluationFocus(e) { + /* 获取焦点时记录时间 yiling 202000408 14:43:56 start */ + this.setData({ focusTime: Date.now() }) + /* 获取焦点时记录时间 yiling 202000408 14:43:56 end */ + const { height } = e.detail // 为键盘高度 + const windowHeight = wx.getSystemInfoSync().windowHeight // 可使用窗口高度,单位px + if (this.data.oldFocusTop) { + this.setData({ focusTop: this.data.oldFocusTop }) + } else { + const query = wx.createSelectorQuery().in(this) // 自定义组件内必须添加.in(this),否则获取不到dom数据! + query.select('.popup-evaluation-wrap').boundingClientRect() + query.exec(res => { + if (res[0]) { + const domHeight = res[0].height || 156 + this.setData({ + focusTop: (windowHeight - domHeight - height) + 'px', + oldFocusTop: (windowHeight - domHeight - height) + 'px', + domHeight: domHeight + 'px', // 固定高度,防止部分机型中多行文本时布局错乱 + }) + } + }) + } + }, + /** + * @author: yiling + * @description: 监听输入框输入内容,统计字数 + * @param {Object} event event + * @return {void} + * @Date: 2019-12-16 15:46:22 + */ + handleEvaluationInput({detail}) { + this.setData({ ['form.remark']: detail.value }) + }, + /** + * @author: yiling + * @description: 点击完成按钮时关闭弹窗 + * @return {void} + * @Date: 2019-12-16 15:46:22 + */ + handleEvaluationConfirm() { + this.handleClose() + }, + /** + * @author: yiling + * @description: 点击发表评论按钮 + * @return {void} + * @Date: 2019-12-16 15:46:22 + */ + handleEvaluationRelease() { + this.handleClose((object) => { + object.id = this.data.info.id // id + object.content = this.data.commentsText // 评论内容 + object.typeName = this.data.info.typeName // 类型:名片 / 资讯 / 商城 / ... + }) + }, + /** + * @author: yiling + * @description: 关闭输入框的弹窗 + * @param {Function} callback 回调 + * @return {void} + * @Date: 2019-12-16 15:46:22 + */ + handleClose(callback) { + this.setData({ focusTop: '100%', editing: false }) + }, + /** + * @author: yiling + * @description: 防页面穿透 + * @return {void} + * @Date: 2019-12-16 15:46:22 + */ + handleEvaluationtouchmove() { + this.handleClose() + return false + }, + /** + * @author: yiling + * @description: 失去焦点(安卓机软键盘右上角的小三角会触发) + * @return {void} + * @Date: 2019-12-19 + */ + handleEvaluationBlur() { + if (Date.now() > this.data.focusTime && this.data.focusTime !== 0) { + this.handleClose() + } + }, + noop: function(){ + + }, + /** + * 用户点击右上角分享 + */ + onShareAppMessage: function () { + + } +}) \ No newline at end of file diff --git a/pages/process/order-appointment/index.json b/pages/process/order-appointment/index.json new file mode 100644 index 0000000..81a11b6 --- /dev/null +++ b/pages/process/order-appointment/index.json @@ -0,0 +1,18 @@ +{ + "usingComponents": { + "van-cell": "/components/cell/index", + "van-field": "/components/field/index", + "van-button": "/components/button/index", + "van-dialog": "/components/dialog/index", + "van-loading": "/components/loading/index", + "van-image": "/components/image/index", + "van-textarea": "/components/textarea/index", + "van-picker": "/components/picker/index", + "van-popup": "/components/popup/index", + "van-icon": "/components/icon/index", + "plate-keyboard": "/components/plate-keyboard/index", + "van-steps": "/components/steps/index", + "van-step": "/components/step/index", + "submit-layout": "/components/submit-layout/index" + } +} \ No newline at end of file diff --git a/pages/process/order-appointment/index.wxml b/pages/process/order-appointment/index.wxml new file mode 100644 index 0000000..e2d9378 --- /dev/null +++ b/pages/process/order-appointment/index.wxml @@ -0,0 +1,127 @@ + + + 代卖预约 + + + + + + + 纸品信息 + + + + 纸厂名称 + {{millName}} + + + + + 纸品品类 + {{cateName || '请选择品类'}} + + + + + 预估单价(元/吨) + + {{formate.formatePrice(form.unitPrice)}} + (已含补贴{{formate.formatePrice(form.publicSubsidies)}}元/吨) + + + + + + 预估重量(吨) + + + + + 货到时间 + {{form.deliveryTime||'请选择货到时间'}} + + + + + 代卖费(元/吨) + + + + + + 车辆信息 + + + + {{item.plateNumber}} + + + + + + {{index + 1}} + 货车车牌: + + {{item.plateNumber || '点击输入车牌号码'}} + + + + + + + + 添加车辆 + + + + + 采购规则 + + + {{form.remark || '点击输入采购规则,最多100字' }} + + + + 贸易商 + + + + + + 1 + + + 2 + + + 3 + + + + + + + + 预计金额: + {{amout || '- -'}} + + 提交订单 + + + + + + + + + + + + 采购规则 + + + + + + + diff --git a/pages/process/order-appointment/index.wxss b/pages/process/order-appointment/index.wxss new file mode 100644 index 0000000..f3f959c --- /dev/null +++ b/pages/process/order-appointment/index.wxss @@ -0,0 +1,94 @@ +.margin-top { + margin-top: 18rpx; +} + +.grid{ + flex: 1; +} + +.cate-list { + margin: 24rpx 30rpx; + border: 1rpx solid #f3f3f3; +} + +.cate-header { + min-height: 80rpx; + background-color: #f3f3f3; + padding: 0rpx 30rpx; +} + +.cate-paper { + height: 100rpx; + border-bottom: 1rpx solid #f3f3f3; +} + +.textarea{ + width:100%; + height:80px; + padding: 12rpx; + font-size: 14px; + border: 1rpx solid #f3f3f3; +} + +.bg-blue{ + color: #FFFFFF; + background-color: #008AFF; +} + +.dialog-input { + padding:0rpx 16rpx; + border:1rpx solid #eee; + height:80rpx; + margin:64rpx +} + +.round{ + width: 44rpx; + height: 44rpx; +} + + + +.popup-evaluation__bg { + background: rgba(0, 0, 0, 0.2); + position: fixed; + left: 0; + right: 0; + top: 100%; + z-index: 66; + opacity: 0; + min-height: 100vh; +} +.popup-evaluation-wrap { + box-sizing: border-box; + background: #fff; + position: absolute; + top: 100%; + /* transition: .15s; */ + width: 100%; + display: flex; + flex-direction: column; +} + +/* 修复ios的padding bug 注:苹果手机中textarea自带会带"填充"且是小值为12 start */ +.textatrea_ios_bug { + padding: 4rpx; +} + +/* 获取焦点时的样式 start */ +.is__show { + top:0; + opacity: 1; + /* transition: .35s; */ +} + +.step-dot{ + height: 40rpx; + width: 40rpx; + line-height: 40rpx; + text-align: center; + font-size: 24rpx; + color: #fff; + background-color: #008AFF; + border-radius: 50%; +} diff --git a/pages/process/order-info/index.js b/pages/process/order-info/index.js new file mode 100644 index 0000000..aeb70ca --- /dev/null +++ b/pages/process/order-info/index.js @@ -0,0 +1,66 @@ +// pages/process/order-info/index.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad: function (options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady: function () { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow: function () { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide: function () { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload: function () { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh: function () { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom: function () { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage: function () { + + } +}) \ No newline at end of file diff --git a/pages/process/order-info/index.json b/pages/process/order-info/index.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/process/order-info/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/process/order-info/index.wxml b/pages/process/order-info/index.wxml new file mode 100644 index 0000000..4510950 --- /dev/null +++ b/pages/process/order-info/index.wxml @@ -0,0 +1,2 @@ + +pages/process/order-info/index.wxml diff --git a/pages/process/order-info/index.wxss b/pages/process/order-info/index.wxss new file mode 100644 index 0000000..231653d --- /dev/null +++ b/pages/process/order-info/index.wxss @@ -0,0 +1 @@ +/* pages/process/order-info/index.wxss */ \ No newline at end of file diff --git a/pages/process/order-list/index.js b/pages/process/order-list/index.js new file mode 100644 index 0000000..128080f --- /dev/null +++ b/pages/process/order-list/index.js @@ -0,0 +1,65 @@ +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad: function (options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady: function () { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow: function () { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide: function () { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload: function () { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh: function () { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom: function () { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage: function () { + + } +}) \ No newline at end of file diff --git a/pages/process/order-list/index.json b/pages/process/order-list/index.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/process/order-list/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/process/order-list/index.wxml b/pages/process/order-list/index.wxml new file mode 100644 index 0000000..17c56ae --- /dev/null +++ b/pages/process/order-list/index.wxml @@ -0,0 +1,2 @@ + +pages/process/order-list/index.wxml diff --git a/pages/process/order-list/index.wxss b/pages/process/order-list/index.wxss new file mode 100644 index 0000000..649b69a --- /dev/null +++ b/pages/process/order-list/index.wxss @@ -0,0 +1 @@ +/* pages/process/order-list/index.wxss */ \ No newline at end of file diff --git a/pages/process/station-create/index.js b/pages/process/station-create/index.js new file mode 100644 index 0000000..30ecb49 --- /dev/null +++ b/pages/process/station-create/index.js @@ -0,0 +1,130 @@ +import { commitBusiness, getPaperList } from "../../../api/ztb" +const util = require('../../../utils/util') +const math = require('../../../utils/math') +const wxmap = require('../../../libs/wxmap.js') +const app = getApp() + +Page({ + data: { + cateList: [], + form: {}, + imgList: [null, null], + requesting: false, + cateString: '', + cateArray: [], + focus: false, + visible: false + }, + onLoad: function (options) { + wx.showLoading({ title: '加载中', mask: true }) + if(app.nowLocation){ + this.setForm() + } else { + var that = this + wx.getLocation({ + type: 'gcj02', + success (res) { + app.nowLocation = res + wxmap.geocoder(app.nowLocation.latitude, app.nowLocation.longitude).then(resp => { + app.nowLocation.cityName = resp.result.address_component.city.replace('市', '') + app.nowLocation.cityCode = resp.result.ad_info.city_code.replace('156', '') + app.nowLocation.address = resp.result.address + app.nowLocation.districtCode = resp.result.ad_info.adcode + that.setForm() + }) + } + }) + } + var sHeight = parseInt(math.times(app.globalData.fragmentHeight, 0.5)) + getPaperList({ type: 2 }).then(result => { + this.setData({ cateList: result.data, sHeight }) + }).catch(err => { + this.setData({ sHeight }) + }) + }, + setForm: function(){ + this.data.form.latitude = parseFloat(app.nowLocation.latitude.toFixed(6)) + this.data.form.longitude = parseFloat(app.nowLocation.longitude.toFixed(6)) + this.data.form.locCityName = app.nowLocation.cityName + this.data.form.locCityId = app.nowLocation.cityCode + this.data.form.locDistrictId = app.nowLocation.districtCode + this.data.form.address = app.nowLocation.address + }, + bindInput: function(e){ + this.data.form.name = e.detail.value + }, + onImageLoad: function({detail}){ + console.log(detail) + if(detail && detail.width){ + var radio = math.divide(detail.width, 750) + var height = parseInt(math.divide(detail.height, radio)) + this.setData({ height }) + } + wx.hideLoading() + }, + selectCategroy: function(){ + this.setData({ visible: true, focus: false }) + }, + clickItem: function(e){ + var index = Number(e.currentTarget.dataset.index) + var item = this.data.cateList[index] + this.setData({ ['cateList[' + index + '].checked']: !item.checked }) + }, + onClose: function(){ + this.setData({ visible: false }) + }, + onConfirm: function(){ + var cateString = null + this.data.form.categoryIds = [] + for (let index = 0; index < this.data.cateList.length; index++) { + const element = this.data.cateList[index] + if(element.checked){ + this.data.form.categoryIds.push(element.id) + if(util.isEmpty(cateString)){ + cateString = element.name + } else { + cateString += ';' + element.name + } + } + } + this.setData({ cateString, visible: false }) + }, + submitForm: function(){ + if(this.data.requesting){ + return + } + if(util.isEmpty(this.data.form.name)){ + util.showToast('请输入你的打包站名称') + return + } + if(util.isEmpty(this.data.form.categoryIds)){ + util.showToast('请选择你的主营品类') + return + } + if(util.isEmpty(this.data.form.factoryPhotoUrls)){ + util.showToast('请上传门头、招牌、场地等照片') + return + } + if(util.isEmpty(this.data.form.weightNotePhotoUrls)){ + util.showToast('请上传3天内的磅单照片') + return + } + this.setData({ requesting: true }) + wx.showLoading({ title: '处理中', mask: true }) + commitBusiness(this.data.form).then(res => { + wx.hideLoading() + app.userInfo.isCommittedPackingFactoryClue = 1 + util.showBackToast('信息完善成功') + }).catch(err => { + wx.hideLoading() + this.setData({ requesting: false }) + util.showToast(err) + }) + }, + beforeChoose: function(e){ + this.setData({ focus: false }) + }, + onImageUpload: function(e){ + console.log(e) + } +}) \ No newline at end of file diff --git a/pages/process/station-create/index.json b/pages/process/station-create/index.json new file mode 100644 index 0000000..5cd0d62 --- /dev/null +++ b/pages/process/station-create/index.json @@ -0,0 +1,11 @@ +{ + "usingComponents": { + "van-image": "/components/image/index", + "van-loading": "/components/loading/index", + "image-upload": "/components/image-upload/index", + "van-popup": "/components/popup/index", + "van-grid": "/components/grid/index", + "van-grid-item": "/components/grid-item/index", + "van-button": "/components/button/index" + } +} \ No newline at end of file diff --git a/pages/process/station-create/index.wxml b/pages/process/station-create/index.wxml new file mode 100644 index 0000000..0431caf --- /dev/null +++ b/pages/process/station-create/index.wxml @@ -0,0 +1,94 @@ + + 完善信息 + + + + + + + + + 为了更好的服务你,和确保数据真实性 + 请你完成以下资料填写 + + + + + + + + 仅用于完善打包站信息 + + + + *包站名称 + + + + *主营品类 + + + + + *包站实地照片 + (请上传门头、招牌、场地等照片) + + + + + + + 示例图: + + + + + + + + + *磅单照片 + (请上传3天内的磅单照片) + + + + + + + 示例图: + + + + + + + + + 提交 + + + + + + + + + 取消 + 选择纸品 + 确定 + + + + + + {{item.name}} + + + + \ No newline at end of file diff --git a/pages/process/station-create/index.wxss b/pages/process/station-create/index.wxss new file mode 100644 index 0000000..490d626 --- /dev/null +++ b/pages/process/station-create/index.wxss @@ -0,0 +1,64 @@ +.relative{ + height: 100%; + width: 100%; + position: relative; +} + +.container { + width: 100%; + flex-direction: column; + position: absolute; + left: 0rpx; + top: 0rpx; + z-index: 11; +} + + +.image-reader-item { + position: relative; + width: 99%; + height: 100%; + background-color: #f8f8f8; + box-sizing: border-box; + list-style: none; + background-size: cover; + border-radius: 6rpx; +} + +.image-reader-item .md-icon { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0.5; +} + +.image-reader-item .md-load { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.image-reader-item .md-hint { + position: absolute; + top: 50%; + left: 0; + width: 100%; + margin-top: 10px; + font-size: 12px; + color: #bababa; + text-align: center; +} + +.image-reader-item .delete { + position: absolute; + top: 0px; + right: 0px; + opacity: 0.8; + border-top-right-radius: 6rpx; + border-bottom-left-radius: 8rpx; + padding: 6rpx 12rpx; + height: auto; + background-color: rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/pages/process/station-info/index.js b/pages/process/station-info/index.js new file mode 100644 index 0000000..28fbf97 --- /dev/null +++ b/pages/process/station-info/index.js @@ -0,0 +1,27 @@ +import { getStationInfo } from "../../../api/ztb" +const util = require('../../../utils/util') +const app = getApp() + +Page({ + data: { + height: app.globalData.fragmentHeight, + factoryInfo: null + }, + onLoad: function (options) { + if(options.id){ + wx.showLoading({ title: '正在处理', mask: true }) + var params = {factoryId: options.id} + if(app.nowLocation){ + params.personalLatitude = app.nowLocation.latitude + params.personalLongitude = app.nowLocation.longitude + } + getStationInfo(params).then(result => { + this.setData({factoryInfo: result.data, height: app.globalData.fragmentHeight}) + wx.hideLoading() + }).catch(err => { + wx.hideLoading() + util.showToast(err) + }) + } + } +}) \ No newline at end of file diff --git a/pages/process/station-info/index.json b/pages/process/station-info/index.json new file mode 100644 index 0000000..e849ebd --- /dev/null +++ b/pages/process/station-info/index.json @@ -0,0 +1,9 @@ +{ + "usingComponents": { + "van-image": "/components/image/index", + "van-tag": "/components/tag/index", + "van-cell": "/components/cell/index", + "van-button": "/components/button/index", + "station-item": "/pages/elements/station-item/index" + } +} \ No newline at end of file diff --git a/pages/process/station-info/index.wxml b/pages/process/station-info/index.wxml new file mode 100644 index 0000000..5bc1b34 --- /dev/null +++ b/pages/process/station-info/index.wxml @@ -0,0 +1,86 @@ + + + 打包站详情 + + + + + + + + + + {{factoryInfo.name}} + {{factoryInfo.distance}}km + + + + {{factoryInfo.locDetail}} + + + 月出货量:{{factoryInfo.categoryProductionCapacityPerMonth}}吨 + 最近出货:{{factoryInfo.recentlyShipmentsPaperMill}} + + + 场地面积:{{factoryInfo.packageFactoryArea}}㎡ + 打包机型号:{{factoryInfo.packerType || '- -'}} + + + + + + + + + 出货品类: + + {{item}} + + + + + + + + 联系人:{{factoryInfo.responsiblePersonName}} + {{factoryInfo.responsiblePersonMobile || ''}} + + + + + 最近出货 + + + + 时间 + 品类 + 重量(吨) + 渠道 + 扣点(%) + + + 1个月前 + 纺线管(长小管) + 26.56 + 江门**纸厂 + 12.6 + + + + + 暂无数据 + + + + + + 周边包站 + + + + 暂无周边包站数据 + + + + + \ No newline at end of file diff --git a/pages/process/station-info/index.wxss b/pages/process/station-info/index.wxss new file mode 100644 index 0000000..b7118a8 --- /dev/null +++ b/pages/process/station-info/index.wxss @@ -0,0 +1,14 @@ +.tag{ + margin-right: 12rpx; + padding: 4rpx 12rpx; + background-color: #F4F4F4; + font-size: 22rpx; + color: #888888; + border-radius: 4rpx; + text-align: center; +} + +.contract{ + justify-content: flex-start; + padding: 0rpx 32rpx 16rpx 32rpx; +} \ No newline at end of file diff --git a/pages/process/store-info/index.js b/pages/process/store-info/index.js new file mode 100644 index 0000000..28fbf97 --- /dev/null +++ b/pages/process/store-info/index.js @@ -0,0 +1,27 @@ +import { getStationInfo } from "../../../api/ztb" +const util = require('../../../utils/util') +const app = getApp() + +Page({ + data: { + height: app.globalData.fragmentHeight, + factoryInfo: null + }, + onLoad: function (options) { + if(options.id){ + wx.showLoading({ title: '正在处理', mask: true }) + var params = {factoryId: options.id} + if(app.nowLocation){ + params.personalLatitude = app.nowLocation.latitude + params.personalLongitude = app.nowLocation.longitude + } + getStationInfo(params).then(result => { + this.setData({factoryInfo: result.data, height: app.globalData.fragmentHeight}) + wx.hideLoading() + }).catch(err => { + wx.hideLoading() + util.showToast(err) + }) + } + } +}) \ No newline at end of file diff --git a/pages/process/store-info/index.json b/pages/process/store-info/index.json new file mode 100644 index 0000000..e849ebd --- /dev/null +++ b/pages/process/store-info/index.json @@ -0,0 +1,9 @@ +{ + "usingComponents": { + "van-image": "/components/image/index", + "van-tag": "/components/tag/index", + "van-cell": "/components/cell/index", + "van-button": "/components/button/index", + "station-item": "/pages/elements/station-item/index" + } +} \ No newline at end of file diff --git a/pages/process/store-info/index.wxml b/pages/process/store-info/index.wxml new file mode 100644 index 0000000..ff9ddf4 --- /dev/null +++ b/pages/process/store-info/index.wxml @@ -0,0 +1,86 @@ + + + 我的店铺 + + + + + + + + + + {{factoryInfo.name}} + {{factoryInfo.distance}}km + + + + {{factoryInfo.locDetail}} + + + 月出货量:{{factoryInfo.categoryProductionCapacityPerMonth}}吨 + 最近出货:{{factoryInfo.recentlyShipmentsPaperMill}} + + + 场地面积:{{factoryInfo.packageFactoryArea}}㎡ + 打包机型号:{{factoryInfo.packerType || '- -'}} + + + + + + + + + 出货品类: + + {{item}} + + + + + + + + 联系人:{{factoryInfo.responsiblePersonName}} + {{factoryInfo.responsiblePersonMobile || ''}} + + + + + 最近出货 + + + + 时间 + 品类 + 重量(吨) + 渠道 + 扣点(%) + + + 1个月前 + 纺线管(长小管) + 26.56 + 江门**纸厂 + 12.6 + + + + + 暂无数据 + + + + + + 周边包站 + + + + 暂无周边包站数据 + + + + + \ No newline at end of file diff --git a/pages/process/store-info/index.wxss b/pages/process/store-info/index.wxss new file mode 100644 index 0000000..b7118a8 --- /dev/null +++ b/pages/process/store-info/index.wxss @@ -0,0 +1,14 @@ +.tag{ + margin-right: 12rpx; + padding: 4rpx 12rpx; + background-color: #F4F4F4; + font-size: 22rpx; + color: #888888; + border-radius: 4rpx; + text-align: center; +} + +.contract{ + justify-content: flex-start; + padding: 0rpx 32rpx 16rpx 32rpx; +} \ No newline at end of file diff --git a/pages/station/index.js b/pages/station/index.js new file mode 100644 index 0000000..c8b8552 --- /dev/null +++ b/pages/station/index.js @@ -0,0 +1,47 @@ +const app = getApp() + +Page({ + data: { + safeBottom: app.globalData.safeBottom, + fHeight: app.globalData.safeFragmentHeight, + tabList: [ + { value: 'store', badge: 0, name: '工作台', blue: '/assets/icon/mall-blue.png', gray: '/assets/icon/mall-gray.png' }, + { value: 'package', badge: 0, name: '我的', blue: '/assets/icon/home-blue.png', gray: '/assets/icon/home-gray.png' } + ], + tabIndex: 0, + }, + onLoad: function (options) { + if (options.url) { + var path = options.url + if (options.key && options.value) { + path += '?' + options.key + '=' + options.value + } + wx.navigateTo({ url: path }) + } + const fHeight = (app.globalData.safeFragmentHeight + app.globalData.statusBarHeight) - 100 + this.setData({ + fHeight: fHeight, + safeBottom: app.globalData.safeBottom, + cityName: this.data.cityName, + customHeight: app.globalData.customHeight, + customWidth: app.globalData.Custom.left, + StatusBar: app.globalData.StatusBar || 40, + }) + }, + onTabClick: function(e){ + if(this.data.tabIndex == e.currentTarget.dataset.index){ + return + } + this.setData({ tabIndex: e.currentTarget.dataset.index }) + this.onShow() + }, + stopTouchMove: function(e){ + return false + }, + onShow: function () { + var pageView = this.selectComponent('#' + this.data.tabList[this.data.tabIndex].value) + if (pageView && pageView.onRestart) { + pageView.onRestart() + } + }, +}) \ No newline at end of file diff --git a/pages/station/index.json b/pages/station/index.json new file mode 100644 index 0000000..0735884 --- /dev/null +++ b/pages/station/index.json @@ -0,0 +1,9 @@ +{ + "usingComponents": { + "store": "/pages/fragments/store-list/index", + "package": "/pages/fragments/package-station/index", + "van-icon": "/components/icon/index", + "van-tabbar": "/components/tabbar/index", + "van-tabbar-item": "/components/tabbar-item/index" + } +} \ No newline at end of file diff --git a/pages/station/index.wxml b/pages/station/index.wxml new file mode 100644 index 0000000..d50a9f7 --- /dev/null +++ b/pages/station/index.wxml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + {{item.name}} + + + \ No newline at end of file diff --git a/pages/station/index.wxss b/pages/station/index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..31b9118 --- /dev/null +++ b/project.config.json @@ -0,0 +1,78 @@ +{ + "description": "项目配置文件", + "packOptions": { + "ignore": [] + }, + "setting": { + "urlCheck": true, + "es6": false, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useIsolateContext": false, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "minifyWXML": true, + "showES6CompileOption": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "libVersion": "2.21.1", + "appid": "wx2a357cf9428b2f41", + "projectname": "ztb-merchant-mini", + "debugOptions": { + "hidedInDevtools": [] + }, + "isGameTourist": false, + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "scripts": { + "beforeCompile": "" + }, + "condition": { + "plugin": { + "list": [] + }, + "game": { + "list": [] + }, + "gamePlugin": { + "list": [] + }, + "miniprogram": { + "list": [ + { + "name": "pages/login/index", + "pathName": "pages/login/index", + "query": "", + "scene": 1047 + } + ] + } + } +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/utils/event.js b/utils/event.js new file mode 100644 index 0000000..937050b --- /dev/null +++ b/utils/event.js @@ -0,0 +1,40 @@ +var events = {} + +function on(name, self, callback) { + var tuple = [self, callback] + var callbacks = events[name] + if (Array.isArray(callbacks)) { + callbacks.push(tuple) + } else { + events[name] = [tuple] + } +} + +function remove(name, self) { + var callbacks = events[name] + if (Array.isArray(callbacks)) { + events[name] = callbacks.filter((tuple) => { + return tuple[0] != self + }) + } +} + +function emit(name, data) { + var callbacks = events[name] + if (Array.isArray(callbacks)) { + callbacks.map((tuple) => { + var self = tuple[0] + var callback = tuple[1] + callback.call(self, data) + }) + } +} + +exports.on = on +exports.remove = remove +exports.emit = emit +/**** + * Event:what说明:200表示vip兑换或者购买成功 + * + * + */ \ No newline at end of file diff --git a/utils/math.js b/utils/math.js new file mode 100644 index 0000000..674a436 --- /dev/null +++ b/utils/math.js @@ -0,0 +1,149 @@ +/** + * https://github.com/nefe/number-precision + */ + +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +/** + * @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。 + * 问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998 + */ +/** + * 把错误的数据转正 + * strip(0.09999999999999998)=0.1 + */ +function strip(num, precision) { + if (precision === void 0) { + precision = 12; + } + return +parseFloat(num.toPrecision(precision)); +} +/** + * Return digits length of a number + * @param {*number} num Input number + */ +function digitLength(num) { + // Get digit length of e + var eSplit = num.toString().split(/[eE]/); + var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0)); + return len > 0 ? len : 0; +} +/** + * 把小数转成整数,支持科学计数法。如果是小数则放大成整数 + * @param {*number} num 输入数 + */ +function float2Fixed(num) { + if (num.toString().indexOf('e') === -1) { + return Number(num.toString().replace('.', '')); + } + var dLen = digitLength(num); + return dLen > 0 ? strip(num * Math.pow(10, dLen)) : num; +} +/** + * 检测数字是否越界,如果越界给出提示 + * @param {*number} num 输入数 + */ +function checkBoundary(num) { + if (_boundaryCheckingState) { + if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) { + console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate"); + } + } +} +/** + * 精确乘法 + */ +function times(num1, num2) { + var others = []; + for (var _i = 2; _i < arguments.length; _i++) { + others[_i - 2] = arguments[_i]; + } + if (others.length > 0) { + return times.apply(void 0, [times(num1, num2), others[0]].concat(others.slice(1))); + } + var num1Changed = float2Fixed(num1); + var num2Changed = float2Fixed(num2); + var baseNum = digitLength(num1) + digitLength(num2); + var leftValue = num1Changed * num2Changed; + checkBoundary(leftValue); + return leftValue / Math.pow(10, baseNum); +} +/** + * 精确加法 + */ +function plus(num1, num2) { + var others = []; + for (var _i = 2; _i < arguments.length; _i++) { + others[_i - 2] = arguments[_i]; + } + if (others.length > 0) { + return plus.apply(void 0, [plus(num1, num2), others[0]].concat(others.slice(1))); + } + var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); + return (times(num1, baseNum) + times(num2, baseNum)) / baseNum; +} +/** + * 精确减法 + */ +function minus(num1, num2) { + var others = []; + for (var _i = 2; _i < arguments.length; _i++) { + others[_i - 2] = arguments[_i]; + } + if (others.length > 0) { + return minus.apply(void 0, [minus(num1, num2), others[0]].concat(others.slice(1))); + } + var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); + return (times(num1, baseNum) - times(num2, baseNum)) / baseNum; +} +/** + * 精确除法 + */ +function divide(num1, num2) { + var others = []; + for (var _i = 2; _i < arguments.length; _i++) { + others[_i - 2] = arguments[_i]; + } + if (others.length > 0) { + return divide.apply(void 0, [divide(num1, num2), others[0]].concat(others.slice(1))); + } + var num1Changed = float2Fixed(num1); + var num2Changed = float2Fixed(num2); + checkBoundary(num1Changed); + checkBoundary(num2Changed); + return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1))); +} +/** + * 四舍五入 + */ +function round(num, ratio) { + var base = Math.pow(10, ratio); + return divide(Math.round(times(num, base)), base); +} +var _boundaryCheckingState = true; +/** + * 是否进行边界检查,默认开启 + * @param flag 标记开关,true 为开启,false 为关闭,默认为 true + */ +function enableBoundaryChecking(flag) { + if (flag === void 0) { + flag = true; + } + _boundaryCheckingState = flag; +} + +module.exports = { + strip: strip, + plus: plus, + minus: minus, + times: times, + divide: divide, + round: round, + digitLength: digitLength, + float2Fixed: float2Fixed, + enableBoundaryChecking: enableBoundaryChecking +} \ No newline at end of file diff --git a/utils/storage.js b/utils/storage.js new file mode 100644 index 0000000..57eb42b --- /dev/null +++ b/utils/storage.js @@ -0,0 +1,48 @@ +/** + * 获取缓存 + * @param String $key key + * @param String $def 若想要无缓存时,返回默认值则get('key','默认值')(支持字符串、json、数组、boolean等等) + * @return value; + */ + function get (key, def = '') { + const timeout = parseInt(wx.getStorageSync(`${key}__separator__`) || 0); + // 过期失效 + if (timeout) { + if (Date.now() > timeout) { + this.remove(key); + return; + } + } + let value = wx.getStorageSync(key); + return value ? value : def; +} + +/** + * 设置缓存 + * @param String $key key + * @param String $value value(支持字符串、json、数组、boolean等等) + * @param Number $timeout 过期时间(单位:分钟)不设置时间即为永久保存 + * @return value; + */ +function put (key, value, timeout = 0) { + let _timeout = parseInt(timeout); + wx.setStorageSync(key, value); + if (_timeout) { + wx.setStorageSync(`${key}__separator__`, Date.now() + 1000 * 60 * _timeout); + } else { + wx.removeStorageSync(`${key}__separator__`); + } + return value; +} + +function remove (key) { + wx.removeStorageSync(key); + wx.removeStorageSync(`${key}__separator__`); + return undefined; +} + +module.exports = { + remove: remove, + put: put, + get: get +} \ No newline at end of file diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..2213c9d --- /dev/null +++ b/utils/util.js @@ -0,0 +1,246 @@ +const app = getApp() + +const formatTime = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : '0' + n +} + +function beforeDay(day, format) { + var date = new Date() + var formateArr = ['Y', 'M', 'D', 'h', 'm', 's']; + var returnArr = []; + returnArr.push(date.getFullYear()); + returnArr.push(formatNumber(date.getMonth() + 1)); + returnArr.push(formatNumber(date.getDate() - day)); + returnArr.push(formatNumber(date.getHours())); + returnArr.push(formatNumber(date.getMinutes())); + returnArr.push(formatNumber(date.getSeconds())); + for (var i in returnArr) { + format = format.replace(formateArr[i], returnArr[i]); + } + return format; +} + +function formatDate(date, format) { + var formateArr = ['Y', 'M', 'D', 'h', 'm', 's']; + var returnArr = []; + returnArr.push(date.getFullYear()); + returnArr.push(formatNumber(date.getMonth() + 1)); + returnArr.push(formatNumber(date.getDate())); + returnArr.push(formatNumber(date.getHours())); + returnArr.push(formatNumber(date.getMinutes())); + returnArr.push(formatNumber(date.getSeconds())); + for (var i in returnArr) { + format = format.replace(formateArr[i], returnArr[i]); + } + return format; +} + +function json2Form(json) { + var str = []; + for (var p in json) { + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(json[p])); + } + return str.join("&"); +} + +function isEmpty(val) { + if(val === 'undefined' || val === null || val === undefined){ + return true + } + if(val){ + val = val.toString().replace(/\s+/g, '') + } + return val === '' +} + +function showToast(content) { + if (isEmpty(content)) { + return + } + wx.showToast({ + title: content, + icon: 'none' + }) +} + +function extend(obj) { + var o = {}, + attr = Array.prototype.slice.call(arguments).slice(1); + attr.forEach(function (val, index) { + if (val in obj) { + o[val] = obj[val]; + } + }); + return o; +} + +function playDing() { + const innerAudioContext = wx.createInnerAudioContext(); //新建一个createInnerAudioContext(); + innerAudioContext.autoplay = true; //音频自动播放设置 + innerAudioContext.src = '/assets/raw/ptt_playfinish.mp3'; //链接到音频的地址 + innerAudioContext.onPlay(() => {}); //播放音效 + innerAudioContext.onError((res) => { //打印错误 + }) +} + +function showBackToast(content) { + if (isEmpty(content)) { + return + } + wx.showToast({ + title: content, + icon: 'none', + duration: 1000, + success: function () { + setTimeout(function () { + wx.navigateBack() + }, 1000) + } + }) +} + +/* 验证手机号 */ +function checkPhone(phone) { + var re = /^1\d{10}$/ + return re.test(phone) && phone.length === 11 +} + +function checkId(id) { + // 1 "验证通过!", 0 //校验不通过 // id为身份证号码 + var format = /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/; + //号码规则校验 + if (!format.test(id)) { + return { + 'status': 0, + 'msg': '身份证号码不合规' + }; + } + //区位码校验 + //出生年月日校验 前正则限制起始年份为1900; + var year = id.substr(6, 4), //身份证年 + month = id.substr(10, 2), //身份证月 + date = id.substr(12, 2), //身份证日 + time = Date.parse(month + '-' + date + '-' + year), //身份证日期时间戳date + now_time = Date.parse(new Date()), //当前时间戳 + dates = (new Date(year, month, 0)).getDate(); //身份证当月天数 + if (time > now_time || date > dates) { + return { + 'status': 0, + 'msg': '出生日期不合规' + } + } + //校验码判断 + var c = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //系数 + var b = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); //校验码对照表 + var id_array = id.split(""); + var sum = 0; + for (var k = 0; k < 17; k++) { + sum += parseInt(id_array[k]) * parseInt(c[k]); + } + if (id_array[17].toUpperCase() != b[sum % 11].toUpperCase()) { + return { status: 0, msg: '身份证校验码不合规' } + } + return { status: 1, msg: '校验通过' } +} + +const tokenList = [ + 'pages/agent/factory/index', + '/pages/home/info/index' +] + +function extendPage(path){ + let pages = getCurrentPages() + for (let index = 0; index < pages.length; index++) { + if(pages[index].route === path){ + return true + } + } + return false +} + +function navigateTo(url){ + if(url === '/pages/login/index'){ + if(!extendPage(url)){ + wx.navigateTo({ url: '/pages/login/index' }) + } + return + } + var white = false + for (let index = 0; index < tokenList.length; index++) { + if(url.indexOf(tokenList[index]) != -1){ + white = true + break + } + } + if(white && !app.userInfo){ + wx.navigateTo({ url: '/pages/login/index' }) + return + } + wx.navigateTo({ url }) +} + +function debounce(fn, interval) { + var timer; + var gapTime = interval || 1000;//间隔时间,如果interval不传,则默认1000ms + return function() { + clearTimeout(timer) + var context = this + var args = arguments//保存此处的arguments,因为setTimeout是全局的,arguments不是防抖函数需要的。 + timer = setTimeout(function() { + fn.call(context, args) + }, gapTime) + } +} + +/*函数节流*/ +function throttle(fn, interval) { + var enterTime = 0 //触发的时间 + var gap = interval || 300//间隔时间,如果interval不传,则默认300ms + return function() { + var backTime = Date.now()//第一次函数return即触发的时间 + if (backTime - enterTime > gap) { + fn.apply(this, arguments) + enterTime = backTime//赋值给第一次触发的时间,这样就保存了第二次触发的时间 + } + } +} + +function statDistance(lat1, lng1, lat2, lng2){ + var radLat1 = lat1 * Math.PI / 180.0; + var radLat2 = lat2 * Math.PI / 180.0; + var a = radLat1 - radLat2; + var b = lng1 * Math.PI / 180.0 - lng2*Math.PI / 180.0; + var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2))) + s = s * 6378.137 + s = Math.round(s * 10000) / 10000 + return s.toFixed(2); +} + +module.exports = { + isEmpty: isEmpty, + extend: extend, + formatTime: formatTime, + beforeDay: beforeDay, + formatDate: formatDate, + json2Form: json2Form, + showToast: showToast, + playDing: playDing, + showBackToast: showBackToast, + checkPhone: checkPhone, + checkId: checkId, + navigateTo: navigateTo, + debounce: debounce, + throttle: throttle, + statDistance: statDistance +} \ No newline at end of file