├── .eslintignore ├── .gitignore ├── App.vue ├── LICENSE ├── README.md ├── apis ├── README.md ├── index.js ├── modules │ ├── goods.js │ └── member.js └── service.js ├── components ├── README.md ├── address-list.vue ├── goods-comment.vue ├── goods-list.vue └── u-city-select.vue ├── main.js ├── manifest.json ├── package.json ├── pages.json ├── pages ├── article │ ├── index.vue │ └── view.vue ├── cart │ └── index.vue ├── center │ └── index.vue ├── classify │ └── index.vue ├── coupon │ └── index.vue ├── goods │ ├── comment.vue │ ├── details.vue │ ├── list.vue │ └── search.vue ├── index │ ├── forget.vue │ ├── index.vue │ ├── login.vue │ ├── msg.vue │ └── register.vue ├── member │ ├── address_edit.vue │ ├── address_list.vue │ ├── index.vue │ ├── my_coupon.vue │ ├── my_favorite.vue │ ├── order_details.vue │ ├── order_list.vue │ ├── order_service.vue │ ├── personal.vue │ ├── personal_ext.vue │ └── setting.vue ├── order │ ├── create.vue │ ├── pay.vue │ ├── select_address.vue │ ├── use_coupon.vue │ └── use_invoice.vue └── vuex_test │ └── index.vue ├── plugins ├── HM-filterDropdown.vue ├── README.md ├── luch-request │ ├── adapters │ │ └── index.js │ ├── core │ │ ├── InterceptorManager.js │ │ ├── Request.js │ │ ├── buildFullPath.js │ │ ├── defaults.js │ │ ├── dispatchRequest.js │ │ ├── mergeConfig.js │ │ └── settle.js │ ├── helpers │ │ ├── buildURL.js │ │ ├── combineURLs.js │ │ └── isAbsoluteURL.js │ ├── index.d.ts │ ├── index.js │ └── utils.js ├── uni-number-box │ └── uni-number-box.vue ├── uview-ui │ ├── LICENSE │ ├── README.md │ ├── components │ │ ├── u-action-sheet │ │ │ └── u-action-sheet.vue │ │ ├── u-alert-tips │ │ │ └── u-alert-tips.vue │ │ ├── u-avatar-cropper │ │ │ ├── u-avatar-cropper.vue │ │ │ └── weCropper.js │ │ ├── u-avatar │ │ │ └── u-avatar.vue │ │ ├── u-back-top │ │ │ └── u-back-top.vue │ │ ├── u-badge │ │ │ └── u-badge.vue │ │ ├── u-button │ │ │ └── u-button.vue │ │ ├── u-calendar │ │ │ └── u-calendar.vue │ │ ├── u-car-keyboard │ │ │ └── u-car-keyboard.vue │ │ ├── u-card │ │ │ └── u-card.vue │ │ ├── u-cell-group │ │ │ └── u-cell-group.vue │ │ ├── u-cell-item │ │ │ └── u-cell-item.vue │ │ ├── u-checkbox-group │ │ │ └── u-checkbox-group.vue │ │ ├── u-checkbox │ │ │ └── u-checkbox.vue │ │ ├── u-circle-progress │ │ │ └── u-circle-progress.vue │ │ ├── u-col │ │ │ └── u-col.vue │ │ ├── u-collapse-item │ │ │ └── u-collapse-item.vue │ │ ├── u-collapse │ │ │ └── u-collapse.vue │ │ ├── u-column-notice │ │ │ └── u-column-notice.vue │ │ ├── u-count-down │ │ │ └── u-count-down.vue │ │ ├── u-count-to │ │ │ └── u-count-to.vue │ │ ├── u-divider │ │ │ └── u-divider.vue │ │ ├── u-dropdown-item │ │ │ └── u-dropdown-item.vue │ │ ├── u-dropdown │ │ │ └── u-dropdown.vue │ │ ├── u-empty │ │ │ └── u-empty.vue │ │ ├── u-field │ │ │ └── u-field.vue │ │ ├── u-form-item │ │ │ └── u-form-item.vue │ │ ├── u-form │ │ │ └── u-form.vue │ │ ├── u-full-screen │ │ │ └── u-full-screen.vue │ │ ├── u-gap │ │ │ └── u-gap.vue │ │ ├── u-grid-item │ │ │ └── u-grid-item.vue │ │ ├── u-grid │ │ │ └── u-grid.vue │ │ ├── u-icon │ │ │ └── u-icon.vue │ │ ├── u-image │ │ │ └── u-image.vue │ │ ├── u-index-anchor │ │ │ └── u-index-anchor.vue │ │ ├── u-index-list │ │ │ └── u-index-list.vue │ │ ├── u-input │ │ │ └── u-input.vue │ │ ├── u-keyboard │ │ │ └── u-keyboard.vue │ │ ├── u-lazy-load │ │ │ └── u-lazy-load.vue │ │ ├── u-line-progress │ │ │ └── u-line-progress.vue │ │ ├── u-line │ │ │ └── u-line.vue │ │ ├── u-link │ │ │ └── u-link.vue │ │ ├── u-loading-page │ │ │ └── u-loading-page.vue │ │ ├── u-loading │ │ │ └── u-loading.vue │ │ ├── u-loadmore │ │ │ └── u-loadmore.vue │ │ ├── u-mask │ │ │ └── u-mask.vue │ │ ├── u-message-input │ │ │ └── u-message-input.vue │ │ ├── u-modal │ │ │ └── u-modal.vue │ │ ├── u-navbar │ │ │ └── u-navbar.vue │ │ ├── u-no-network │ │ │ └── u-no-network.vue │ │ ├── u-notice-bar │ │ │ └── u-notice-bar.vue │ │ ├── u-number-box │ │ │ └── u-number-box.vue │ │ ├── u-number-keyboard │ │ │ └── u-number-keyboard.vue │ │ ├── u-parse │ │ │ ├── libs │ │ │ │ ├── CssHandler.js │ │ │ │ ├── MpHtmlParser.js │ │ │ │ ├── config.js │ │ │ │ ├── handler.wxs │ │ │ │ └── trees.vue │ │ │ └── u-parse.vue │ │ ├── u-picker │ │ │ └── u-picker.vue │ │ ├── u-popup │ │ │ └── u-popup.vue │ │ ├── u-radio-group │ │ │ └── u-radio-group.vue │ │ ├── u-radio │ │ │ └── u-radio.vue │ │ ├── u-rate │ │ │ └── u-rate.vue │ │ ├── u-read-more │ │ │ └── u-read-more.vue │ │ ├── u-row-notice │ │ │ └── u-row-notice.vue │ │ ├── u-row │ │ │ └── u-row.vue │ │ ├── u-search │ │ │ └── u-search.vue │ │ ├── u-section │ │ │ └── u-section.vue │ │ ├── u-select │ │ │ └── u-select.vue │ │ ├── u-skeleton │ │ │ └── u-skeleton.vue │ │ ├── u-slider │ │ │ └── u-slider.vue │ │ ├── u-steps │ │ │ └── u-steps.vue │ │ ├── u-sticky │ │ │ └── u-sticky.vue │ │ ├── u-subsection │ │ │ └── u-subsection.vue │ │ ├── u-swipe-action │ │ │ └── u-swipe-action.vue │ │ ├── u-swiper │ │ │ └── u-swiper.vue │ │ ├── u-switch │ │ │ └── u-switch.vue │ │ ├── u-tabbar │ │ │ └── u-tabbar.vue │ │ ├── u-table │ │ │ └── u-table.vue │ │ ├── u-tabs-swiper │ │ │ └── u-tabs-swiper.vue │ │ ├── u-tabs │ │ │ └── u-tabs.vue │ │ ├── u-tag │ │ │ └── u-tag.vue │ │ ├── u-td │ │ │ └── u-td.vue │ │ ├── u-th │ │ │ └── u-th.vue │ │ ├── u-time-line-item │ │ │ └── u-time-line-item.vue │ │ ├── u-time-line │ │ │ └── u-time-line.vue │ │ ├── u-toast │ │ │ └── u-toast.vue │ │ ├── u-top-tips │ │ │ └── u-top-tips.vue │ │ ├── u-tr │ │ │ └── u-tr.vue │ │ ├── u-upload │ │ │ └── u-upload.vue │ │ ├── u-verification-code │ │ │ └── u-verification-code.vue │ │ └── u-waterfall │ │ │ └── u-waterfall.vue │ ├── iconfont.css │ ├── index.js │ ├── index.scss │ ├── libs │ │ ├── config │ │ │ ├── config.js │ │ │ └── zIndex.js │ │ ├── css │ │ │ ├── color.scss │ │ │ ├── common.scss │ │ │ ├── style.components.scss │ │ │ ├── style.h5.scss │ │ │ ├── style.mp.scss │ │ │ ├── style.nvue.scss │ │ │ └── style.vue.scss │ │ ├── function │ │ │ ├── $parent.js │ │ │ ├── addUnit.js │ │ │ ├── bem.js │ │ │ ├── color.js │ │ │ ├── colorGradient.js │ │ │ ├── debounce.js │ │ │ ├── deepClone.js │ │ │ ├── deepMerge.js │ │ │ ├── getParent.js │ │ │ ├── guid.js │ │ │ ├── md5.js │ │ │ ├── queryParams.js │ │ │ ├── random.js │ │ │ ├── randomArray.js │ │ │ ├── route.js │ │ │ ├── sys.js │ │ │ ├── test.js │ │ │ ├── throttle.js │ │ │ ├── timeFormat.js │ │ │ ├── timeFrom.js │ │ │ ├── toast.js │ │ │ ├── trim.js │ │ │ └── type2icon.js │ │ ├── mixin │ │ │ ├── mixin.js │ │ │ └── mpShare.js │ │ ├── request │ │ │ └── index.js │ │ ├── store │ │ │ └── index.js │ │ └── util │ │ │ ├── area.js │ │ │ ├── async-validator.js │ │ │ ├── city.js │ │ │ ├── emitter.js │ │ │ └── province.js │ ├── package.json │ └── theme.scss ├── vk-u-goods-sku-popup │ └── vk-u-goods-sku-popup.vue ├── vk-u-number-box │ └── vk-u-number-box.vue └── zhouWei-navBar │ ├── index.vue │ └── zhouWei-navBar.md ├── router └── index.js ├── static ├── README.md ├── css │ ├── login.scss │ └── member_order_list.scss ├── icon │ └── iconfont.css └── images │ ├── btn_sku_popup_close.png │ └── tabber │ ├── cart-a.png │ ├── cart.png │ ├── fenlei-a.png │ ├── fenlei.png │ ├── home-a.png │ ├── home.png │ ├── user-a.png │ └── user.png ├── store ├── README.md ├── index.js └── modules │ └── test.js ├── template.h5.html ├── uni.scss ├── utils ├── README.md ├── classify.data.js ├── index.js └── modules │ └── article.js └── vue.config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | unpackage 2 | node_modules 3 | uview-ui 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /unpackage 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | 24 | package-lock.json 25 | yarn.lock 26 | -------------------------------------------------------------------------------- /App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## gdshop 商城 uniapp 版 2 | 3 | 基于uviewUI 1.x 开发的商城 4 | 5 | 包含基本商城所需的界面,后面会继续完善 6 | 7 | ## 用到的组件 8 | 1. uviewUI做基础UI框架 9 | 1. uni-simple-router 做路由管理 10 | 1. uni-read-pages 自动构建路由表 11 | 1. luch-request 做请求管理 12 | 1. vk-u-goods-sku-popup 商品详情SKU弹窗 13 | 1. zhouWei-navBar 自定义头部 14 | 1. HM-filterDropdown 下来筛选组件 15 | 16 | 17 | ## 适配测试 18 | 19 | 1. H5 20 | 1. 微信小程序 21 | 22 | ## 目录结构 23 | ``` 24 | ├─apis // API统一管理目录 25 | │ └─modules // API模块目录 26 | ├─components // 自己开发的组件 27 | ├─node_modules // node依赖包 28 | ├─pages // 页面目录 29 | │ ├─article 30 | │ ├─cart 31 | │ ├─center 32 | │ ├─classify 33 | │ ├─coupon 34 | │ ├─goods 35 | │ ├─index 36 | │ ├─member 37 | │ ├─order 38 | │ └─vuex_test 39 | ├─plugins // 外部引用的插件 40 | │ ├─luch-request 41 | │ ├─uni-number-box 42 | │ ├─uview-ui 43 | │ ├─vk-u-goods-sku-popup 44 | │ ├─vk-u-number-box 45 | │ └─zhouWei-navBar 46 | ├─router // 路由统一管理目录 47 | ├─static // 静态资源目录,除非必要墙裂建议放到外部加载 48 | │ ├─css // 存放样式 49 | │ ├─icon // 存放图标 50 | │ └─images // 存放图片 51 | │ └─tabber 52 | ├─store // vuex 目录 53 | │ └─modules // vuex 模块 54 | └─utils // 自己写的工具方法 55 | └─modules // 工具方法模块 56 | 57 | ``` 58 | 59 | ## 安装使用 60 | 61 | 1. 下载、解压 62 | 1. 在项目根目录运行 npm install ,安装node依赖包 63 | 2. 使用 HBuilderX 打开即可运行 64 | 65 | ## 预览图 66 | 67 | ![01](http://kuke365-img.winlo.net/project_demo/gdshop/01.png) 68 | ![02](http://kuke365-img.winlo.net/project_demo/gdshop/02.png) 69 | ![03](http://kuke365-img.winlo.net/project_demo/gdshop/03.png) 70 | ![04](http://kuke365-img.winlo.net/project_demo/gdshop/04.png) 71 | ![05](http://kuke365-img.winlo.net/project_demo/gdshop/05.png) 72 | ![06](http://kuke365-img.winlo.net/project_demo/gdshop/06.png) 73 | ![07](http://kuke365-img.winlo.net/project_demo/gdshop/07.png) 74 | ![08](http://kuke365-img.winlo.net/project_demo/gdshop/08.png) 75 | ![09](http://kuke365-img.winlo.net/project_demo/gdshop/09.png) 76 | ![10](http://kuke365-img.winlo.net/project_demo/gdshop/10.png) 77 | ![11](http://kuke365-img.winlo.net/project_demo/gdshop/11.png) 78 | ![12](http://kuke365-img.winlo.net/project_demo/gdshop/12.png) 79 | ![13](http://kuke365-img.winlo.net/project_demo/gdshop/13.png) 80 | ![14](http://kuke365-img.winlo.net/project_demo/gdshop/14.png) 81 | ![15](http://kuke365-img.winlo.net/project_demo/gdshop/15.png) 82 | ![16](http://kuke365-img.winlo.net/project_demo/gdshop/16.png) 83 | 84 | ## 交流QQ群 85 | 86 | QQ群:822176616 87 | 88 | ![QQ群:822176616](http://kuke365-img.winlo.net/project_demo/gdshop/gdshop_qun.png) 89 | 90 | 91 | 92 | ## 感谢 93 | 94 | 1. uniapp 95 | 1. uviewUI 96 | 1. uni-simple-router 97 | 1. uni-read-pages 98 | 1. luch-request 99 | 1. vk-u-goods-sku-popup 100 | 1. zhouWei-navBar 101 | 1. HM-filterDropdown 102 | -------------------------------------------------------------------------------- /apis/README.md: -------------------------------------------------------------------------------- 1 | 全部API定义目录 -------------------------------------------------------------------------------- /apis/index.js: -------------------------------------------------------------------------------- 1 | import http from './service' 2 | 3 | const files = require.context('./modules', false, /\.js$/) 4 | 5 | let api = {} 6 | files.keys().map(key => { 7 | api[key.replace(/(\.\/|\.js)/g, '')] = files(key).default(http) 8 | }) 9 | export default api 10 | -------------------------------------------------------------------------------- /apis/modules/goods.js: -------------------------------------------------------------------------------- 1 | export default ( http ) => ({ 2 | details (query = {}) { 3 | return http.request({ 4 | method: 'GET', 5 | url: '/goods/details', 6 | params: query 7 | }) 8 | }, 9 | test () { 10 | return 'test' 11 | } 12 | }) -------------------------------------------------------------------------------- /apis/modules/member.js: -------------------------------------------------------------------------------- 1 | export default ( http ) => ({ 2 | login (query = {}) { 3 | return http.request({ 4 | method: 'POST', 5 | url: '/configs/get_pager', 6 | params: query 7 | }) 8 | }, 9 | test () { 10 | return 'test' 11 | } 12 | }) -------------------------------------------------------------------------------- /apis/service.js: -------------------------------------------------------------------------------- 1 | import Request from '@/plugins/luch-request/index.js' 2 | 3 | // 初始化 4 | const http = new Request() 5 | // 设置公共参数 6 | http.config.baseURL = 'http://127.0.0.1:8181' 7 | 8 | // 请求前拦截 9 | http.interceptors.request.use((config) => { // 可使用async await 做异步操作 10 | config.header = { 11 | ...config.header, 12 | a: 1 // 演示拦截器header加参 13 | } 14 | // 演示custom 用处 15 | // if (config.custom.auth) { 16 | // config.header.token = 'token' 17 | // } 18 | // if (config.custom.loading) { 19 | // uni.showLoading() 20 | // } 21 | /** 22 | /* 演示 23 | if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求 24 | return Promise.reject(config) 25 | } 26 | **/ 27 | return config 28 | }, config => { // 可使用async await 做异步操作 29 | return Promise.reject(config) 30 | }) 31 | 32 | // 返回拦截 33 | http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/ 34 | // if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject() 35 | // return Promise.reject(response) // return Promise.reject 可使promise状态进入catch 36 | // if (response.config.custom.verification) { // 演示自定义参数的作用 37 | // return response.data 38 | // } 39 | const dataAxios = response.data 40 | if (dataAxios.code === 0) { 41 | // 正常返回数据 42 | return dataAxios.data 43 | } else { 44 | const error = new Error(dataAxios.msg) 45 | // 需要重新登录 46 | // 10001 - 无效的 token 47 | // 10002 - 其它客户端登录 48 | // 10003 - token 过期 49 | if ([ 50 | 10001, 51 | 10002, 52 | 10003 53 | ].indexOf(dataAxios.code) >= 0) { 54 | Notification.error({ 55 | title: '身份验证失败', 56 | message: '请重新登录' 57 | }) 58 | // 执行退出方法 59 | // await store.dispatch('d2admin/user/logout', { focus: true, remote: false, back: true }) 60 | } else { 61 | log(error) 62 | } 63 | return Promise.reject(error) 64 | } 65 | }, (response) => { /* 对响应错误做点什么 (statusCode !== 200)*/ 66 | console.log(response) 67 | return Promise.reject(response) 68 | }) 69 | 70 | export default http -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | 通用组件目录,组件通常是自己系统开发的 -------------------------------------------------------------------------------- /components/address-list.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 71 | 72 | 149 | -------------------------------------------------------------------------------- /components/goods-list.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 51 | 52 | 113 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import Store from '@/store' 4 | import Api from '@/apis' 5 | import router from './router' 6 | import { RouterMount } from 'uni-simple-router' 7 | 8 | Vue.config.productionTip = false 9 | 10 | App.mpType = 'app' 11 | Vue.prototype.$store = Store 12 | Vue.prototype.$myRouter = router 13 | Vue.prototype.$api = Api 14 | // 引入全局uView 15 | import uView from 'plugins/uview-ui' 16 | Vue.use(uView); 17 | 18 | const app = new Vue({ 19 | Store, 20 | ...App 21 | }) 22 | 23 | // #ifdef H5 24 | RouterMount(app,'#app'); 25 | // #endif 26 | 27 | // #ifndef H5 28 | app.$mount(); //为了兼容小程序及app端必须这样写才有效果 29 | // #endif 30 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "gdshop商城", 3 | "appid" : "", 4 | "description" : "gdshop商城", 5 | "versionName" : "1.0.0", 6 | "versionCode" : "100", 7 | "transformPx" : false, 8 | /* 5+App特有相关 */ 9 | "app-plus" : { 10 | "safearea" : { 11 | "bottom" : { 12 | "offset" : "none" 13 | } 14 | }, 15 | "usingComponents" : true, 16 | "nvueCompiler" : "uni-app", 17 | "compilerVersion" : 3, 18 | "splashscreen" : { 19 | "alwaysShowBeforeRender" : true, 20 | "waiting" : true, 21 | "autoclose" : true, 22 | "delay" : 0 23 | }, 24 | /* 模块配置 */ 25 | "modules" : {}, 26 | /* 应用发布信息 */ 27 | "distribute" : { 28 | /* android打包配置 */ 29 | "android" : { 30 | "permissions" : [ 31 | "", 32 | "", 33 | "", 34 | "", 35 | "", 36 | "", 37 | "", 38 | "", 39 | "", 40 | "", 41 | "", 42 | "", 43 | "", 44 | "", 45 | "", 46 | "", 47 | "", 48 | "", 49 | "", 50 | "", 51 | "", 52 | "" 53 | ] 54 | }, 55 | /* ios打包配置 */ 56 | "ios" : {}, 57 | /* SDK配置 */ 58 | "sdkConfigs" : {}, 59 | "splashscreen" : { 60 | "androidStyle" : "common" 61 | } 62 | } 63 | }, 64 | /* 快应用特有相关 */ 65 | "quickapp" : {}, 66 | /* 小程序特有相关 */ 67 | "mp-weixin" : { 68 | "appid" : "", 69 | "setting" : { 70 | "urlCheck" : false 71 | }, 72 | "usingComponents" : true 73 | }, 74 | "mp-alipay" : { 75 | "usingComponents" : true 76 | }, 77 | "mp-baidu" : { 78 | "usingComponents" : true 79 | }, 80 | "mp-toutiao" : { 81 | "usingComponents" : true 82 | }, 83 | "h5" : { 84 | "template" : "template.h5.html", 85 | "router" : { 86 | "mode" : "history" 87 | }, 88 | "title" : "gdbase6商城", 89 | "optimization" : { 90 | "treeShaking" : { 91 | "enable" : true 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gdshop-uniapp", 3 | "version": "1.0.0", 4 | "description": "gdshop商城", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://gitee.com/hackchen/gdbase6-shop-uniapp.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "@holyhigh/func.js": "^0.1.2", 18 | "uni-read-pages": "^1.0.5", 19 | "uni-simple-router": "^1.5.5", 20 | "vuex": "^3.5.1", 21 | "vuex-persistedstate": "^4.0.0-beta.1" 22 | }, 23 | "devDependencies": { 24 | "@types/uni-app": "^1.4.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pages/article/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /pages/article/view.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /pages/center/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 30 | 31 | 63 | -------------------------------------------------------------------------------- /pages/goods/comment.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 80 | 81 | 83 | -------------------------------------------------------------------------------- /pages/goods/search.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 70 | 71 | 114 | -------------------------------------------------------------------------------- /pages/index/login.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 116 | 117 | 135 | -------------------------------------------------------------------------------- /pages/index/msg.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 54 | 55 | 69 | -------------------------------------------------------------------------------- /pages/member/address_list.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 61 | 62 | 65 | -------------------------------------------------------------------------------- /pages/member/order_details.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /pages/member/personal.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 106 | 107 | 118 | -------------------------------------------------------------------------------- /pages/member/personal_ext.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 96 | 97 | 122 | -------------------------------------------------------------------------------- /pages/member/setting.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 53 | -------------------------------------------------------------------------------- /pages/order/pay.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 95 | 96 | 164 | -------------------------------------------------------------------------------- /pages/order/select_address.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 69 | 70 | 73 | -------------------------------------------------------------------------------- /pages/order/use_invoice.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /pages/vuex_test/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 59 | 60 | 96 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | 外部插件目录,引用其他外部的组件,插件 -------------------------------------------------------------------------------- /plugins/luch-request/adapters/index.js: -------------------------------------------------------------------------------- 1 | import buildURL from '../helpers/buildURL' 2 | import buildFullPath from '../core/buildFullPath' 3 | import settle from '../core/settle' 4 | 5 | /** 6 | * 返回可选值存在的配置 7 | * @param {Array} keys - 可选值数组 8 | * @param {Object} config2 - 配置 9 | * @return {{}} - 存在的配置项 10 | */ 11 | const mergeKeys = (keys, config2) => { 12 | let config = {} 13 | keys.forEach(prop => { 14 | if (typeof config2[prop] !== 'undefined') { 15 | config[prop] = config2[prop] 16 | } 17 | }) 18 | return config 19 | } 20 | export default (config) => { 21 | return new Promise((resolve, reject) => { 22 | const _config = { 23 | url: buildURL(buildFullPath(config.baseURL, config.url), config.params), 24 | header: config.header, 25 | complete: (response) => { 26 | response.config = config 27 | try { 28 | // 对可能字符串不是json 的情况容错 29 | if (typeof response.data === 'string') { 30 | response.data = JSON.parse(response.data) 31 | } 32 | // eslint-disable-next-line no-empty 33 | } catch (e) { 34 | } 35 | settle(resolve, reject, response) 36 | } 37 | } 38 | let requestTask 39 | if (config.method === 'UPLOAD') { 40 | delete _config.header['content-type'] 41 | delete _config.header['Content-Type'] 42 | let otherConfig = { 43 | // #ifdef MP-ALIPAY 44 | fileType: config.fileType, 45 | // #endif 46 | filePath: config.filePath, 47 | name: config.name 48 | } 49 | const optionalKeys = [ 50 | // #ifdef APP-PLUS || H5 51 | 'files', 52 | // #endif 53 | // #ifdef H5 54 | 'file', 55 | // #endif 56 | 'formData' 57 | ] 58 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)}) 59 | } else if (config.method === 'DOWNLOAD') { 60 | requestTask = uni.downloadFile(_config) 61 | } else { 62 | const optionalKeys = [ 63 | 'data', 64 | 'method', 65 | // #ifdef MP-ALIPAY || MP-WEIXIN 66 | 'timeout', 67 | // #endif 68 | 'dataType', 69 | // #ifndef MP-ALIPAY || APP-PLUS 70 | 'responseType', 71 | // #endif 72 | // #ifdef APP-PLUS 73 | 'sslVerify', 74 | // #endif 75 | // #ifdef H5 76 | 'withCredentials', 77 | // #endif 78 | // #ifdef APP-PLUS 79 | 'firstIpv4', 80 | // #endif 81 | ] 82 | requestTask = uni.request({..._config,...mergeKeys(optionalKeys, config)}) 83 | } 84 | if (config.getTask) { 85 | config.getTask(requestTask, config) 86 | } 87 | }) 88 | } 89 | -------------------------------------------------------------------------------- /plugins/luch-request/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | 4 | function InterceptorManager() { 5 | this.handlers = [] 6 | } 7 | 8 | /** 9 | * Add a new interceptor to the stack 10 | * 11 | * @param {Function} fulfilled The function to handle `then` for a `Promise` 12 | * @param {Function} rejected The function to handle `reject` for a `Promise` 13 | * 14 | * @return {Number} An ID used to remove interceptor later 15 | */ 16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) { 17 | this.handlers.push({ 18 | fulfilled: fulfilled, 19 | rejected: rejected 20 | }) 21 | return this.handlers.length - 1 22 | } 23 | 24 | /** 25 | * Remove an interceptor from the stack 26 | * 27 | * @param {Number} id The ID that was returned by `use` 28 | */ 29 | InterceptorManager.prototype.eject = function eject(id) { 30 | if (this.handlers[id]) { 31 | this.handlers[id] = null 32 | } 33 | } 34 | 35 | /** 36 | * Iterate over all the registered interceptors 37 | * 38 | * This method is particularly useful for skipping over any 39 | * interceptors that may have become `null` calling `eject`. 40 | * 41 | * @param {Function} fn The function to call for each interceptor 42 | */ 43 | InterceptorManager.prototype.forEach = function forEach(fn) { 44 | this.handlers.forEach(h => { 45 | if (h !== null) { 46 | fn(h) 47 | } 48 | }) 49 | } 50 | 51 | export default InterceptorManager 52 | -------------------------------------------------------------------------------- /plugins/luch-request/core/buildFullPath.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import isAbsoluteURL from '../helpers/isAbsoluteURL' 4 | import combineURLs from '../helpers/combineURLs' 5 | 6 | /** 7 | * Creates a new URL by combining the baseURL with the requestedURL, 8 | * only when the requestedURL is not already an absolute URL. 9 | * If the requestURL is absolute, this function returns the requestedURL untouched. 10 | * 11 | * @param {string} baseURL The base URL 12 | * @param {string} requestedURL Absolute or relative URL to combine 13 | * @returns {string} The combined full path 14 | */ 15 | export default function buildFullPath(baseURL, requestedURL) { 16 | if (baseURL && !isAbsoluteURL(requestedURL)) { 17 | return combineURLs(baseURL, requestedURL) 18 | } 19 | return requestedURL 20 | } 21 | -------------------------------------------------------------------------------- /plugins/luch-request/core/defaults.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 默认的全局配置 3 | */ 4 | 5 | 6 | export default { 7 | baseURL: '', 8 | header: {}, 9 | method: 'GET', 10 | dataType: 'json', 11 | // #ifndef MP-ALIPAY || APP-PLUS 12 | responseType: 'text', 13 | // #endif 14 | custom: {}, 15 | // #ifdef MP-ALIPAY || MP-WEIXIN 16 | timeout: 30000, 17 | // #endif 18 | // #ifdef APP-PLUS 19 | sslVerify: true, 20 | // #endif 21 | // #ifdef H5 22 | withCredentials: false, 23 | // #endif 24 | // #ifdef APP-PLUS 25 | firstIpv4: false, 26 | // #endif 27 | validateStatus: function validateStatus(status) { 28 | return status >= 200 && status < 300 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugins/luch-request/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | import adapter from '../adapters/index' 2 | 3 | 4 | export default (config) => { 5 | return adapter(config) 6 | } 7 | -------------------------------------------------------------------------------- /plugins/luch-request/core/mergeConfig.js: -------------------------------------------------------------------------------- 1 | import {deepMerge} from '../utils' 2 | 3 | /** 4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局 5 | * @param {Array} keys - 配置项 6 | * @param {Object} globalsConfig - 当前的全局配置 7 | * @param {Object} config2 - 局部配置 8 | * @return {{}} 9 | */ 10 | const mergeKeys = (keys, globalsConfig, config2) => { 11 | let config = {} 12 | keys.forEach(prop => { 13 | if (typeof config2[prop] !== 'undefined') { 14 | config[prop] = config2[prop] 15 | } else if (typeof globalsConfig[prop] !== 'undefined') { 16 | config[prop] = globalsConfig[prop] 17 | } 18 | }) 19 | return config 20 | } 21 | /** 22 | * 23 | * @param globalsConfig - 当前实例的全局配置 24 | * @param config2 - 当前的局部配置 25 | * @return - 合并后的配置 26 | */ 27 | export default (globalsConfig, config2 = {}) => { 28 | const method = config2.method || globalsConfig.method || 'GET' 29 | let config = { 30 | baseURL: globalsConfig.baseURL || '', 31 | method: method, 32 | url: config2.url || '', 33 | params: config2.params || {}, 34 | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})}, 35 | header: deepMerge(globalsConfig.header || {}, config2.header || {}) 36 | } 37 | const defaultToConfig2Keys = ['getTask', 'validateStatus'] 38 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)} 39 | 40 | // eslint-disable-next-line no-empty 41 | if (method === 'DOWNLOAD') { 42 | 43 | } else if (method === 'UPLOAD') { 44 | delete config.header['content-type'] 45 | delete config.header['Content-Type'] 46 | const uploadKeys = [ 47 | // #ifdef APP-PLUS || H5 48 | 'files', 49 | // #endif 50 | // #ifdef MP-ALIPAY 51 | 'fileType', 52 | // #endif 53 | // #ifdef H5 54 | 'file', 55 | // #endif 56 | 'filePath', 57 | 'name', 58 | 'formData', 59 | ] 60 | uploadKeys.forEach(prop => { 61 | if (typeof config2[prop] !== 'undefined') { 62 | config[prop] = config2[prop] 63 | } 64 | }) 65 | } else { 66 | const defaultsKeys = [ 67 | 'data', 68 | // #ifdef MP-ALIPAY || MP-WEIXIN 69 | 'timeout', 70 | // #endif 71 | 'dataType', 72 | // #ifndef MP-ALIPAY || APP-PLUS 73 | 'responseType', 74 | // #endif 75 | // #ifdef APP-PLUS 76 | 'sslVerify', 77 | // #endif 78 | // #ifdef H5 79 | 'withCredentials', 80 | // #endif 81 | // #ifdef APP-PLUS 82 | 'firstIpv4', 83 | // #endif 84 | ] 85 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)} 86 | } 87 | 88 | return config 89 | } 90 | -------------------------------------------------------------------------------- /plugins/luch-request/core/settle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Resolve or reject a Promise based on response status. 3 | * 4 | * @param {Function} resolve A function that resolves the promise. 5 | * @param {Function} reject A function that rejects the promise. 6 | * @param {object} response The response. 7 | */ 8 | export default function settle(resolve, reject, response) { 9 | const validateStatus = response.config.validateStatus 10 | const status = response.statusCode 11 | if (status && (!validateStatus || validateStatus(status))) { 12 | resolve(response) 13 | } else { 14 | reject(response) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugins/luch-request/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import * as utils from './../utils' 4 | 5 | function encode(val) { 6 | return encodeURIComponent(val). 7 | replace(/%40/gi, '@'). 8 | replace(/%3A/gi, ':'). 9 | replace(/%24/g, '$'). 10 | replace(/%2C/gi, ','). 11 | replace(/%20/g, '+'). 12 | replace(/%5B/gi, '['). 13 | replace(/%5D/gi, ']') 14 | } 15 | 16 | /** 17 | * Build a URL by appending params to the end 18 | * 19 | * @param {string} url The base of the url (e.g., http://www.google.com) 20 | * @param {object} [params] The params to be appended 21 | * @returns {string} The formatted url 22 | */ 23 | export default function buildURL(url, params) { 24 | /*eslint no-param-reassign:0*/ 25 | if (!params) { 26 | return url 27 | } 28 | 29 | var serializedParams 30 | if (utils.isURLSearchParams(params)) { 31 | serializedParams = params.toString() 32 | } else { 33 | var parts = [] 34 | 35 | utils.forEach(params, function serialize(val, key) { 36 | if (val === null || typeof val === 'undefined') { 37 | return 38 | } 39 | 40 | if (utils.isArray(val)) { 41 | key = key + '[]' 42 | } else { 43 | val = [val] 44 | } 45 | 46 | utils.forEach(val, function parseValue(v) { 47 | if (utils.isDate(v)) { 48 | v = v.toISOString() 49 | } else if (utils.isObject(v)) { 50 | v = JSON.stringify(v) 51 | } 52 | parts.push(encode(key) + '=' + encode(v)) 53 | }) 54 | }) 55 | 56 | serializedParams = parts.join('&') 57 | } 58 | 59 | if (serializedParams) { 60 | var hashmarkIndex = url.indexOf('#') 61 | if (hashmarkIndex !== -1) { 62 | url = url.slice(0, hashmarkIndex) 63 | } 64 | 65 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams 66 | } 67 | 68 | return url 69 | } 70 | -------------------------------------------------------------------------------- /plugins/luch-request/helpers/combineURLs.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Creates a new URL by combining the specified URLs 5 | * 6 | * @param {string} baseURL The base URL 7 | * @param {string} relativeURL The relative URL 8 | * @returns {string} The combined URL 9 | */ 10 | export default function combineURLs(baseURL, relativeURL) { 11 | return relativeURL 12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') 13 | : baseURL 14 | } 15 | -------------------------------------------------------------------------------- /plugins/luch-request/helpers/isAbsoluteURL.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Determines whether the specified URL is absolute 5 | * 6 | * @param {string} url The URL to test 7 | * @returns {boolean} True if the specified URL is absolute, otherwise false 8 | */ 9 | export default function isAbsoluteURL(url) { 10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 12 | // by any combination of letters, digits, plus, period, or hyphen. 13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) 14 | } 15 | -------------------------------------------------------------------------------- /plugins/luch-request/index.d.ts: -------------------------------------------------------------------------------- 1 | type AnyObject = Record 2 | 3 | export interface RequestTask { 4 | abort: () => void; 5 | offHeadersReceived: () => void; 6 | onHeadersReceived: () => void; 7 | } 8 | export interface HttpRequestConfig { 9 | /** 请求基地址 */ 10 | baseURL?: string; 11 | /** 请求服务器接口地址 */ 12 | url?: string; 13 | 14 | /** 请求查询参数,自动拼接为查询字符串 */ 15 | params?: AnyObject; 16 | /** 请求体参数 */ 17 | data?: AnyObject; 18 | 19 | /** 文件对应的 key */ 20 | name?: string; 21 | /** HTTP 请求中其他额外的 form data */ 22 | formData?: AnyObject; 23 | /** 要上传文件资源的路径。 */ 24 | filePath?: string; 25 | /** 需要上传的文件列表。使用 files 时,filePath 和 name 不生效,App、H5( 2.6.15+) */ 26 | files?: Array<{ 27 | name?: string; 28 | file?: File; 29 | uri: string; 30 | }>; 31 | /** 要上传的文件对象,仅H5(2.6.15+)支持 */ 32 | file?: File; 33 | 34 | /** 请求头信息 */ 35 | header?: AnyObject; 36 | /** 请求方式 */ 37 | method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD"; 38 | /** 如果设为 json,会尝试对返回的数据做一次 JSON.parse */ 39 | dataType?: string; 40 | /** 设置响应的数据类型,App和支付宝小程序不支持 */ 41 | responseType?: "text" | "arraybuffer"; 42 | /** 自定义参数 */ 43 | custom?: AnyObject; 44 | /** 超时时间,仅微信小程序(2.10.0)、支付宝小程序支持 */ 45 | timeout?: number; 46 | /** DNS解析时优先使用ipv4,仅 App-Android 支持 (HBuilderX 2.8.0+) */ 47 | firstIpv4?: boolean; 48 | /** 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) */ 49 | sslVerify?: boolean; 50 | /** 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) */ 51 | withCredentials?: boolean; 52 | 53 | /** 返回当前请求的task, options。请勿在此处修改options。 */ 54 | getTask?: (task: RequestTask, options: HttpRequestConfig) => void; 55 | /** 全局自定义验证器 */ 56 | validateStatus?: (statusCode: number) => boolean | void; 57 | } 58 | export interface HttpResponse { 59 | config: HttpRequestConfig; 60 | statusCode: number; 61 | cookies: Array; 62 | data: T; 63 | errMsg: string; 64 | header: AnyObject; 65 | } 66 | export interface HttpUploadResponse { 67 | config: HttpRequestConfig; 68 | statusCode: number; 69 | data: T; 70 | errMsg: string; 71 | } 72 | export interface HttpDownloadResponse extends HttpResponse { 73 | tempFilePath: string; 74 | } 75 | export interface HttpError { 76 | config: HttpRequestConfig; 77 | statusCode?: number; 78 | cookies?: Array; 79 | data?: any; 80 | errMsg: string; 81 | header?: AnyObject; 82 | } 83 | export interface HttpInterceptorManager { 84 | use( 85 | onFulfilled?: (config: V) => V, 86 | onRejected?: (config: E) => Promise | E 87 | ): void; 88 | eject(id: number): void; 89 | } 90 | export abstract class HttpRequestAbstract { 91 | constructor(config?: HttpRequestConfig); 92 | config: HttpRequestConfig; 93 | interceptors: { 94 | request: HttpInterceptorManager; 95 | response: HttpInterceptorManager; 96 | } 97 | middleware(config: HttpRequestConfig): Promise>; 98 | request(config: HttpRequestConfig): Promise>; 99 | get(url: string, config?: HttpRequestConfig): Promise>; 100 | upload(url: string, config?: HttpRequestConfig): Promise>; 101 | delete(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 102 | head(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 103 | post(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 104 | put(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 105 | connect(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 106 | options(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 107 | trace(url: string, data?: AnyObject, config?: HttpRequestConfig): Promise>; 108 | 109 | download(url: string, config?: HttpRequestConfig): Promise; 110 | 111 | setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void; 112 | } 113 | 114 | declare class HttpRequest extends HttpRequestAbstract { } 115 | export default HttpRequest; 116 | -------------------------------------------------------------------------------- /plugins/luch-request/index.js: -------------------------------------------------------------------------------- 1 | import Request from './core/Request' 2 | export default Request 3 | -------------------------------------------------------------------------------- /plugins/luch-request/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // utils is a library of generic helper functions non-specific to axios 4 | 5 | var toString = Object.prototype.toString 6 | 7 | /** 8 | * Determine if a value is an Array 9 | * 10 | * @param {Object} val The value to test 11 | * @returns {boolean} True if value is an Array, otherwise false 12 | */ 13 | export function isArray (val) { 14 | return toString.call(val) === '[object Array]' 15 | } 16 | 17 | 18 | /** 19 | * Determine if a value is an Object 20 | * 21 | * @param {Object} val The value to test 22 | * @returns {boolean} True if value is an Object, otherwise false 23 | */ 24 | export function isObject (val) { 25 | return val !== null && typeof val === 'object' 26 | } 27 | 28 | /** 29 | * Determine if a value is a Date 30 | * 31 | * @param {Object} val The value to test 32 | * @returns {boolean} True if value is a Date, otherwise false 33 | */ 34 | export function isDate (val) { 35 | return toString.call(val) === '[object Date]' 36 | } 37 | 38 | /** 39 | * Determine if a value is a URLSearchParams object 40 | * 41 | * @param {Object} val The value to test 42 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false 43 | */ 44 | export function isURLSearchParams (val) { 45 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams 46 | } 47 | 48 | 49 | /** 50 | * Iterate over an Array or an Object invoking a function for each item. 51 | * 52 | * If `obj` is an Array callback will be called passing 53 | * the value, index, and complete array for each item. 54 | * 55 | * If 'obj' is an Object callback will be called passing 56 | * the value, key, and complete object for each property. 57 | * 58 | * @param {Object|Array} obj The object to iterate 59 | * @param {Function} fn The callback to invoke for each item 60 | */ 61 | export function forEach (obj, fn) { 62 | // Don't bother if no value provided 63 | if (obj === null || typeof obj === 'undefined') { 64 | return 65 | } 66 | 67 | // Force an array if not already something iterable 68 | if (typeof obj !== 'object') { 69 | /*eslint no-param-reassign:0*/ 70 | obj = [obj] 71 | } 72 | 73 | if (isArray(obj)) { 74 | // Iterate over array values 75 | for (var i = 0, l = obj.length; i < l; i++) { 76 | fn.call(null, obj[i], i, obj) 77 | } 78 | } else { 79 | // Iterate over object keys 80 | for (var key in obj) { 81 | if (Object.prototype.hasOwnProperty.call(obj, key)) { 82 | fn.call(null, obj[key], key, obj) 83 | } 84 | } 85 | } 86 | } 87 | 88 | /** 89 | * 是否为boolean 值 90 | * @param val 91 | * @returns {boolean} 92 | */ 93 | export function isBoolean(val) { 94 | return typeof val === 'boolean' 95 | } 96 | 97 | /** 98 | * 是否为真正的对象{} new Object 99 | * @param {any} obj - 检测的对象 100 | * @returns {boolean} 101 | */ 102 | export function isPlainObject(obj) { 103 | return Object.prototype.toString.call(obj) === '[object Object]' 104 | } 105 | 106 | 107 | 108 | /** 109 | * Function equal to merge with the difference being that no reference 110 | * to original objects is kept. 111 | * 112 | * @see merge 113 | * @param {Object} obj1 Object to merge 114 | * @returns {Object} Result of all merge properties 115 | */ 116 | export function deepMerge(/* obj1, obj2, obj3, ... */) { 117 | let result = {} 118 | function assignValue(val, key) { 119 | if (typeof result[key] === 'object' && typeof val === 'object') { 120 | result[key] = deepMerge(result[key], val) 121 | } else if (typeof val === 'object') { 122 | result[key] = deepMerge({}, val) 123 | } else { 124 | result[key] = val 125 | } 126 | } 127 | for (let i = 0, l = arguments.length; i < l; i++) { 128 | forEach(arguments[i], assignValue) 129 | } 130 | return result 131 | } 132 | -------------------------------------------------------------------------------- /plugins/uview-ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 www.uviewui.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /plugins/uview-ui/README.md: -------------------------------------------------------------------------------- 1 |

2 | logo 3 |

4 |

uView

5 |

多平台快速开发的UI框架

6 | 7 | 8 | ## 说明 9 | 10 | uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 11 | 12 | ## 特性 13 | 14 | - 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序 15 | - 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用 16 | - 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨 17 | - 众多的常用页面和布局,让您专注逻辑,事半功倍 18 | - 详尽的文档支持,现代化的演示效果 19 | - 按需引入,精简打包体积 20 | 21 | 22 | ## 安装 23 | 24 | ```bash 25 | # npm方式安装 26 | npm i uview-ui 27 | ``` 28 | 29 | ## 快速上手 30 | 31 | 1. `main.js`引入uView库 32 | ```js 33 | // main.js 34 | import uView from 'uview-ui'; 35 | Vue.use(uView); 36 | ``` 37 | 38 | 2. `App.vue`引入基础样式(注意style标签需声明scss属性支持) 39 | ```css 40 | /* App.vue */ 41 | 44 | ``` 45 | 46 | 3. `uni.scss`引入全局scss变量文件 47 | ```css 48 | /* uni.scss */ 49 | @import "uview-ui/theme.scss"; 50 | ``` 51 | 52 | 4. `pages.json`配置easycom规则(按需引入) 53 | 54 | ```js 55 | // pages.json 56 | { 57 | "easycom": { 58 | // npm安装的方式不需要前面的"@/",下载安装的方式需要"@/" 59 | // npm安装方式 60 | "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" 61 | // 下载安装方式 62 | // "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" 63 | }, 64 | // 此为本身已有的内容 65 | "pages": [ 66 | // ...... 67 | ] 68 | } 69 | ``` 70 | 71 | 请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 72 | 73 | ## 使用方法 74 | 配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 75 | 76 | ```html 77 | 80 | ``` 81 | 82 | 请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 83 | 84 | ## 链接 85 | 86 | - [官方文档](https://uviewui.com/) 87 | - [更新日志](https://uviewui.com/components/changelog.html) 88 | - [升级指南](https://uviewui.com/components/changelog.html) 89 | - [关于我们](https://uviewui.com/cooperation/about.html) 90 | 91 | ## 预览 92 | 93 | 您可以通过**微信**扫码,查看最佳的演示效果。 94 |
95 |
96 | 97 | 98 | 105 | ## 版权信息 106 | uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 107 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-back-top/u-back-top.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 124 | 125 | 154 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-cell-group/u-cell-group.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 51 | 52 | 71 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-checkbox-group/u-checkbox-group.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 113 | 114 | 124 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-col/u-col.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 95 | 96 | 157 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-collapse/u-collapse.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 96 | 97 | 100 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-divider/u-divider.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 106 | 107 | 154 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-dropdown-item/u-dropdown-item.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 129 | 130 | 133 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-form/u-form.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 131 | 132 | 135 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-full-screen/u-full-screen.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 38 | 39 | 53 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-gap/u-gap.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 51 | 52 | 55 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-grid-item/u-grid-item.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 81 | 82 | 127 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-grid/u-grid.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 90 | 91 | 109 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-index-anchor/u-index-anchor.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 68 | 69 | 90 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-line-progress/u-line-progress.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 102 | 103 | 148 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-line/u-line.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 77 | 78 | 85 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-link/u-link.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 82 | 83 | 90 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-loading-page/u-loading-page.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-loading/u-loading.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 53 | 54 | 104 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-mask/u-mask.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 102 | 103 | 124 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-parse/libs/CssHandler.js: -------------------------------------------------------------------------------- 1 | const cfg = require('./config.js'), 2 | isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 3 | 4 | function CssHandler(tagStyle) { 5 | var styles = Object.assign(Object.create(null), cfg.userAgentStyles); 6 | for (var item in tagStyle) 7 | styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item]; 8 | this.styles = styles; 9 | } 10 | CssHandler.prototype.getStyle = function(data) { 11 | this.styles = new parser(data, this.styles).parse(); 12 | } 13 | CssHandler.prototype.match = function(name, attrs) { 14 | var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : ''; 15 | if (attrs.class) { 16 | var items = attrs.class.split(' '); 17 | for (var i = 0, item; item = items[i]; i++) 18 | if (tmp = this.styles['.' + item]) 19 | matched += tmp + ';'; 20 | } 21 | if (tmp = this.styles['#' + attrs.id]) 22 | matched += tmp + ';'; 23 | return matched; 24 | } 25 | module.exports = CssHandler; 26 | 27 | function parser(data, init) { 28 | this.data = data; 29 | this.floor = 0; 30 | this.i = 0; 31 | this.list = []; 32 | this.res = init; 33 | this.state = this.Space; 34 | } 35 | parser.prototype.parse = function() { 36 | for (var c; c = this.data[this.i]; this.i++) 37 | this.state(c); 38 | return this.res; 39 | } 40 | parser.prototype.section = function() { 41 | return this.data.substring(this.start, this.i); 42 | } 43 | // 状态机 44 | parser.prototype.Space = function(c) { 45 | if (c == '.' || c == '#' || isLetter(c)) { 46 | this.start = this.i; 47 | this.state = this.Name; 48 | } else if (c == '/' && this.data[this.i + 1] == '*') 49 | this.Comment(); 50 | else if (!cfg.blankChar[c] && c != ';') 51 | this.state = this.Ignore; 52 | } 53 | parser.prototype.Comment = function() { 54 | this.i = this.data.indexOf('*/', this.i) + 1; 55 | if (!this.i) this.i = this.data.length; 56 | this.state = this.Space; 57 | } 58 | parser.prototype.Ignore = function(c) { 59 | if (c == '{') this.floor++; 60 | else if (c == '}' && !--this.floor) { 61 | this.list = []; 62 | this.state = this.Space; 63 | } 64 | } 65 | parser.prototype.Name = function(c) { 66 | if (cfg.blankChar[c]) { 67 | this.list.push(this.section()); 68 | this.state = this.NameSpace; 69 | } else if (c == '{') { 70 | this.list.push(this.section()); 71 | this.Content(); 72 | } else if (c == ',') { 73 | this.list.push(this.section()); 74 | this.Comma(); 75 | } else if (!isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_') 76 | this.state = this.Ignore; 77 | } 78 | parser.prototype.NameSpace = function(c) { 79 | if (c == '{') this.Content(); 80 | else if (c == ',') this.Comma(); 81 | else if (!cfg.blankChar[c]) this.state = this.Ignore; 82 | } 83 | parser.prototype.Comma = function() { 84 | while (cfg.blankChar[this.data[++this.i]]); 85 | if (this.data[this.i] == '{') this.Content(); 86 | else { 87 | this.start = this.i--; 88 | this.state = this.Name; 89 | } 90 | } 91 | parser.prototype.Content = function() { 92 | this.start = ++this.i; 93 | if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length; 94 | var content = this.section(); 95 | for (var i = 0, item; item = this.list[i++];) 96 | if (this.res[item]) this.res[item] += ';' + content; 97 | else this.res[item] = content; 98 | this.list = []; 99 | this.state = this.Space; 100 | } 101 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-parse/libs/config.js: -------------------------------------------------------------------------------- 1 | /* 配置文件 */ 2 | var cfg = { 3 | // 出错占位图 4 | errorImg: null, 5 | // 过滤器函数 6 | filter: null, 7 | // 代码高亮函数 8 | highlight: null, 9 | // 文本处理函数 10 | onText: null, 11 | // 实体编码列表 12 | entities: { 13 | quot: '"', 14 | apos: "'", 15 | semi: ';', 16 | nbsp: '\xA0', 17 | ensp: '\u2002', 18 | emsp: '\u2003', 19 | ndash: '–', 20 | mdash: '—', 21 | middot: '·', 22 | lsquo: '‘', 23 | rsquo: '’', 24 | ldquo: '“', 25 | rdquo: '”', 26 | bull: '•', 27 | hellip: '…' 28 | }, 29 | blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'), 30 | boolAttrs: makeMap('allowfullscreen,autoplay,autostart,controls,ignore,loop,muted'), 31 | // 块级标签,将被转为 div 32 | blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'), 33 | // 将被移除的标签 34 | ignoreTags: makeMap('area,base,canvas,frame,iframe,input,link,map,meta,param,script,source,style,svg,textarea,title,track,wbr'), 35 | // 只能被 rich-text 显示的标签 36 | richOnlyTags: makeMap('a,colgroup,fieldset,legend'), 37 | // 自闭合的标签 38 | selfClosingTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'), 39 | // 信任的标签 40 | trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'), 41 | // 默认的标签样式 42 | userAgentStyles: { 43 | address: 'font-style:italic', 44 | big: 'display:inline;font-size:1.2em', 45 | blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px', 46 | caption: 'display:table-caption;text-align:center', 47 | center: 'text-align:center', 48 | cite: 'font-style:italic', 49 | dd: 'margin-left:40px', 50 | mark: 'background-color:yellow', 51 | pre: 'font-family:monospace;white-space:pre;overflow:scroll', 52 | s: 'text-decoration:line-through', 53 | small: 'display:inline;font-size:0.8em', 54 | u: 'text-decoration:underline' 55 | } 56 | } 57 | 58 | function makeMap(str) { 59 | var map = Object.create(null), 60 | list = str.split(','); 61 | for (var i = list.length; i--;) 62 | map[list[i]] = true; 63 | return map; 64 | } 65 | 66 | // #ifdef MP-WEIXIN 67 | if (wx.canIUse('editor')) { 68 | cfg.blockTags.pre = void 0; 69 | cfg.ignoreTags.rp = true; 70 | Object.assign(cfg.richOnlyTags, makeMap('bdi,bdo,caption,rt,ruby')); 71 | Object.assign(cfg.trustTags, makeMap('bdi,bdo,caption,pre,rt,ruby')); 72 | } 73 | // #endif 74 | 75 | // #ifdef APP-PLUS 76 | cfg.ignoreTags.iframe = void 0; 77 | Object.assign(cfg.trustTags, makeMap('embed,iframe')); 78 | // #endif 79 | 80 | module.exports = cfg; 81 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-parse/libs/handler.wxs: -------------------------------------------------------------------------------- 1 | var inline = { 2 | abbr: 1, 3 | b: 1, 4 | big: 1, 5 | code: 1, 6 | del: 1, 7 | em: 1, 8 | i: 1, 9 | ins: 1, 10 | label: 1, 11 | q: 1, 12 | small: 1, 13 | span: 1, 14 | strong: 1, 15 | sub: 1, 16 | sup: 1 17 | } 18 | module.exports = { 19 | use: function(item) { 20 | return !item.c && !inline[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-radio-group/u-radio-group.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 118 | 119 | 129 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-row/u-row.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 65 | 66 | 85 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-section/u-section.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 117 | 118 | 155 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-table/u-table.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 76 | 77 | 85 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-td/u-td.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 51 | 52 | 67 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-th/u-th.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | 49 | 63 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-time-line-item/u-time-line-item.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 52 | 53 | 84 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-time-line/u-time-line.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | 24 | 44 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-top-tips/u-top-tips.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 69 | 70 | 122 | -------------------------------------------------------------------------------- /plugins/uview-ui/components/u-tr/u-tr.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /plugins/uview-ui/index.js: -------------------------------------------------------------------------------- 1 | // 引入全局mixin 2 | import mixin from './libs/mixin/mixin.js' 3 | // 引入关于是否mixin集成小程序分享的配置 4 | // import wxshare from './libs/mixin/mpShare.js' 5 | // 全局挂载引入http相关请求拦截插件 6 | // import http from './libs/request' //不需要这个 7 | 8 | function wranning(str) { 9 | // 开发环境进行信息输出,主要是一些报错信息 10 | // 这个环境的来由是在程序编写时候,点击hx编辑器运行调试代码的时候,详见: 11 | // https://uniapp.dcloud.io/frame?id=%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e5%92%8c%e7%94%9f%e4%ba%a7%e7%8e%af%e5%a2%83 12 | if (process.env.NODE_ENV === 'development') { 13 | console.warn(str) 14 | } 15 | } 16 | 17 | // 尝试判断在根目录的/store中是否有$u.mixin.js,此文件uView默认为需要挂在到全局的vuex的state变量 18 | // HX2.6.11版本,放到try中,控制台依然会警告,暂时不用此方式, 19 | // let vuexStore = {}; 20 | // try { 21 | // vuexStore = require("@/store/$u.mixin.js"); 22 | // } catch (e) { 23 | // //TODO handle the exception 24 | // } 25 | 26 | // post类型对象参数转为get类型url参数 27 | import queryParams from './libs/function/queryParams.js' 28 | // 路由封装 29 | // import route from './libs/function/route.js' //不需要这个 30 | // 时间格式化 31 | import timeFormat from './libs/function/timeFormat.js' 32 | // 时间戳格式化,返回多久之前 33 | import timeFrom from './libs/function/timeFrom.js' 34 | // 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制 35 | import colorGradient from './libs/function/colorGradient.js' 36 | // 生成全局唯一guid字符串 37 | import guid from './libs/function/guid.js' 38 | // 主题相关颜色,info|success|warning|primary|default|error,此颜色已在uview.scss中定义,但是为js中也能使用,故也定义一份 39 | import color from './libs/function/color.js' 40 | // 根据type获取图标名称 41 | import type2icon from './libs/function/type2icon.js' 42 | // 打乱数组的顺序 43 | import randomArray from './libs/function/randomArray.js' 44 | // 对象和数组的深度克隆 45 | import deepClone from './libs/function/deepClone.js' 46 | // 对象深度拷贝 47 | import deepMerge from './libs/function/deepMerge.js' 48 | // 添加单位 49 | import addUnit from './libs/function/addUnit.js' 50 | 51 | // 规则检验 52 | import test from './libs/function/test.js' 53 | // 随机数 54 | import random from './libs/function/random.js' 55 | // 去除空格 56 | import trim from './libs/function/trim.js' 57 | // toast提示,对uni.showToast的封装 58 | import toast from './libs/function/toast.js' 59 | // 获取父组件参数 60 | import getParent from './libs/function/getParent.js' 61 | // 获取整个父组件 62 | import $parent from './libs/function/$parent.js' 63 | // 获取sys()和os()工具方法 64 | // 获取设备信息,挂载到$u的sys()(system的缩写)属性中, 65 | // 同时把安卓和ios平台的名称"ios"和"android"挂到$u.os()中,方便取用 66 | import {sys, os} from './libs/function/sys.js' 67 | // 防抖方法 68 | import debounce from './libs/function/debounce.js' 69 | // 节流方法 70 | import throttle from './libs/function/throttle.js' 71 | 72 | 73 | // 配置信息 74 | import config from './libs/config/config.js' 75 | // 各个需要fixed的地方的z-index配置文件 76 | import zIndex from './libs/config/zIndex.js' 77 | 78 | const $u = { 79 | queryParams: queryParams, 80 | // route: route, 81 | timeFormat: timeFormat, 82 | date: timeFormat, // 另名date 83 | timeFrom, 84 | colorGradient: colorGradient.colorGradient, 85 | colorToRgba: colorGradient.colorToRgba, 86 | guid, 87 | color, 88 | sys, 89 | os, 90 | type2icon, 91 | randomArray, 92 | wranning, 93 | /* 94 | get: http.get, 95 | post: http.post, 96 | put: http.put, 97 | 'delete': http.delete, 98 | http, 99 | */ 100 | hexToRgb: colorGradient.hexToRgb, 101 | rgbToHex: colorGradient.rgbToHex, 102 | test, 103 | random, 104 | deepClone, 105 | deepMerge, 106 | getParent, 107 | $parent, 108 | addUnit, 109 | trim, 110 | type: ['primary', 'success', 'error', 'warning', 'info'], 111 | toast, 112 | config, // uView配置信息相关,比如版本号 113 | zIndex, 114 | debounce, 115 | throttle, 116 | } 117 | 118 | // $u挂载到uni对象上 119 | uni.$u = $u 120 | 121 | const install = Vue => { 122 | Vue.mixin(mixin) 123 | if (Vue.prototype.openShare) { 124 | Vue.mixin(mpShare); 125 | } 126 | // Vue.mixin(vuexStore); 127 | // 时间格式化,同时两个名称,date和timeFormat 128 | Vue.filter('timeFormat', (timestamp, format) => { 129 | return timeFormat(timestamp, format) 130 | }) 131 | Vue.filter('date', (timestamp, format) => { 132 | return timeFormat(timestamp, format) 133 | }) 134 | // 将多久以前的方法,注入到全局过滤器 135 | Vue.filter('timeFrom', (timestamp, format) => { 136 | return timeFrom(timestamp, format) 137 | }) 138 | Vue.prototype.$u = $u 139 | } 140 | 141 | export default { 142 | install 143 | } -------------------------------------------------------------------------------- /plugins/uview-ui/index.scss: -------------------------------------------------------------------------------- 1 | // 引入公共基础类 2 | @import "./libs/css/common.scss"; 3 | @import "./libs/css/color.scss"; 4 | 5 | // 非nvue的样式 6 | /* #ifndef APP-NVUE */ 7 | @import "./libs/css/style.vue.scss"; 8 | /* #endif */ 9 | 10 | // nvue的特有样式 11 | /* #ifdef APP-NVUE */ 12 | @import "./libs/css/style.nvue.scss"; 13 | /* #endif */ 14 | 15 | // 小程序特有的样式 16 | /* #ifdef MP */ 17 | @import "./libs/css/style.mp.scss"; 18 | /* #endif */ 19 | 20 | // H5特有的样式 21 | /* #ifdef H5 */ 22 | @import "./libs/css/style.h5.scss"; 23 | /* #endif */ -------------------------------------------------------------------------------- /plugins/uview-ui/libs/config/config.js: -------------------------------------------------------------------------------- 1 | // 此版本发布于2020-11-19 2 | let version = '1.8.2'; 3 | 4 | export default { 5 | v: version, 6 | version: version, 7 | // 主题名称 8 | type: [ 9 | 'primary', 10 | 'success', 11 | 'info', 12 | 'error', 13 | 'warning' 14 | ] 15 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/config/zIndex.js: -------------------------------------------------------------------------------- 1 | // uniapp在H5中各API的z-index值如下: 2 | /** 3 | * actionsheet: 999 4 | * modal: 999 5 | * navigate: 998 6 | * tabbar: 998 7 | * toast: 999 8 | */ 9 | 10 | export default { 11 | toast: 10090, 12 | noNetwork: 10080, 13 | // popup包含popup,actionsheet,keyboard,picker的值 14 | popup: 10075, 15 | mask: 10070, 16 | navbar: 980, 17 | topTips: 975, 18 | sticky: 970, 19 | indexListSticky: 965, 20 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/color.scss: -------------------------------------------------------------------------------- 1 | .u-type-primary-light { 2 | color: $u-type-primary-light; 3 | } 4 | 5 | .u-type-warning-light { 6 | color: $u-type-warning-light; 7 | } 8 | 9 | .u-type-success-light { 10 | color: $u-type-success-light; 11 | } 12 | 13 | .u-type-error-light { 14 | color: $u-type-error-light; 15 | } 16 | 17 | .u-type-info-light { 18 | color: $u-type-info-light; 19 | } 20 | 21 | .u-type-primary-light-bg { 22 | background-color: $u-type-primary-light; 23 | } 24 | 25 | .u-type-warning-light-bg { 26 | background-color: $u-type-warning-light; 27 | } 28 | 29 | .u-type-success-light-bg { 30 | background-color: $u-type-success-light; 31 | } 32 | 33 | .u-type-error-light-bg { 34 | background-color: $u-type-error-light; 35 | } 36 | 37 | .u-type-info-light-bg { 38 | background-color: $u-type-info-light; 39 | } 40 | 41 | .u-type-primary-dark { 42 | color: $u-type-primary-dark; 43 | } 44 | 45 | .u-type-warning-dark { 46 | color: $u-type-warning-dark; 47 | } 48 | 49 | .u-type-success-dark { 50 | color: $u-type-success-dark; 51 | } 52 | 53 | .u-type-error-dark { 54 | color: $u-type-error-dark; 55 | } 56 | 57 | .u-type-info-dark { 58 | color: $u-type-info-dark; 59 | } 60 | 61 | .u-type-primary-dark-bg { 62 | background-color: $u-type-primary-dark; 63 | } 64 | 65 | .u-type-warning-dark-bg { 66 | background-color: $u-type-warning-dark; 67 | } 68 | 69 | .u-type-success-dark-bg { 70 | background-color: $u-type-success-dark; 71 | } 72 | 73 | .u-type-error-dark-bg { 74 | background-color: $u-type-error-dark; 75 | } 76 | 77 | .u-type-info-dark-bg { 78 | background-color: $u-type-info-dark; 79 | } 80 | 81 | .u-type-primary-disabled { 82 | color: $u-type-primary-disabled; 83 | } 84 | 85 | .u-type-warning-disabled { 86 | color: $u-type-warning-disabled; 87 | } 88 | 89 | .u-type-success-disabled { 90 | color: $u-type-success-disabled; 91 | } 92 | 93 | .u-type-error-disabled { 94 | color: $u-type-error-disabled; 95 | } 96 | 97 | .u-type-info-disabled { 98 | color: $u-type-info-disabled; 99 | } 100 | 101 | .u-type-primary { 102 | color: $u-type-primary; 103 | } 104 | 105 | .u-type-warning { 106 | color: $u-type-warning; 107 | } 108 | 109 | .u-type-success { 110 | color: $u-type-success; 111 | } 112 | 113 | .u-type-error { 114 | color: $u-type-error; 115 | } 116 | 117 | .u-type-info { 118 | color: $u-type-info; 119 | } 120 | 121 | .u-type-primary-bg { 122 | background-color: $u-type-primary; 123 | } 124 | 125 | .u-type-warning-bg { 126 | background-color: $u-type-warning; 127 | } 128 | 129 | .u-type-success-bg { 130 | background-color: $u-type-success; 131 | } 132 | 133 | .u-type-error-bg { 134 | background-color: $u-type-error; 135 | } 136 | 137 | .u-type-info-bg { 138 | background-color: $u-type-info; 139 | } 140 | 141 | .u-main-color { 142 | color: $u-main-color; 143 | } 144 | 145 | .u-content-color { 146 | color: $u-content-color; 147 | } 148 | 149 | .u-tips-color { 150 | color: $u-tips-color; 151 | } 152 | 153 | .u-light-color { 154 | color: $u-light-color; 155 | } 156 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/common.scss: -------------------------------------------------------------------------------- 1 | .u-relative, 2 | .u-rela { 3 | position: relative; 4 | } 5 | 6 | .u-absolute, 7 | .u-abso { 8 | position: absolute; 9 | } 10 | 11 | // nvue不能用标签命名样式,不能放在微信组件中,否则微信开发工具会报警告,无法使用标签名当做选择器 12 | /* #ifndef APP-NVUE */ 13 | image { 14 | display: inline-block; 15 | } 16 | 17 | // 在weex,也即nvue中,所有元素默认为border-box 18 | view, 19 | text { 20 | box-sizing: border-box; 21 | } 22 | /* #endif */ 23 | 24 | .u-font-xs { 25 | font-size: 22rpx; 26 | } 27 | 28 | .u-font-sm { 29 | font-size: 26rpx; 30 | } 31 | 32 | .u-font-md { 33 | font-size: 28rpx; 34 | } 35 | 36 | .u-font-lg { 37 | font-size: 30rpx; 38 | } 39 | 40 | .u-font-xl { 41 | font-size: 34rpx; 42 | } 43 | 44 | .u-flex { 45 | /* #ifndef APP-NVUE */ 46 | display: flex; 47 | /* #endif */ 48 | flex-direction: row; 49 | align-items: center; 50 | } 51 | 52 | .u-flex-wrap { 53 | flex-wrap: wrap; 54 | } 55 | 56 | .u-flex-nowrap { 57 | flex-wrap: nowrap; 58 | } 59 | 60 | .u-col-center { 61 | align-items: center; 62 | } 63 | 64 | .u-col-top { 65 | align-items: flex-start; 66 | } 67 | 68 | .u-col-bottom { 69 | align-items: flex-end; 70 | } 71 | 72 | .u-row-center { 73 | justify-content: center; 74 | } 75 | 76 | .u-row-left { 77 | justify-content: flex-start; 78 | } 79 | 80 | .u-row-right { 81 | justify-content: flex-end; 82 | } 83 | 84 | .u-row-between { 85 | justify-content: space-between; 86 | } 87 | 88 | .u-row-around { 89 | justify-content: space-around; 90 | } 91 | 92 | .u-text-left { 93 | text-align: left; 94 | } 95 | 96 | .u-text-center { 97 | text-align: center; 98 | } 99 | 100 | .u-text-right { 101 | text-align: right; 102 | } 103 | 104 | .u-flex-col { 105 | /* #ifndef APP-NVUE */ 106 | display: flex; 107 | /* #endif */ 108 | flex-direction: column; 109 | } 110 | 111 | // 定义flex等分 112 | @for $i from 0 through 12 { 113 | .u-flex-#{$i} { 114 | flex: $i; 115 | } 116 | } 117 | 118 | // 定义字体(px)单位,小于20都为px单位字体 119 | @for $i from 9 to 20 { 120 | .u-font-#{$i} { 121 | font-size: $i + px; 122 | } 123 | } 124 | 125 | // 定义字体(rpx)单位,大于或等于20的都为rpx单位字体 126 | @for $i from 20 through 40 { 127 | .u-font-#{$i} { 128 | font-size: $i + rpx; 129 | } 130 | } 131 | 132 | // 定义内外边距,历遍1-80 133 | @for $i from 0 through 80 { 134 | // 只要双数和能被5除尽的数 135 | @if $i % 2 == 0 or $i % 5 == 0 { 136 | // 得出:u-margin-30或者u-m-30 137 | .u-margin-#{$i}, .u-m-#{$i} { 138 | margin: $i + rpx!important; 139 | } 140 | 141 | // 得出:u-padding-30或者u-p-30 142 | .u-padding-#{$i}, .u-p-#{$i} { 143 | padding: $i + rpx!important; 144 | } 145 | 146 | @each $short, $long in l left, t top, r right, b bottom { 147 | // 缩写版,结果如: u-m-l-30 148 | // 定义外边距 149 | .u-m-#{$short}-#{$i} { 150 | margin-#{$long}: $i + rpx!important; 151 | } 152 | 153 | // 定义内边距 154 | .u-p-#{$short}-#{$i} { 155 | padding-#{$long}: $i + rpx!important; 156 | } 157 | 158 | // 完整版,结果如:u-margin-left-30 159 | // 定义外边距 160 | .u-margin-#{$long}-#{$i} { 161 | margin-#{$long}: $i + rpx!important; 162 | } 163 | 164 | // 定义内边距 165 | .u-padding-#{$long}-#{$i} { 166 | padding-#{$long}: $i + rpx!important; 167 | } 168 | } 169 | } 170 | } 171 | 172 | // 重置nvue的默认关于flex的样式 173 | .u-reset-nvue { 174 | flex-direction: row; 175 | align-items: center; 176 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/style.components.scss: -------------------------------------------------------------------------------- 1 | // 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错 2 | @mixin vue-flex($direction: row) { 3 | /* #ifndef APP-NVUE */ 4 | display: flex; 5 | flex-direction: $direction; 6 | /* #endif */ 7 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/style.h5.scss: -------------------------------------------------------------------------------- 1 | /* H5的时候,隐藏滚动条 */ 2 | ::-webkit-scrollbar { 3 | display: none; 4 | width: 0 !important; 5 | height: 0 !important; 6 | -webkit-appearance: none; 7 | background: transparent; 8 | } 9 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/style.mp.scss: -------------------------------------------------------------------------------- 1 | /* start--微信小程序编译后页面有组件名的元素,特别处理--start */ 2 | /* #ifdef MP-WEIXIN || MP-QQ */ 3 | u-td, u-th { 4 | flex: 1; 5 | align-self: stretch; 6 | } 7 | 8 | .u-td { 9 | height: 100%; 10 | } 11 | 12 | u-icon { 13 | display: inline-flex; 14 | align-items: center; 15 | } 16 | 17 | // 各家小程序宫格组件外层设置为100%,避免受到父元素display: flex;的影响 18 | u-grid { 19 | width: 100%; 20 | flex: 0 0 100%; 21 | } 22 | 23 | // 避免小程序线条组件因为父组件display: flex;而失效 24 | u-line { 25 | flex: 1; 26 | } 27 | 28 | u-switch { 29 | display: inline-flex; 30 | align-items: center; 31 | } 32 | 33 | u-dropdown { 34 | flex: 1; 35 | } 36 | /* #endif */ 37 | /* end-微信小程序编译后页面有组件名的元素,特别处理--end */ 38 | 39 | 40 | /* #ifdef MP-QQ || MP-TOUTIAO */ 41 | // 需要做这一切额外的兼容,都是因为TX的无能 42 | u-icon { 43 | line-height: 0; 44 | } 45 | /* #endif */ 46 | 47 | /* start--头条小程序编译后页面有组件名的元素,特别处理--start */ 48 | // 由于头条小程序不支持直接组件名形式写样式,目前只能在写组件的时候给组件加上对应的类名 49 | /* #ifdef MP-TOUTIAO */ 50 | .u-td, .u-th, .u-tr { 51 | flex: 1; 52 | align-self: stretch; 53 | } 54 | 55 | .u-row, .u-col { 56 | flex: 1; 57 | align-self: stretch; 58 | } 59 | 60 | // 避免小程序线条组件因为父组件display: flex;而失效 61 | .u-line { 62 | flex: 1; 63 | } 64 | 65 | .u-dropdown { 66 | flex: 1; 67 | } 68 | /* #endif */ 69 | /* end-头条小程序编译后页面有组件名的元素,特别处理--end */ 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/style.nvue.scss: -------------------------------------------------------------------------------- 1 | .nvue { 2 | font-size: 24rpx; 3 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/css/style.vue.scss: -------------------------------------------------------------------------------- 1 | page { 2 | color: $u-main-color; 3 | font-size: 28rpx; 4 | } 5 | 6 | /* start--去除webkit的默认样式--start */ 7 | .u-fix-ios-appearance { 8 | -webkit-appearance:none; 9 | } 10 | /* end--去除webkit的默认样式--end */ 11 | 12 | /* start--icon图标外层套一个view,让其达到更好的垂直居中的效果--start */ 13 | .u-icon-wrap { 14 | display: flex; 15 | align-items: center; 16 | } 17 | /* end-icon图标外层套一个view,让其达到更好的垂直居中的效果--end */ 18 | 19 | /* start--iPhoneX底部安全区定义--start */ 20 | .safe-area-inset-bottom { 21 | padding-bottom: 0; 22 | padding-bottom: constant(safe-area-inset-bottom); 23 | padding-bottom: env(safe-area-inset-bottom); 24 | } 25 | /* end-iPhoneX底部安全区定义--end */ 26 | 27 | /* start--各种hover点击反馈相关的类名-start */ 28 | .u-hover-class { 29 | // background-color: #f7f8f9!important; 30 | opacity: 0.6; 31 | } 32 | 33 | .u-cell-hover { 34 | background-color: #f7f8f9!important; 35 | } 36 | /* end--各种hover点击反馈相关的类名--end */ 37 | 38 | /* start--文本行数限制--start */ 39 | .u-line-1 { 40 | overflow: hidden; 41 | white-space: nowrap; 42 | text-overflow: ellipsis; 43 | } 44 | 45 | .u-line-2 { 46 | -webkit-line-clamp: 2; 47 | } 48 | 49 | .u-line-3 { 50 | -webkit-line-clamp: 3; 51 | } 52 | 53 | .u-line-4 { 54 | -webkit-line-clamp: 4; 55 | } 56 | 57 | .u-line-5 { 58 | -webkit-line-clamp: 5; 59 | } 60 | 61 | .u-line-2, .u-line-3, .u-line-4, .u-line-5 { 62 | overflow: hidden; 63 | word-break: break-all; 64 | text-overflow: ellipsis; 65 | display: -webkit-box; // 弹性伸缩盒 66 | -webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式 67 | } 68 | 69 | /* end--文本行数限制--end */ 70 | 71 | 72 | /* start--Retina 屏幕下的 1px 边框--start */ 73 | .u-border, 74 | .u-border-bottom, 75 | .u-border-left, 76 | .u-border-right, 77 | .u-border-top, 78 | .u-border-top-bottom { 79 | position: relative 80 | } 81 | 82 | .u-border-bottom:after, 83 | .u-border-left:after, 84 | .u-border-right:after, 85 | .u-border-top-bottom:after, 86 | .u-border-top:after, 87 | .u-border:after { 88 | /* #ifndef APP-NVUE */ 89 | content: ' '; 90 | /* #endif */ 91 | position: absolute; 92 | left: 0; 93 | top: 0; 94 | pointer-events: none; 95 | box-sizing: border-box; 96 | -webkit-transform-origin: 0 0; 97 | transform-origin: 0 0; 98 | // 多加0.1%,能解决有时候边框缺失的问题 99 | width: 199.8%; 100 | height: 199.7%; 101 | transform: scale(0.5, 0.5); 102 | border: 0 solid $u-border-color; 103 | z-index: 2; 104 | } 105 | 106 | .u-border-top:after { 107 | border-top-width: 1px 108 | } 109 | 110 | .u-border-left:after { 111 | border-left-width: 1px 112 | } 113 | 114 | .u-border-right:after { 115 | border-right-width: 1px 116 | } 117 | 118 | .u-border-bottom:after { 119 | border-bottom-width: 1px 120 | } 121 | 122 | .u-border-top-bottom:after { 123 | border-width: 1px 0 124 | } 125 | 126 | .u-border:after { 127 | border-width: 1px 128 | } 129 | /* end--Retina 屏幕下的 1px 边框--end */ 130 | 131 | 132 | /* start--clearfix--start */ 133 | .u-clearfix:after, 134 | .clearfix:after { 135 | /* #ifndef APP-NVUE */ 136 | content: ''; 137 | /* #endif */ 138 | display: table; 139 | clear: both 140 | } 141 | /* end--clearfix--end */ 142 | 143 | /* start--高斯模糊tabbar底部处理--start */ 144 | .u-blur-effect-inset { 145 | width: 750rpx; 146 | height: var(--window-bottom); 147 | background-color: #FFFFFF; 148 | } 149 | /* end--高斯模糊tabbar底部处理--end */ 150 | 151 | /* start--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--start */ 152 | /* #ifdef H5 */ 153 | uni-toast { 154 | z-index: 10090; 155 | } 156 | uni-toast .uni-toast { 157 | z-index: 10090; 158 | } 159 | /* #endif */ 160 | /* end--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--end */ 161 | 162 | /* start--去除button的所有默认样式--start */ 163 | .u-reset-button { 164 | padding: 0; 165 | font-size: inherit; 166 | line-height: inherit; 167 | background-color: transparent; 168 | color: inherit; 169 | } 170 | 171 | .u-reset-button::after { 172 | border: none; 173 | } 174 | /* end--去除button的所有默认样式--end */ 175 | 176 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/$parent.js: -------------------------------------------------------------------------------- 1 | // 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 2 | // this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx 3 | // 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name 4 | // 值(默认为undefined),就是查找最顶层的$parent 5 | export default function $parent(name = undefined) { 6 | let parent = this.$parent; 7 | // 通过while历遍,这里主要是为了H5需要多层解析的问题 8 | while (parent) { 9 | // 父组件 10 | if (parent.$options && parent.$options.name !== name) { 11 | // 如果组件的name不相等,继续上一级寻找 12 | parent = parent.$parent; 13 | } else { 14 | return parent; 15 | } 16 | } 17 | return false; 18 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/addUnit.js: -------------------------------------------------------------------------------- 1 | import validation from './test.js'; 2 | 3 | // 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾 4 | export default function addUnit(value = 'auto', unit = 'rpx') { 5 | value = String(value); 6 | // 用uView内置验证规则中的number判断是否为数值 7 | return validation.number(value) ? `${value}${unit}` : value; 8 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/bem.js: -------------------------------------------------------------------------------- 1 | function bem(name, conf) { 2 | 3 | } 4 | 5 | module.exports.bem = bem; 6 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/color.js: -------------------------------------------------------------------------------- 1 | // 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供 2 | // 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20) 3 | let color = { 4 | primary: "#2979ff", 5 | primaryDark: "#2b85e4", 6 | primaryDisabled: "#a0cfff", 7 | primaryLight: "#ecf5ff", 8 | bgColor: "#f3f4f6", 9 | 10 | info: "#909399", 11 | infoDark: "#82848a", 12 | infoDisabled: "#c8c9cc", 13 | infoLight: "#f4f4f5", 14 | 15 | warning: "#ff9900", 16 | warningDark: "#f29100", 17 | warningDisabled: "#fcbd71", 18 | warningLight: "#fdf6ec", 19 | 20 | error: "#fa3534", 21 | errorDark: "#dd6161", 22 | errorDisabled: "#fab6b6", 23 | errorLight: "#fef0f0", 24 | 25 | success: "#19be6b", 26 | successDark: "#18b566", 27 | successDisabled: "#71d5a1", 28 | successLight: "#dbf1e1", 29 | 30 | mainColor: "#303133", 31 | contentColor: "#606266", 32 | tipsColor: "#909399", 33 | lightColor: "#c0c4cc", 34 | borderColor: "#e4e7ed" 35 | } 36 | 37 | export default color; -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/colorGradient.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 求两个颜色之间的渐变值 3 | * @param {string} startColor 开始的颜色 4 | * @param {string} endColor 结束的颜色 5 | * @param {number} step 颜色等分的份额 6 | * */ 7 | function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) { 8 | let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式 9 | let startR = startRGB[0]; 10 | let startG = startRGB[1]; 11 | let startB = startRGB[2]; 12 | 13 | let endRGB = hexToRgb(endColor, false); 14 | let endR = endRGB[0]; 15 | let endG = endRGB[1]; 16 | let endB = endRGB[2]; 17 | 18 | let sR = (endR - startR) / step; //总差值 19 | let sG = (endG - startG) / step; 20 | let sB = (endB - startB) / step; 21 | let colorArr = []; 22 | for (let i = 0; i < step; i++) { 23 | //计算每一步的hex值 24 | let hex = rgbToHex('rgb(' + Math.round((sR * i + startR)) + ',' + Math.round((sG * i + startG)) + ',' + Math.round((sB * 25 | i + startB)) + ')'); 26 | colorArr.push(hex); 27 | } 28 | return colorArr; 29 | } 30 | 31 | // 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式) 32 | function hexToRgb(sColor, str = true) { 33 | let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; 34 | sColor = sColor.toLowerCase(); 35 | if (sColor && reg.test(sColor)) { 36 | if (sColor.length === 4) { 37 | let sColorNew = "#"; 38 | for (let i = 1; i < 4; i += 1) { 39 | sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); 40 | } 41 | sColor = sColorNew; 42 | } 43 | //处理六位的颜色值 44 | let sColorChange = []; 45 | for (let i = 1; i < 7; i += 2) { 46 | sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2))); 47 | } 48 | if(!str) { 49 | return sColorChange; 50 | } else { 51 | return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`; 52 | } 53 | } else if (/^(rgb|RGB)/.test(sColor)) { 54 | let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",") 55 | return arr.map(val => Number(val)); 56 | } else { 57 | return sColor; 58 | } 59 | }; 60 | 61 | // 将rgb表示方式转换为hex表示方式 62 | function rgbToHex(rgb) { 63 | let _this = rgb; 64 | let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; 65 | if (/^(rgb|RGB)/.test(_this)) { 66 | let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); 67 | let strHex = "#"; 68 | for (let i = 0; i < aColor.length; i++) { 69 | let hex = Number(aColor[i]).toString(16); 70 | hex = String(hex).length == 1 ? 0 + '' + hex : hex; // 保证每个rgb的值为2位 71 | if (hex === "0") { 72 | hex += hex; 73 | } 74 | strHex += hex; 75 | } 76 | if (strHex.length !== 7) { 77 | strHex = _this; 78 | } 79 | return strHex; 80 | } else if (reg.test(_this)) { 81 | let aNum = _this.replace(/#/, "").split(""); 82 | if (aNum.length === 6) { 83 | return _this; 84 | } else if (aNum.length === 3) { 85 | let numHex = "#"; 86 | for (let i = 0; i < aNum.length; i += 1) { 87 | numHex += (aNum[i] + aNum[i]); 88 | } 89 | return numHex; 90 | } 91 | } else { 92 | return _this; 93 | } 94 | } 95 | 96 | 97 | /** 98 | * JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串 99 | * sHex为传入的十六进制的色值 100 | * alpha为rgba的透明度 101 | */ 102 | function colorToRgba(color, alpha = 0.3) { 103 | color = rgbToHex(color) 104 | // 十六进制颜色值的正则表达式 105 | var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ 106 | /* 16进制颜色转为RGB格式 */ 107 | let sColor = color.toLowerCase() 108 | if (sColor && reg.test(sColor)) { 109 | if (sColor.length === 4) { 110 | var sColorNew = '#' 111 | for (let i = 1; i < 4; i += 1) { 112 | sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)) 113 | } 114 | sColor = sColorNew 115 | } 116 | // 处理六位的颜色值 117 | var sColorChange = [] 118 | for (let i = 1; i < 7; i += 2) { 119 | sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2))) 120 | } 121 | // return sColorChange.join(',') 122 | return 'rgba(' + sColorChange.join(',') + ',' + alpha + ')' 123 | } 124 | else { 125 | return sColor 126 | } 127 | } 128 | 129 | export default { 130 | colorGradient, 131 | hexToRgb, 132 | rgbToHex, 133 | colorToRgba 134 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/debounce.js: -------------------------------------------------------------------------------- 1 | let timeout = null; 2 | 3 | /** 4 | * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数 5 | * 6 | * @param {Function} func 要执行的回调函数 7 | * @param {Number} wait 延时的时间 8 | * @param {Boolean} immediate 是否立即执行 9 | * @return null 10 | */ 11 | function debounce(func, wait = 500, immediate = false) { 12 | // 清除定时器 13 | if (timeout !== null) clearTimeout(timeout); 14 | // 立即执行,此类情况一般用不到 15 | if (immediate) { 16 | var callNow = !timeout; 17 | timeout = setTimeout(function() { 18 | timeout = null; 19 | }, wait); 20 | if (callNow) typeof func === 'function' && func(); 21 | } else { 22 | // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法 23 | timeout = setTimeout(function() { 24 | typeof func === 'function' && func(); 25 | }, wait); 26 | } 27 | } 28 | 29 | export default debounce 30 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/deepClone.js: -------------------------------------------------------------------------------- 1 | // 判断arr是否为一个数组,返回一个bool值 2 | function isArray (arr) { 3 | return Object.prototype.toString.call(arr) === '[object Array]'; 4 | } 5 | 6 | // 深度克隆 7 | function deepClone (obj) { 8 | // 对常见的“非”值,直接返回原来值 9 | if([null, undefined, NaN, false].includes(obj)) return obj; 10 | if(typeof obj !== "object" && typeof obj !== 'function') { 11 | //原始类型直接返回 12 | return obj; 13 | } 14 | var o = isArray(obj) ? [] : {}; 15 | for(let i in obj) { 16 | if(obj.hasOwnProperty(i)){ 17 | o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; 18 | } 19 | } 20 | return o; 21 | } 22 | 23 | export default deepClone; 24 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/deepMerge.js: -------------------------------------------------------------------------------- 1 | import deepClone from "./deepClone"; 2 | 3 | // JS对象深度合并 4 | function deepMerge(target = {}, source = {}) { 5 | target = deepClone(target); 6 | if (typeof target !== 'object' || typeof source !== 'object') return false; 7 | for (var prop in source) { 8 | if (!source.hasOwnProperty(prop)) continue; 9 | if (prop in target) { 10 | if (typeof target[prop] !== 'object') { 11 | target[prop] = source[prop]; 12 | } else { 13 | if (typeof source[prop] !== 'object') { 14 | target[prop] = source[prop]; 15 | } else { 16 | if (target[prop].concat && source[prop].concat) { 17 | target[prop] = target[prop].concat(source[prop]); 18 | } else { 19 | target[prop] = deepMerge(target[prop], source[prop]); 20 | } 21 | } 22 | } 23 | } else { 24 | target[prop] = source[prop]; 25 | } 26 | } 27 | return target; 28 | } 29 | 30 | export default deepMerge; -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/getParent.js: -------------------------------------------------------------------------------- 1 | // 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 2 | // this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx 3 | export default function getParent(name, keys) { 4 | let parent = this.$parent; 5 | // 通过while历遍,这里主要是为了H5需要多层解析的问题 6 | while (parent) { 7 | // 父组件 8 | if (parent.$options.name !== name) { 9 | // 如果组件的name不相等,继续上一级寻找 10 | parent = parent.$parent; 11 | } else { 12 | let data = {}; 13 | // 判断keys是否数组,如果传过来的是一个数组,那么直接使用数组元素值当做键值去父组件寻找 14 | if(Array.isArray(keys)) { 15 | keys.map(val => { 16 | data[val] = parent[val] ? parent[val] : ''; 17 | }) 18 | } else { 19 | // 历遍传过来的对象参数 20 | for(let i in keys) { 21 | // 如果子组件有此值则用,无此值则用父组件的值 22 | // 判断是否空数组,如果是,则用父组件的值,否则用子组件的值 23 | if(Array.isArray(keys[i])) { 24 | if(keys[i].length) { 25 | data[i] = keys[i]; 26 | } else { 27 | data[i] = parent[i]; 28 | } 29 | } else if(keys[i].constructor === Object) { 30 | // 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值 31 | if(Object.keys(keys[i]).length) { 32 | data[i] = keys[i]; 33 | } else { 34 | data[i] = parent[i]; 35 | } 36 | } else { 37 | // 只要子组件有传值,即使是false值,也是“传值”了,也需要覆盖父组件的同名参数 38 | data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i]; 39 | } 40 | } 41 | } 42 | return data; 43 | } 44 | } 45 | 46 | return {}; 47 | } -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/guid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 本算法来源于简书开源代码,详见:https://www.jianshu.com/p/fdbf293d0a85 3 | * 全局唯一标识符(uuid,Globally Unique Identifier),也称作 uuid(Universally Unique IDentifier) 4 | * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题 5 | * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱 6 | * v-for的时候,推荐使用后端返回的id而不是循环的index 7 | * @param {Number} len uuid的长度 8 | * @param {Boolean} firstU 将返回的首字母置为"u" 9 | * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制 10 | */ 11 | function guid(len = 32, firstU = true, radix = null) { 12 | let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 13 | let uuid = []; 14 | radix = radix || chars.length; 15 | 16 | if (len) { 17 | // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位 18 | for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]; 19 | } else { 20 | let r; 21 | // rfc4122标准要求返回的uuid中,某些位为固定的字符 22 | uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; 23 | uuid[14] = '4'; 24 | 25 | for (let i = 0; i < 36; i++) { 26 | if (!uuid[i]) { 27 | r = 0 | Math.random() * 16; 28 | uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; 29 | } 30 | } 31 | } 32 | // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class 33 | if (firstU) { 34 | uuid.shift(); 35 | return 'u' + uuid.join(''); 36 | } else { 37 | return uuid.join(''); 38 | } 39 | } 40 | 41 | export default guid; 42 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/queryParams.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 对象转url参数 3 | * @param {*} data,对象 4 | * @param {*} isPrefix,是否自动加上"?" 5 | */ 6 | function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') { 7 | let prefix = isPrefix ? '?' : '' 8 | let _result = [] 9 | if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'; 10 | for (let key in data) { 11 | let value = data[key] 12 | // 去掉为空的参数 13 | if (['', undefined, null].indexOf(value) >= 0) { 14 | continue; 15 | } 16 | // 如果值为数组,另行处理 17 | if (value.constructor === Array) { 18 | // e.g. {ids: [1, 2, 3]} 19 | switch (arrayFormat) { 20 | case 'indices': 21 | // 结果: ids[0]=1&ids[1]=2&ids[2]=3 22 | for (let i = 0; i < value.length; i++) { 23 | _result.push(key + '[' + i + ']=' + value[i]) 24 | } 25 | break; 26 | case 'brackets': 27 | // 结果: ids[]=1&ids[]=2&ids[]=3 28 | value.forEach(_value => { 29 | _result.push(key + '[]=' + _value) 30 | }) 31 | break; 32 | case 'repeat': 33 | // 结果: ids=1&ids=2&ids=3 34 | value.forEach(_value => { 35 | _result.push(key + '=' + _value) 36 | }) 37 | break; 38 | case 'comma': 39 | // 结果: ids=1,2,3 40 | let commaStr = ""; 41 | value.forEach(_value => { 42 | commaStr += (commaStr ? "," : "") + _value; 43 | }) 44 | _result.push(key + '=' + commaStr) 45 | break; 46 | default: 47 | value.forEach(_value => { 48 | _result.push(key + '[]=' + _value) 49 | }) 50 | } 51 | } else { 52 | _result.push(key + '=' + value) 53 | } 54 | } 55 | return _result.length ? prefix + _result.join('&') : '' 56 | } 57 | 58 | export default queryParams; 59 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/random.js: -------------------------------------------------------------------------------- 1 | function random(min, max) { 2 | if (min >= 0 && max > 0 && max >= min) { 3 | let gab = max - min + 1; 4 | return Math.floor(Math.random() * gab + min); 5 | } else { 6 | return 0; 7 | } 8 | } 9 | 10 | export default random; 11 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/randomArray.js: -------------------------------------------------------------------------------- 1 | // 打乱数组 2 | function randomArray(array = []) { 3 | // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0 4 | return array.sort(() => Math.random() - 0.5); 5 | } 6 | 7 | export default randomArray 8 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/route.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷 3 | * 并且带有路由拦截功能 4 | */ 5 | 6 | class Router { 7 | constructor() { 8 | // 原始属性定义 9 | this.config = { 10 | type: 'navigateTo', 11 | url: '', 12 | delta: 1, // navigateBack页面后退时,回退的层数 13 | params: {}, // 传递的参数 14 | animationType: 'pop-in', // 窗口动画,只在APP有效 15 | animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效 16 | intercept: false, // 是否需要拦截 17 | } 18 | // 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文 19 | // 这里在构造函数中进行this绑定 20 | this.route = this.route.bind(this) 21 | } 22 | 23 | // 判断url前面是否有"/",如果没有则加上,否则无法跳转 24 | addRootPath(url) { 25 | return url[0] === '/' ? url : `/${url}` 26 | } 27 | 28 | // 整合路由参数 29 | mixinParam(url, params) { 30 | url = url && this.addRootPath(url) 31 | 32 | // 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary" 33 | // 如果有url中有get参数,转换后无需带上"?" 34 | let query = '' 35 | if (/.*\/.*\?.*=.*/.test(url)) { 36 | // object对象转为get类型的参数 37 | query = uni.$u.queryParams(params, false); 38 | // 因为已有get参数,所以后面拼接的参数需要带上"&"隔开 39 | return url += "&" + query 40 | } else { 41 | // 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号 42 | query = uni.$u.queryParams(params); 43 | return url += query 44 | } 45 | } 46 | 47 | // 对外的方法名称 48 | async route(options = {}, params = {}) { 49 | // 合并用户的配置和内部的默认配置 50 | let mergeConfig = {} 51 | 52 | if (typeof options === 'string') { 53 | // 如果options为字符串,则为route(url, params)的形式 54 | mergeConfig.url = this.mixinParam(options, params) 55 | mergeConfig.type = 'navigateTo' 56 | } else { 57 | mergeConfig = uni.$u.deepClone(options, this.config) 58 | // 否则正常使用mergeConfig中的url和params进行拼接 59 | mergeConfig.url = this.mixinParam(options.url, options.params) 60 | } 61 | 62 | if(params.intercept) { 63 | this.config.intercept = params.intercept 64 | } 65 | // params参数也带给拦截器 66 | mergeConfig.params = params 67 | // 合并内外部参数 68 | mergeConfig = uni.$u.deepMerge(this.config, mergeConfig) 69 | // 判断用户是否定义了拦截器 70 | if (typeof uni.$u.routeIntercept === 'function') { 71 | // 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转 72 | const isNext = await new Promise((resolve, reject) => { 73 | uni.$u.routeIntercept(mergeConfig, resolve) 74 | }) 75 | // 如果isNext为true,则执行路由跳转 76 | isNext && this.openPage(mergeConfig) 77 | } else { 78 | this.openPage(mergeConfig) 79 | } 80 | } 81 | 82 | // 执行路由跳转 83 | openPage(config) { 84 | // 解构参数 85 | const { 86 | url, 87 | type, 88 | delta, 89 | animationType, 90 | animationDuration 91 | } = config 92 | if (config.type == 'navigateTo' || config.type == 'to') { 93 | uni.navigateTo({ 94 | url, 95 | animationType, 96 | animationDuration 97 | }); 98 | } 99 | if (config.type == 'redirectTo' || config.type == 'redirect') { 100 | uni.redirectTo({ 101 | url 102 | }); 103 | } 104 | if (config.type == 'switchTab' || config.type == 'tab') { 105 | uni.switchTab({ 106 | url 107 | }); 108 | } 109 | if (config.type == 'reLaunch' || config.type == 'launch') { 110 | uni.reLaunch({ 111 | url 112 | }); 113 | } 114 | if (config.type == 'navigateBack' || config.type == 'back') { 115 | uni.navigateBack({ 116 | delta 117 | }); 118 | } 119 | } 120 | } 121 | 122 | export default (new Router()).route -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/sys.js: -------------------------------------------------------------------------------- 1 | export function os() { 2 | return uni.getSystemInfoSync().platform; 3 | }; 4 | 5 | export function sys() { 6 | return uni.getSystemInfoSync(); 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/throttle.js: -------------------------------------------------------------------------------- 1 | let timer, flag; 2 | /** 3 | * 节流原理:在一定时间内,只能触发一次 4 | * 5 | * @param {Function} func 要执行的回调函数 6 | * @param {Number} wait 延时的时间 7 | * @param {Boolean} immediate 是否立即执行 8 | * @return null 9 | */ 10 | function throttle(func, wait = 500, immediate = true) { 11 | if (immediate) { 12 | if (!flag) { 13 | flag = true; 14 | // 如果是立即执行,则在wait毫秒内开始时执行 15 | typeof func === 'function' && func(); 16 | timer = setTimeout(() => { 17 | flag = false; 18 | }, wait); 19 | } 20 | } else { 21 | if (!flag) { 22 | flag = true 23 | // 如果是非立即执行,则在wait毫秒内的结束处执行 24 | timer = setTimeout(() => { 25 | flag = false 26 | typeof func === 'function' && func(); 27 | }, wait); 28 | } 29 | 30 | } 31 | }; 32 | export default throttle 33 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/timeFormat.js: -------------------------------------------------------------------------------- 1 | // padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序 2 | // 所以这里做一个兼容polyfill的兼容处理 3 | if (!String.prototype.padStart) { 4 | // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解 5 | String.prototype.padStart = function(maxLength, fillString = ' ') { 6 | if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError( 7 | 'fillString must be String') 8 | let str = this 9 | // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉 10 | if (str.length >= maxLength) return String(str) 11 | 12 | let fillLength = maxLength - str.length, 13 | times = Math.ceil(fillLength / fillString.length) 14 | while (times >>= 1) { 15 | fillString += fillString 16 | if (times === 1) { 17 | fillString += fillString 18 | } 19 | } 20 | return fillString.slice(0, fillLength) + str; 21 | } 22 | } 23 | 24 | // 其他更多是格式化有如下: 25 | // yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 26 | function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') { 27 | // 如果为null,则格式化当前时间 28 | if (!dateTime) dateTime = Number(new Date()); 29 | // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 30 | if (dateTime.toString().length == 10) dateTime *= 1000; 31 | let date = new Date(Number(dateTime)); 32 | let ret; 33 | let opt = { 34 | "y+": date.getFullYear().toString(), // 年 35 | "m+": (date.getMonth() + 1).toString(), // 月 36 | "d+": date.getDate().toString(), // 日 37 | "h+": date.getHours().toString(), // 时 38 | "M+": date.getMinutes().toString(), // 分 39 | "s+": date.getSeconds().toString() // 秒 40 | // 有其他格式化字符需求可以继续添加,必须转化成字符串 41 | }; 42 | for (let k in opt) { 43 | ret = new RegExp("(" + k + ")").exec(fmt); 44 | if (ret) { 45 | fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0"))) 46 | }; 47 | }; 48 | return fmt; 49 | } 50 | 51 | export default timeFormat 52 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/timeFrom.js: -------------------------------------------------------------------------------- 1 | import timeFormat from '../../libs/function/timeFormat.js'; 2 | 3 | /** 4 | * 时间戳转为多久之前 5 | * @param String timestamp 时间戳 6 | * @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式; 7 | * 如果为布尔值false,无论什么时间,都返回多久以前的格式 8 | */ 9 | function timeFrom(dateTime = null, format = 'yyyy-mm-dd') { 10 | // 如果为null,则格式化当前时间 11 | if (!dateTime) dateTime = Number(new Date()); 12 | // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 13 | if (dateTime.toString().length == 10) dateTime *= 1000; 14 | let timestamp = + new Date(Number(dateTime)); 15 | 16 | let timer = (Number(new Date()) - timestamp) / 1000; 17 | // 如果小于5分钟,则返回"刚刚",其他以此类推 18 | let tips = ''; 19 | switch (true) { 20 | case timer < 300: 21 | tips = '刚刚'; 22 | break; 23 | case timer >= 300 && timer < 3600: 24 | tips = parseInt(timer / 60) + '分钟前'; 25 | break; 26 | case timer >= 3600 && timer < 86400: 27 | tips = parseInt(timer / 3600) + '小时前'; 28 | break; 29 | case timer >= 86400 && timer < 2592000: 30 | tips = parseInt(timer / 86400) + '天前'; 31 | break; 32 | default: 33 | // 如果format为false,则无论什么时间戳,都显示xx之前 34 | if(format === false) { 35 | if(timer >= 2592000 && timer < 365 * 86400) { 36 | tips = parseInt(timer / (86400 * 30)) + '个月前'; 37 | } else { 38 | tips = parseInt(timer / (86400 * 365)) + '年前'; 39 | } 40 | } else { 41 | tips = timeFormat(timestamp, format); 42 | } 43 | } 44 | return tips; 45 | } 46 | 47 | export default timeFrom; 48 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/toast.js: -------------------------------------------------------------------------------- 1 | function toast(title, duration = 1500) { 2 | uni.showToast({ 3 | title: title, 4 | icon: 'none', 5 | duration: duration 6 | }) 7 | } 8 | 9 | export default toast 10 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/trim.js: -------------------------------------------------------------------------------- 1 | function trim(str, pos = 'both') { 2 | if (pos == 'both') { 3 | return str.replace(/^\s+|\s+$/g, ""); 4 | } else if (pos == "left") { 5 | return str.replace(/^\s*/, ''); 6 | } else if (pos == 'right') { 7 | return str.replace(/(\s*$)/g, ""); 8 | } else if (pos == 'all') { 9 | return str.replace(/\s+/g, ""); 10 | } else { 11 | return str; 12 | } 13 | } 14 | 15 | export default trim 16 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/function/type2icon.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 根据主题type值,获取对应的图标 3 | * @param String type 主题名称,primary|info|error|warning|success 4 | * @param String fill 是否使用fill填充实体的图标 5 | */ 6 | function type2icon(type = 'success', fill = false) { 7 | // 如果非预置值,默认为success 8 | if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'; 9 | let iconName = ''; 10 | // 目前(2019-12-12),info和primary使用同一个图标 11 | switch (type) { 12 | case 'primary': 13 | iconName = 'info-circle'; 14 | break; 15 | case 'info': 16 | iconName = 'info-circle'; 17 | break; 18 | case 'error': 19 | iconName = 'close-circle'; 20 | break; 21 | case 'warning': 22 | iconName = 'error-circle'; 23 | break; 24 | case 'success': 25 | iconName = 'checkmark-circle'; 26 | break; 27 | default: 28 | iconName = 'checkmark-circle'; 29 | } 30 | // 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的 31 | if (fill) iconName += '-fill'; 32 | return iconName; 33 | } 34 | 35 | export default type2icon 36 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/mixin/mixin.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | data() { 3 | return {} 4 | }, 5 | onLoad() { 6 | // getRect挂载到$u上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出 7 | this.$u.getRect = this.$uGetRect 8 | }, 9 | methods: { 10 | // 查询节点信息 11 | // 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21) 12 | // 解决办法为在组件根部再套一个没有任何作用的view元素 13 | $uGetRect(selector, all) { 14 | return new Promise(resolve => { 15 | uni.createSelectorQuery(). 16 | in(this)[all ? 'selectAll' : 'select'](selector) 17 | .boundingClientRect(rect => { 18 | if (all && Array.isArray(rect) && rect.length) { 19 | resolve(rect) 20 | } 21 | if (!all && rect) { 22 | resolve(rect) 23 | } 24 | }) 25 | .exec() 26 | }) 27 | }, 28 | getParentData(parentName = '') { 29 | // 避免在created中去定义parent变量 30 | if(!this.parent) this.parent = false; 31 | // 这里的本质原理是,通过获取父组件实例(也即u-radio-group的this) 32 | // 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性 33 | // 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化 34 | this.parent = this.$u.$parent.call(this, parentName); 35 | if(this.parent) { 36 | // 历遍parentData中的属性,将parent中的同名属性赋值给parentData 37 | Object.keys(this.parentData).map(key => { 38 | this.parentData[key] = this.parent[key]; 39 | }); 40 | } 41 | }, 42 | // 阻止事件冒泡 43 | preventEvent(e) { 44 | e && e.stopPropagation && e.stopPropagation() 45 | } 46 | }, 47 | onReachBottom() { 48 | uni.$emit('uOnReachBottom') 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/mixin/mpShare.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | onLoad() { 3 | // 设置默认的转发参数 4 | this.$u.mpShare = { 5 | title: '', // 默认为小程序名称 6 | path: '', // 默认为当前页面路径 7 | imageUrl: '' // 默认为当前页面的截图 8 | } 9 | }, 10 | onShareAppMessage() { 11 | return this.$u.mpShare 12 | }, 13 | // #ifdef MP-WEIXIN 14 | onShareTimeline() { 15 | return this.$u.mpShare 16 | } 17 | // #endif 18 | } 19 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/store/index.js: -------------------------------------------------------------------------------- 1 | // 暂时不用vuex模块方式实现,将该方法直接放入到/store/index.js中 2 | const module = { 3 | actions: { 4 | $uStore({rootState}, params) { 5 | let nameArr = params.name.split('.'); 6 | if(nameArr.length >= 2) { 7 | let obj = rootState[nameArr[0]]; 8 | for(let i = 1; i < nameArr.length - 1; i ++) { 9 | obj = obj[nameArr[i]]; 10 | } 11 | obj[nameArr[nameArr.length - 1]] = params.value; 12 | } else { 13 | rootState[params.name] = params.value; 14 | } 15 | } 16 | } 17 | } 18 | 19 | export default module -------------------------------------------------------------------------------- /plugins/uview-ui/libs/util/emitter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 递归使用 call 方式this指向 3 | * @param componentName // 需要找的组件的名称 4 | * @param eventName // 事件名称 5 | * @param params // 需要传递的参数 6 | */ 7 | function broadcast(componentName, eventName, params) { 8 | // 循环子节点找到名称一样的子节点 否则 递归 当前子节点 9 | this.$children.map(child=>{ 10 | if (componentName===child.$options.name) { 11 | child.$emit.apply(child,[eventName].concat(params)) 12 | }else { 13 | broadcast.apply(child,[componentName,eventName].concat(params)) 14 | } 15 | }) 16 | } 17 | export default { 18 | methods: { 19 | /** 20 | * 派发 (向上查找) (一个) 21 | * @param componentName // 需要找的组件的名称 22 | * @param eventName // 事件名称 23 | * @param params // 需要传递的参数 24 | */ 25 | dispatch(componentName, eventName, params) { 26 | let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点 27 | let name = parent.$options.name; // 获取当前组件实例的name 28 | // 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点 29 | // 循环出当前名称的一样的组件实例 30 | while (parent && (!name||name!==componentName)) { 31 | parent = parent.$parent; 32 | if (parent) { 33 | name = parent.$options.name; 34 | } 35 | } 36 | // 有节点表示当前找到了name一样的实例 37 | if (parent) { 38 | parent.$emit.apply(parent,[eventName].concat(params)) 39 | } 40 | }, 41 | /** 42 | * 广播 (向下查找) (广播多个) 43 | * @param componentName // 需要找的组件的名称 44 | * @param eventName // 事件名称 45 | * @param params // 需要传递的参数 46 | */ 47 | broadcast(componentName, eventName, params) { 48 | broadcast.call(this,componentName, eventName, params) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /plugins/uview-ui/libs/util/province.js: -------------------------------------------------------------------------------- 1 | var provinceData=[{"label":"北京市","value":"11"},{"label":"天津市","value":"12"},{"label":"河北省","value":"13"},{"label":"山西省","value":"14"},{"label":"内蒙古自治区","value":"15"},{"label":"辽宁省","value":"21"},{"label":"吉林省","value":"22"},{"label":"黑龙江省","value":"23"},{"label":"上海市","value":"31"},{"label":"江苏省","value":"32"},{"label":"浙江省","value":"33"},{"label":"安徽省","value":"34"},{"label":"福建省","value":"35"},{"label":"江西省","value":"36"},{"label":"山东省","value":"37"},{"label":"河南省","value":"41"},{"label":"湖北省","value":"42"},{"label":"湖南省","value":"43"},{"label":"广东省","value":"44"},{"label":"广西壮族自治区","value":"45"},{"label":"海南省","value":"46"},{"label":"重庆市","value":"50"},{"label":"四川省","value":"51"},{"label":"贵州省","value":"52"},{"label":"云南省","value":"53"},{"label":"西藏自治区","value":"54"},{"label":"陕西省","value":"61"},{"label":"甘肃省","value":"62"},{"label":"青海省","value":"63"},{"label":"宁夏回族自治区","value":"64"},{"label":"新疆维吾尔自治区","value":"65"},{"label":"台湾","value":"66"},{"label":"香港","value":"67"},{"label":"澳门","value":"68"}];export default provinceData; -------------------------------------------------------------------------------- /plugins/uview-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uview-ui", 3 | "version": "1.8.2", 4 | "description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水", 5 | "main": "index.js", 6 | "keywords": [ 7 | "uview", 8 | "uView", 9 | "uni-app", 10 | "uni-app ui", 11 | "uniapp", 12 | "uviewui", 13 | "uview ui", 14 | "uviewUI", 15 | "uViewui", 16 | "uViewUI", 17 | "uView UI", 18 | "uni ui", 19 | "uni UI", 20 | "uniapp ui", 21 | "ui", 22 | "UI框架", 23 | "uniapp ui框架", 24 | "uniapp UI" 25 | ], 26 | "scripts": { 27 | "test": "echo \"Error: no test specified\" && exit 1" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "" 32 | }, 33 | "devDependencies": { 34 | "node-sass": "^4.14.0", 35 | "sass-loader": "^8.0.2" 36 | }, 37 | "author": "uView", 38 | "license": "MIT" 39 | } 40 | -------------------------------------------------------------------------------- /plugins/uview-ui/theme.scss: -------------------------------------------------------------------------------- 1 | // 此文件为uView的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于 2 | // uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大, 3 | // 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入 4 | 5 | $u-main-color: #303133; 6 | $u-content-color: #606266; 7 | $u-tips-color: #909399; 8 | $u-light-color: #c0c4cc; 9 | $u-border-color: #e4e7ed; 10 | $u-bg-color: #f3f4f6; 11 | 12 | $u-type-primary: #2979ff; 13 | $u-type-primary-light: #ecf5ff; 14 | $u-type-primary-disabled: #a0cfff; 15 | $u-type-primary-dark: #2b85e4; 16 | 17 | $u-type-warning: #ff9900; 18 | $u-type-warning-disabled: #fcbd71; 19 | $u-type-warning-dark: #f29100; 20 | $u-type-warning-light: #fdf6ec; 21 | 22 | $u-type-success: #19be6b; 23 | $u-type-success-disabled: #71d5a1; 24 | $u-type-success-dark: #18b566; 25 | $u-type-success-light: #dbf1e1; 26 | 27 | $u-type-error: #fa3534; 28 | $u-type-error-disabled: #fab6b6; 29 | $u-type-error-dark: #dd6161; 30 | $u-type-error-light: #fef0f0; 31 | 32 | $u-type-info: #909399; 33 | $u-type-info-disabled: #c8c9cc; 34 | $u-type-info-dark: #82848a; 35 | $u-type-info-light: #f4f4f5; 36 | 37 | $u-form-item-height: 70rpx; 38 | $u-form-item-border-color: #dcdfe6; 39 | -------------------------------------------------------------------------------- /router/index.js: -------------------------------------------------------------------------------- 1 | 2 | import Vue from 'vue' 3 | //这里仅示范npm安装方式的引入,其它方式引入请看最上面【安装】部分 4 | import Router from 'uni-simple-router' 5 | 6 | Vue.use(Router) 7 | //初始化 8 | const router = new Router({ 9 | encodeURI:false, 10 | h5:{ 11 | paramsToQuery:true, 12 | }, 13 | routes: ROUTES //路由表 14 | }); 15 | 16 | //全局路由前置守卫 17 | router.beforeEach((to, from, next) => { 18 | next() 19 | }) 20 | // 全局路由后置守卫 21 | router.afterEach((to, from) => { 22 | }) 23 | export default router; 24 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | 静态资源目录,尽量使用网络的方式 -------------------------------------------------------------------------------- /static/css/login.scss: -------------------------------------------------------------------------------- 1 | page { 2 | background: #fff; 3 | } 4 | 5 | .send-msg { 6 | border-radius: 30px; 7 | color: black; 8 | background: white; 9 | height: 30px; 10 | font-size: 14px; 11 | line-height: 30px; 12 | } 13 | 14 | .container { 15 | top: 0; 16 | padding-top: 32upx; 17 | position: relative; 18 | width: 100%; 19 | height: 100%; 20 | overflow: hidden; 21 | background: #fff; 22 | } 23 | 24 | .wrapper { 25 | position: relative; 26 | z-index: 90; 27 | background: #fff; 28 | padding-bottom: 20px; 29 | } 30 | 31 | .confirm-btn { 32 | width: 300px; 33 | height: 42px; 34 | line-height: 42px; 35 | border-radius: 30px; 36 | margin-top: 40rpx; 37 | background-color: #F00; 38 | color: #fff; 39 | font-size: 32rpx; 40 | 41 | &:after { 42 | border-radius: 60px; 43 | } 44 | 45 | &.disable{ 46 | background-color: #CCC; 47 | } 48 | } 49 | .form{ 50 | padding: 0 60rpx; 51 | } 52 | .quick-login{ 53 | text-align: center; 54 | margin-top: 30rpx; 55 | .title{ 56 | color: #AAA; 57 | } 58 | .icons{ 59 | padding-top: 20rpx; 60 | 61 | .ql-icon{ 62 | margin-left: 20rpx; 63 | &:first{ 64 | margin-left: 0; 65 | } 66 | } 67 | } 68 | } 69 | .agree-box{ 70 | display: flex; 71 | justify-content: center; 72 | justify-items: center; 73 | margin-top: 60rpx; 74 | .text{ 75 | line-height: 60rpx; 76 | } 77 | } -------------------------------------------------------------------------------- /static/css/member_order_list.scss: -------------------------------------------------------------------------------- 1 | .order { 2 | width: 710rpx; 3 | background-color: #ffffff; 4 | margin: 20rpx auto; 5 | border-radius: 20rpx; 6 | box-sizing: border-box; 7 | padding: 20rpx; 8 | font-size: 28rpx; 9 | .top { 10 | display: flex; 11 | justify-content: space-between; 12 | .left { 13 | display: flex; 14 | align-items: center; 15 | .store { 16 | margin: 0 10rpx; 17 | font-size: 32rpx; 18 | font-weight: bold; 19 | } 20 | } 21 | .right { 22 | color: $u-type-warning-dark; 23 | } 24 | } 25 | .item { 26 | display: flex; 27 | margin: 20rpx 0 0; 28 | .left { 29 | margin-right: 20rpx; 30 | image { 31 | width: 200rpx; 32 | height: 200rpx; 33 | border-radius: 10rpx; 34 | } 35 | } 36 | .content { 37 | .title { 38 | font-size: 28rpx; 39 | line-height: 50rpx; 40 | } 41 | .type { 42 | margin: 10rpx 0; 43 | font-size: 24rpx; 44 | color: $u-tips-color; 45 | } 46 | .delivery-time { 47 | color: #e5d001; 48 | font-size: 24rpx; 49 | } 50 | } 51 | .right { 52 | margin-left: 10rpx; 53 | padding-top: 20rpx; 54 | text-align: right; 55 | .decimal { 56 | font-size: 24rpx; 57 | margin-top: 4rpx; 58 | } 59 | .number { 60 | color: $u-tips-color; 61 | font-size: 24rpx; 62 | } 63 | } 64 | } 65 | .total { 66 | margin-top: 20rpx; 67 | text-align: right; 68 | font-size: 24rpx; 69 | .total-price { 70 | font-size: 32rpx; 71 | } 72 | } 73 | .bottom { 74 | display: flex; 75 | margin-top: 40rpx; 76 | padding: 0 10rpx; 77 | justify-content: space-between; 78 | align-items: center; 79 | .btn { 80 | line-height: 52rpx; 81 | width: 160rpx; 82 | border-radius: 26rpx; 83 | border: 2rpx solid $u-border-color; 84 | font-size: 26rpx; 85 | text-align: center; 86 | color: $u-type-info-dark; 87 | } 88 | .evaluate { 89 | color: $u-type-warning-dark; 90 | border-color: $u-type-warning-dark; 91 | } 92 | } 93 | } 94 | .centre { 95 | text-align: center; 96 | margin: 200rpx auto; 97 | font-size: 32rpx; 98 | image { 99 | width: 164rpx; 100 | height: 164rpx; 101 | border-radius: 50%; 102 | margin-bottom: 20rpx; 103 | } 104 | .tips { 105 | font-size: 24rpx; 106 | color: #999999; 107 | margin-top: 20rpx; 108 | } 109 | .btn { 110 | margin: 80rpx auto; 111 | width: 200rpx; 112 | border-radius: 32rpx; 113 | line-height: 64rpx; 114 | color: #ffffff; 115 | font-size: 26rpx; 116 | background: linear-gradient(270deg, rgba(249, 116, 90, 1) 0%, rgba(255, 158, 1, 1) 100%); 117 | } 118 | } 119 | .wrap { 120 | display: flex; 121 | flex-direction: column; 122 | height: calc(100vh - var(--window-top)); 123 | width: 100%; 124 | } 125 | .swiper-box { 126 | flex: 1; 127 | } 128 | .swiper-item { 129 | height: 100%; 130 | } -------------------------------------------------------------------------------- /static/images/btn_sku_popup_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/btn_sku_popup_close.png -------------------------------------------------------------------------------- /static/images/tabber/cart-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/cart-a.png -------------------------------------------------------------------------------- /static/images/tabber/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/cart.png -------------------------------------------------------------------------------- /static/images/tabber/fenlei-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/fenlei-a.png -------------------------------------------------------------------------------- /static/images/tabber/fenlei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/fenlei.png -------------------------------------------------------------------------------- /static/images/tabber/home-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/home-a.png -------------------------------------------------------------------------------- /static/images/tabber/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/home.png -------------------------------------------------------------------------------- /static/images/tabber/user-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/user-a.png -------------------------------------------------------------------------------- /static/images/tabber/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackchen01/gdshop-uniapp/168de0f760ad6c5e1fc4740bacb58791cd5da241/static/images/tabber/user.png -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | vuex目录 -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import createPersistedState from 'vuex-persistedstate' 4 | // import testModules from './modules/test' 5 | 6 | Vue.use(Vuex) 7 | 8 | const state = { 9 | favorites: [], 10 | username:"", 11 | demoxxxx: "" 12 | } 13 | const mutations = { 14 | setUsername: (state, value) => { 15 | state.username = value; 16 | }, 17 | } 18 | 19 | let modules = {} 20 | const files = require.context('./modules', false, /\.js$/) 21 | files.keys().map(key => { 22 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default 23 | }) 24 | 25 | export default new Vuex.Store({ 26 | /* 27 | modules : { 28 | test:testModules 29 | },*/ 30 | modules: modules, 31 | state, 32 | mutations, 33 | plugins: [ 34 | // 可以有多个持久化实例 35 | createPersistedState({ 36 | key: 'app_config_data', // 状态保存到本地的 key 37 | paths: ['favorites', 'username'], // 要持久化的状态,在state里面取,如果有嵌套,可以 a.b.c 38 | storage: { // 存储方式定义 39 | getItem: (key) => uni.getStorageSync(key), // 获取 40 | setItem: (key, value) => uni.setStorageSync(key, value), // 存储 41 | removeItem: (key) => uni.removeStorageSync(key) // 删除 42 | } 43 | }) 44 | ] 45 | }) -------------------------------------------------------------------------------- /store/modules/test.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | test: '测试VUEX', 5 | }, 6 | mutations: { 7 | setTest: (state, value) => { 8 | state.test = value; 9 | }, 10 | }, 11 | actions: { 12 | 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /template.h5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <%= htmlWebpackPlugin.options.title %> 10 | 11 | 16 | 17 | 18 | 19 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /uni.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 下方引入的为uView UI的集成样式文件,为scss预处理器,其中包含了一些"u-"开头的自定义变量 3 | * uView自定义的css类名和scss变量,均以"u-"开头,不会造成冲突,请放心使用 4 | */ 5 | @import 'plugins/uview-ui/theme.scss'; 6 | 7 | $gdbase-type-primary: #d81e06; 8 | 9 | .page-bg-gray{ 10 | position: fixed; 11 | left: 0; 12 | top: 0; 13 | width: 100%; 14 | height: 100%; 15 | z-index: -1; 16 | background: #f5f5f5; 17 | } -------------------------------------------------------------------------------- /utils/README.md: -------------------------------------------------------------------------------- 1 | 通用工具目录 -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | import * as article from './modules/article' 2 | 3 | const utils = { 4 | article 5 | } 6 | 7 | export default utils -------------------------------------------------------------------------------- /utils/modules/article.js: -------------------------------------------------------------------------------- 1 | import router from '@/router' 2 | 3 | export function gotoArticle (_type) { 4 | router.push({name:'article/view',params:{type:_type}}) 5 | } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const TransformPages = require('uni-read-pages') 2 | const {webpack} = new TransformPages() 3 | 4 | module.exports = { 5 | // 配置路径别名 6 | configureWebpack: { 7 | devServer: { 8 | disableHostCheck: true 9 | }, 10 | plugins: [ 11 | new webpack.DefinePlugin({ 12 | ROUTES: webpack.DefinePlugin.runtimeValue(() => { 13 | const tfPages = new TransformPages({ 14 | includes: ['path', 'name', 'meta','aliasPath'] 15 | }); 16 | return JSON.stringify(tfPages.routes) 17 | }, true ) 18 | }) 19 | ] 20 | }, 21 | transpileDependencies: [ 22 | 'uni-simple-router' 23 | ] 24 | } 25 | --------------------------------------------------------------------------------