diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..37d0a69 --- /dev/null +++ b/App.vue @@ -0,0 +1,86 @@ + + + diff --git a/apis/index.js b/apis/index.js new file mode 100644 index 0000000..30a2c44 --- /dev/null +++ b/apis/index.js @@ -0,0 +1,158 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + */ + +import store from '@/store' + +// 基础配置 +const config = { + apiUrl : 'http://api.gout.shangkelian.cn/api/', // 正式环境 + timeout : 60000 +} + +let loginHintState = false + +// 网络请求 +const request = (parameter, hideLoding) => { + // 检查url配置 + if(parameter.url === 'undefined' || parameter.url === ''){ + uni.showToast({ + title: '请求地址不能为空', + icon : 'none' + }) + return + } + // 注入header + config.header = { + 'Accept': 'application/json', + 'Authorization': store.getters.getToken || '' + } + + // 加载提示 + if(!hideLoding) uni.showLoading({ + title: '加载中', + mask : true + }); + + // 请求实例 + return new Promise((resolve, reject) => { + uni.request({ + url : config.apiUrl + parameter.url, + timeout : config.timeout, + header : config.header || {}, + data : parameter.data || {}, + method : parameter.method || 'GET', + success : res => { + if (res.header.Authorization){ + updateToken('token', res.header.Authorization) + } + if(res.statusCode === 200){ + uni.hideLoading() + const resolveData = res.data + if(resolveData.status_code === 200) { + resolve(resolveData.data) + return + } + if(resolveData.status_code === 401) { + loginHint() + return + } + reject(resolveData) + return + } + errToast(res.statusCode) + } + }) + }) +} + +// 文件上传 +const uploading = (paths) => { + uni.showLoading({ + title: '上传中', + mask : true + }); + // 注入header + config.header = { + 'Accept': 'application/json', + 'Authorization': store.getters.getToken || '' + } + // 上传图片 + return new Promise((resolve, reject) => { + uni.uploadFile({ + url : config.apiUrl + 'storage/uploads', + files : paths, + header : config.header || {}, + success : res=>{ + if(res.statusCode === 200){ + uni.hideLoading() + let updData = JSON.parse(res.data) + if(updData.status_code === 200){ + resolve(updData.data) + return + } + reject(updData) + return + } + errToast(res.statusCode) + } + }) + }) +} + +// 处理一些http请求错误提示 +const errToast = (code) => { + switch (code){ + case 404: + uni.showToast({ + title: code + '接口不存在,请联系系统管理员', + icon : 'none' + }) + break; + case 405: + uni.showToast({ + title: code + '请检查接口请求方式错误', + icon : 'none' + }) + break; + case 500: + uni.showToast({ + title: code + '服务端错误,请检查服务器信息', + icon : 'none' + }) + break; + } +} + +// 更新token +const updateToken = (token) => { + store.commit('setToken', token) +} + +// 处理登录提示 +const loginHint = () => { + if( loginHintState ) return + if(!loginHintState) loginHintState = true + updateToken('') + uni.showModal({ + title: '登录提示', + content: '您的登录信息已过期,请重新登录', + confirmColor: '#8b64fd', + showCancel:false, + success: res=> { + loginHintState = false + if (res.confirm) uni.reLaunch({ + url: '/pages/index/index' + }) + } + }) +} + +export { + request, + uploading, + config +} diff --git a/apis/interfaces/auth.js b/apis/interfaces/auth.js new file mode 100644 index 0000000..033e570 --- /dev/null +++ b/apis/interfaces/auth.js @@ -0,0 +1,31 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + * moduleName: 鉴权 + */ + +import { request } from '../index' + +// 验证码登录 +const smsAuth = (data) =>{ + return request({ + url: "user/auth/sms", + method: 'POST', + data: data + }) +} + +// 获取验证码 +const getSms = (data) =>{ + return request({ + url: "user/auth/verify", + method: 'POST', + data: data + }) +} +export { + smsAuth, + getSms +} diff --git a/apis/interfaces/gout.js b/apis/interfaces/gout.js new file mode 100644 index 0000000..c20175f --- /dev/null +++ b/apis/interfaces/gout.js @@ -0,0 +1,128 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + * moduleName:腾风 病例 + */ + +import { request } from '../index' + +// 添加病例-前置 +const goutCreate = () => { + return request({ + url: 'gout/result/create' + }) +} + +// 添加病例 +const goutAdd = (data) => { + return request({ + url: 'gout/result', + method: 'POST', + data: data + }) +} + +// 查看病例 +const goutSee = () => { + return request({ + url: 'gout/result' + }) +} + +// 添加病例-图片 +const goutCover = (case_id, data) => { + return request({ + url: 'gout/result/' + case_id + '/add_cover', + method: 'POST', + data: data + }) +} + +// 查看尿酸 +const lastLog = () => { + return request({ + url: 'gout/result/last_log' + }) +} + +// 添加尿酸值 +const AddlastLog = (user_case_id, data) => { + return request({ + url: 'gout/result/' + user_case_id + '/logs', + method: 'POST', + data: data + }) +} + +// 尿酸记录 +const ListLog = (user_case_id, data) => { + return request({ + url: 'gout/result/' + user_case_id + '/logs', + data: data + }) +} + +// 尿酸记录-详情 +const DetLog = (user_case_id) => { + return request({ + url: 'gout/result/logs/' + user_case_id + }) +} + +// 删除尿酸记录 +const DelLog = (user_case_id) => { + return request({ + url: 'gout/result/logs/' + user_case_id, + method: 'DELETE' + }) +} + +// 病友记 +const allLogs = (data) => { + return request({ + url: 'gout/result/all_logs', + data: data + }) +} + + +// 食物列表/嘌呤查询 +const foodList = (data) => { + return request({ + url: 'gout/food', + data: data + }) +} + +// 食物详情 +const foodDet = (food_id) => { + return request({ + url: 'gout/food/' + food_id + }, true) +} + +// 食物投票 +const foodVote = (food_id, option_id) => { + return request({ + url: 'gout/food/' + food_id + '/' + option_id, + method: 'POST' + }) +} + +export { + goutCreate, + goutAdd, + goutSee, + goutCover, + lastLog, + AddlastLog, + ListLog, + DetLog, + DelLog, + allLogs, + foodList, + foodDet, + foodVote +} diff --git a/apis/interfaces/mall.js b/apis/interfaces/mall.js new file mode 100644 index 0000000..b1e36a7 --- /dev/null +++ b/apis/interfaces/mall.js @@ -0,0 +1,77 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + * moduleName: 腾风首页 + */ + +import { request } from '../index' + +// 首页 +const index = () => { + return request({ + url: 'mall' + }) +} + +// 商品详情 +const goods = (goods_id) => { + return request({ + url: 'mall/goods/' + goods_id + }) +} + +// 文章详情 +const artiicle = (artiicle_id) => { + return request({ + url: 'cms/articles/' + artiicle_id + }) +} + +// 退货单-审核 +const storeAudit = (refund_id, data) => { + return request({ + url: 'manages/refunds/' + refund_id + '/audit', + method: 'POST', + data: data + }) +} + +// 提货单列表 +const storeDeliver = (state) => { + return request({ + url: 'manages/shipments', + data: { + state + } + }) +} + +// 领取商品 +const Receive = (data) => { + return request({ + url: 'mall/buy/samples', + method: 'POST', + data: data + }) +} + +// 省市区-获取 +const create = (data) => { + return request({ + url: 'mall/addresses/create', + data: data + }) +} + + +export { + index, + goods, + artiicle, + storeAudit, + storeDeliver, + Receive, + create +} diff --git a/apis/interfaces/uploading.js b/apis/interfaces/uploading.js new file mode 100644 index 0000000..31b85f7 --- /dev/null +++ b/apis/interfaces/uploading.js @@ -0,0 +1,17 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + * moduleName: 上传图片 + */ + +import { uploading as upd } from '../index' + +const uploads = (paths) => { + return upd(paths) +} + +export { + uploads +} diff --git a/apis/interfaces/user.js b/apis/interfaces/user.js new file mode 100644 index 0000000..a83005c --- /dev/null +++ b/apis/interfaces/user.js @@ -0,0 +1,72 @@ + +/** + * Web唐明明 + * 匆匆数载恍如梦,岁月迢迢华发增。 + * 碌碌无为枉半生,一朝惊醒万事空。 + * moduleName:腾风 我的 + */ + +import { request } from '../index' + +// 用户信息 +const userIndex = () => { + return request({ + url: 'user/info' + }) +} + +// 上传头像 +const setting = (key, data) => { + return request({ + url: 'user/setting/' + key, + method: 'PUT', + data: data + }) +} + +// 订单列表 +const orders = (data) => { + return request({ + url: 'mall/orders', + data: data + }) +} + +// 订单详情 +const goodsDet = (order_no) => { + return request({ + url: 'mall/orders/' + order_no + }) +} + +// 订单签收 +const goodsSign = (order_no) => { + return request({ + url: 'mall/orders/' + order_no + '/sign', + method: 'PUT' + }, true) +} + +// 我的伙伴 +const relations = () => { + return request({ + url: 'user/relations' + }) +} + +// 我的推广码 +const invite = () => { + return request({ + url: 'user/invite' + }) +} + +export { + userIndex, + setting, + orders, + goodsDet, + goodsSign, + relations, + invite +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..8fd5617 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + +
+ +
+ + + diff --git a/js_sdk/junyi-h5-copy/junyi-h5-copy/junyi-h5-copy.js b/js_sdk/junyi-h5-copy/junyi-h5-copy/junyi-h5-copy.js new file mode 100644 index 0000000..f489838 --- /dev/null +++ b/js_sdk/junyi-h5-copy/junyi-h5-copy/junyi-h5-copy.js @@ -0,0 +1,18 @@ +export default function h5Copy(content) { + + if (!document.queryCommandSupported('copy')) { + // 不支持 + return false + } + + let textarea = document.createElement("textarea") + textarea.value = content + textarea.readOnly = "readOnly" + document.body.appendChild(textarea) + textarea.select() // 选择对象 + textarea.setSelectionRange(0, content.length) //核心 + let result = document.execCommand("copy") // 执行浏览器复制命令 + textarea.remove() + return result + +} \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..9254c64 --- /dev/null +++ b/main.js @@ -0,0 +1,31 @@ +import App from './App' + +// #ifndef VUE3 +import Vue from 'vue'; +import { router, RouterMount } from './router'; +import store from './store'; +import uView from "uview-ui"; +Vue.use(uView); +Vue.use(router) +Vue.config.productionTip = false +Vue.prototype.$store = store +App.mpType = 'app' +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + // #ifdef H5 + RouterMount(app,router,'#app') + // #endif +// #ifdef VUE3 +import { + createSSRApp +} from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..79226c1 --- /dev/null +++ b/manifest.json @@ -0,0 +1,78 @@ +{ + "name" : "medical", + "appid" : "__UNI__F02BFB1", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2", + "h5" : { + "router" : { + "mode" : "history" + }, + "title" : "痛风" + } +} diff --git a/node_modules/uni-read-pages/README.md b/node_modules/uni-read-pages/README.md new file mode 100644 index 0000000..9552873 --- /dev/null +++ b/node_modules/uni-read-pages/README.md @@ -0,0 +1,108 @@ +# uni-read-pages + +![coverage](https://img.shields.io/badge/coverage%20-98%25-green) ![npm](https://img.shields.io/badge/npm%20-v2.6.11-blue) ![license](https://img.shields.io/badge/license-MIT-red) ![size](https://img.shields.io/badge/size-1.48%20kb-yellowgreen) + +通过 [vue.config.js](https://cli.vuejs.org/zh/config/) 配合此库,可以随心所欲的读取 `pages.json` 下的所有配置 + +## 安装 + +您可以使用 `Yarn` 或 `npm` 安装该软件包(选择一个): + +##### Yarn + +```sh +yarn add uni-read-pages +``` +##### npm + +```sh +npm install uni-read-pages +``` +## 开始 +配置 `vue.config.js` 通过 `webpack` 注入全局变量 [查看文档](https://www.webpackjs.com/plugins/define-plugin/) + +#### 配置 `vue.config.js` +```js +//vue.config.js +const TransformPages = require('uni-read-pages') +const tfPages = new TransformPages() +module.exports = { + configureWebpack: { + plugins: [ + new tfPages.webpack.DefinePlugin({ + ROUTES: JSON.stringify(tfPages.routes) + }) + ] + } +} +``` +借助`webpack.DefinePlugin` 轻松注入全局变量。`ROUTES` 及可全局使用 + +#### 使用 +```js +// xxx.vue + +``` +## API +#### options +```js +//默认值 +const CONFIG={ + cli:false, //当前是否为脚手架初始化的项目 + includes:['path','aliasPath','name'] //需要获取包涵的字段 +} +``` + +#### Instance method + +* **getPagesRoutes** + * 通过读取 `pages.json` 文件 生成直接可用的routes + +* **parsePages(pageCallback, subPageCallback)** + * 单条page对象解析 + +* **resolvePath(dir)** + * 解析绝对路径 + +#### Instance attr + +* **CONFIG** + * 当前配置项 + +* **webpack** + * 当前工程下需要用到 `webpack` + +* **uniPagesJSON** + * 当前 `uni-app` 内置对象,可以通过此属性调用一些内置方法 + +* **routes** + * 通过 **includes** 解析后得到的路由表 **可直接使用** + +#### getter + +* **pagesJson** + * 获取所有 `pages.json` 下的内容 返回 `json` + + +#### uniPagesJSON method + +* getMainEntry() +* getNVueMainEntry() +* parsePages (pagesJson, pageCallback, subPageCallback) +* parseEntry (pagesJson) +* getPagesJson() +* parsePagesJson (content, loader) + +#### uniPagesJSON attr +* pagesJsonJsFileName //默认值 pages.js \ No newline at end of file diff --git a/node_modules/uni-read-pages/index.js b/node_modules/uni-read-pages/index.js new file mode 100644 index 0000000..a938961 --- /dev/null +++ b/node_modules/uni-read-pages/index.js @@ -0,0 +1,83 @@ +const path = require('path') +const CONFIG = { + includes: ['path', 'aliasPath', 'name'] +} +const rootPath = path.resolve(process.cwd(), 'node_modules'); + +/** 解析绝对路径 + * @param {Object} dir + */ +function resolvePath(dir) { + return path.resolve(rootPath, dir); +} + +class TransformPages { + constructor(config) { + config = { + ...CONFIG, + ...config + }; + this.CONFIG = config; + this.webpack = require(resolvePath('webpack')); + this.uniPagesJSON = require(resolvePath('@dcloudio/uni-cli-shared/lib/pages.js')); + this.routes = this.getPagesRoutes().concat(this.getNotMpRoutes()); + } + /** + * 获取所有pages.json下的内容 返回json + */ + get pagesJson() { + return this.uniPagesJSON.getPagesJson(); + } + /** + * 通过读取pages.json文件 生成直接可用的routes + */ + getPagesRoutes(pages = this.pagesJson.pages, rootPath = null) { + const routes = []; + for (let i = 0; i < pages.length; i++) { + const item = pages[i]; + const route = {}; + for (let j = 0; j < this.CONFIG.includes.length; j++) { + const key = this.CONFIG.includes[j]; + let value = item[key]; + if (key === 'path') { + value = rootPath ? `/${rootPath}/${value}` : `/${value}` + } + if (key === 'aliasPath' && i == 0 && rootPath == null) { + route[key] = route[key] || '/' + } else if (value !== undefined) { + route[key] = value; + } + } + routes.push(route); + } + return routes; + } + /** + * 解析小程序分包路径 + */ + getNotMpRoutes() { + const { + subPackages + } = this.pagesJson; + let routes = []; + if (subPackages == null || subPackages.length == 0) { + return []; + } + for (let i = 0; i < subPackages.length; i++) { + const subPages = subPackages[i].pages; + const root = subPackages[i].root; + const subRoutes = this.getPagesRoutes(subPages, root); + routes = routes.concat(subRoutes) + } + return routes + } + /** + * 单条page对象解析 + * @param {Object} pageCallback + * @param {Object} subPageCallback + */ + parsePages(pageCallback, subPageCallback) { + this.uniPagesJSON.parsePages(this.pagesJson, pageCallback, subPageCallback) + } +} +module.exports = TransformPages \ No newline at end of file diff --git a/node_modules/uni-read-pages/package.json b/node_modules/uni-read-pages/package.json new file mode 100644 index 0000000..97a01b7 --- /dev/null +++ b/node_modules/uni-read-pages/package.json @@ -0,0 +1,51 @@ +{ + "_from": "uni-read-pages", + "_id": "uni-read-pages@1.0.5", + "_inBundle": false, + "_integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==", + "_location": "/uni-read-pages", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "uni-read-pages", + "name": "uni-read-pages", + "escapedName": "uni-read-pages", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/uni-read-pages/-/uni-read-pages-1.0.5.tgz", + "_shasum": "452c8dcaa8977bbaef600909be926c8d9704387c", + "_spec": "uni-read-pages", + "_where": "/Users/WebTmm/Desktop/medical/medical", + "author": "", + "bugs": { + "url": "https://github.com/SilurianYang/uni-read-pages/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "read `pages.json` file to generate the routes table", + "directories": { + "example": "examples" + }, + "homepage": "https://github.com/SilurianYang/uni-read-pages#readme", + "keywords": [], + "license": "ISC", + "main": "index.js", + "name": "uni-read-pages", + "repository": { + "type": "git", + "url": "git+https://github.com/SilurianYang/uni-read-pages.git" + }, + "scripts": { + "build": "webpack --progress --config webpack/webpack.prod.js", + "dev": "webpack --watch --progress --config webpack/webpack.dev.js", + "postinstall": "node -e \"console.log('\\x1b[91m','\\n\\n uni-simple-router 垫脚片,欢迎下载!\\n \\n 开源不易,需要鼓励。去给 uni-read-pages 项目 点个 star 吧 \\n\\n')\"" + }, + "version": "1.0.5" +} diff --git a/node_modules/uni-simple-router/.eslintignore b/node_modules/uni-simple-router/.eslintignore new file mode 100644 index 0000000..3661113 --- /dev/null +++ b/node_modules/uni-simple-router/.eslintignore @@ -0,0 +1,6 @@ +dist +/node_modules +/webpack +/src/global.d.ts +/test +/jest.config.js \ No newline at end of file diff --git a/node_modules/uni-simple-router/.eslintrc.js b/node_modules/uni-simple-router/.eslintrc.js new file mode 100644 index 0000000..e792a31 --- /dev/null +++ b/node_modules/uni-simple-router/.eslintrc.js @@ -0,0 +1,257 @@ +module.exports = { + root: true, + env: { + browser: true, + node: true, + es6: true + }, + globals: { + uni: true, + plus: true, + getCurrentPages: true, + getApp: true, + __uniConfig: true, + __uniRoutes: true, + $npm_package_name: true + }, + parser: '@typescript-eslint/parser', + extends: ['eslint:recommended'], + plugins: ['@typescript-eslint'], + rules: { + '@typescript-eslint/consistent-type-definitions': [ + 'error', + 'interface' + ], + 'accessor-pairs': 2, + 'arrow-spacing': [ + 2, + { + before: true, + after: true + } + ], + 'block-spacing': [2, 'always'], + 'brace-style': [ + 2, + '1tbs', + { + allowSingleLine: true + } + ], + camelcase: [ + 0, + { + properties: 'always' + } + ], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [ + 2, + { + before: false, + after: true + } + ], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + curly: [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + eqeqeq: ['error', 'always', {null: 'ignore'}], + 'generator-star-spacing': [ + 2, + { + before: true, + after: true + } + ], + 'handle-callback-err': [2, '^(err|error)$'], + indent: ['error', 4], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [ + 2, + { + beforeColon: false, + afterColon: true + } + ], + 'keyword-spacing': [ + 2, + { + before: true, + after: true + } + ], + 'new-cap': [ + 2, + { + newIsCap: true, + capIsNew: false + } + ], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [ + 2, + { + allowLoop: false, + allowSwitch: false + } + ], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [ + 2, + { + max: 1 + } + ], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [ + 2, + { + defaultAssignment: false + } + ], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [ + 2, + { + vars: 'all', + args: 'none' + } + ], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [ + 2, + { + initialized: 'never' + } + ], + 'operator-linebreak': [ + 2, + 'after', + { + overrides: { + '?': 'before', + ':': 'before' + } + } + ], + 'padded-blocks': [2, 'never'], + quotes: [ + 2, + 'single', + { + avoidEscape: true, + allowTemplateLiterals: true + } + ], + semi: 'off', + 'semi-spacing': [ + 2, + { + before: false, + after: true + } + ], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [ + 2, + { + words: true, + nonwords: false + } + ], + 'spaced-comment': [ + 2, + 'always', + { + markers: [ + 'global', + 'globals', + 'eslint', + 'eslint-disable', + '*package', + '!', + ',' + ] + } + ], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + yoda: [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': 'off', + 'array-bracket-spacing': [2, 'never'] + } +}; diff --git a/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/bug_report.md b/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..ac848ad --- /dev/null +++ b/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: 报告问题(Bug report) +about: 详细描述你遇到的问题并寻求社区帮助 +title: '' +labels: '' +assignees: '' + +--- + +**问题描述** +[问题描述:尽可能简洁清晰地把问题描述清楚] + +**复现步骤** +[复现问题的步骤] +1. 启动 '...' +2. 点击 '....' +3. 查看 + +[或者可以直接贴源代码] + +**预期结果** +[使用简洁清晰的语言描述你希望生效的预期结果] + +**实际结果** +[这里请贴上你的报错截图或文字] + + +**系统信息:** + - 发行平台: [如 微信小程序、H5平台、5+ App等] + - 操作系统 [如 iOS 12.1.2、Android 7.0] + - HBuilderX版本 [如使用HBuilderX,则需提供 HBuilderX 版本号] + - 项目创建方法 [如使用Vue-cli创建/HBuilderX] + - 设备信息 [如 iPhone8 Plus] + - uni-simple-router版本 [如 v1.5.4] + + +**补充信息** +[可选] +[根据你的分析,出现这个问题的原因可能在哪里?] diff --git a/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/feature_request.md b/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..6559ac3 --- /dev/null +++ b/node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- +name: 建议新功能(Feature Request) +about: 对 uni-simple-router 提出改善建议 +title: '' +labels: '' +assignees: '' + +--- + +**新功能描述** +简洁描述你希望补充完善的增强功能 + +**现状及问题** +[当前现状及由此导致的不便] + +**尝试方案** +[如果你有尝试绕开或其它解决方案,在这里描述你的建议方案] + +**补充信息** +[其它你认为有参考价值的信息] + diff --git a/node_modules/uni-simple-router/CODE_OF_CONDUCT.md b/node_modules/uni-simple-router/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d8f066b --- /dev/null +++ b/node_modules/uni-simple-router/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at 1606726660@qq.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/node_modules/uni-simple-router/LICENSE b/node_modules/uni-simple-router/LICENSE new file mode 100644 index 0000000..7eddf4c --- /dev/null +++ b/node_modules/uni-simple-router/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 hhyang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/uni-simple-router/README.md b/node_modules/uni-simple-router/README.md new file mode 100644 index 0000000..1dbb5d8 --- /dev/null +++ b/node_modules/uni-simple-router/README.md @@ -0,0 +1,49 @@ +# uni-simple-router + +> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造 + +## 介绍 + +`uni-simple-router` 是专为 [uni-app](https://uniapp.dcloud.io/) 打造的路由器。它与 [uni-app](https://uniapp.dcloud.io/) 核心深度集成,使使用 [uni-app](https://uniapp.dcloud.io/) 轻松构建单页应用程序变得轻而易举。功能包括: + +* `H5端` 能完全使用 `vue-router` 进行开发。 + +* 模块化,基于组件的路由器配置。 + +* 路由参数,查询,通配符。 + +* `H5端` 查看由 `uni-simple-router` 过渡系统提供动力的过渡效果。 + +* 更细粒度的导航控制。 + +* `H端`自动控制活动的CSS类链接。 + +* 通配小程序端、APP端、H5端。 + + +开始使用 [查看文档](http://hhyang.cn),或 [使用示例](https://github.com/SilurianYang/uni-simple-router/tree/master/examples)(请参见下面的示例)。 + +## 问题 +在提交问题的之前,请确保阅读 [“问题报告清单”](https://github.com/SilurianYang/uni-simple-router/issues/new?assignees=&labels=&template=bug_report.md&title=) 。不符合准则的问题可能会立即被解决。 + +## 贡献 +提出拉取请求之前,请务必先阅读 [查看文档](http://hhyang.cn)(请参见下面的示例)。。 + +## 变更日志 +[发行说明](https://github.com/SilurianYang/uni-simple-router/releases) 中记录了每个发行版的详细信息更改。 + +## 特别感谢 + +特别感谢 [markrgba](https://github.com/markrgba) 一直以来对文档和相关测试的维护。 + +## 技术交流 + +uni-app  插件 + + +## 成品预览 + +
+

uni-simple-router@2.0+ts+uni-app

+ +
\ No newline at end of file diff --git a/node_modules/uni-simple-router/RFC.md b/node_modules/uni-simple-router/RFC.md new file mode 100644 index 0000000..d96f6e8 --- /dev/null +++ b/node_modules/uni-simple-router/RFC.md @@ -0,0 +1,38 @@ +```flow + +st=>start: 开始跳转 +e=>end: 跳转结束 +platform=>operation: 平台选择 +H5=>condition: H5 +APP=>condition: APP +applets=>condition: 小程序 +routerBeforeEach=>operation: routerBeforeEach +lock=>condition: 跳转加锁 + +runH5=>operation: H5 +runAPP=>parallel: APP +runapplets=>parallel: 小程序 + +beforeRouteLeave=>condition: beforeRouteLeave +beforeEach=>condition: beforeEach +beforeEnter=>condition: beforeEnter +afterEach=>operation: afterEach +runJump=>condition: 执行跳转成功或者失败 +stopJump=>operation: next(false) 停止跳转 +errorJump=>operation: 跳转失败 +routerErrorEach=>operation: routerErrorEach +routerAfterEach=>operation: routerAfterEach + +st->platform(right)->applets(yes)->routerBeforeEach +applets(no)->APP(yes)->routerBeforeEach +APP(no)->H5(yes)->routerBeforeEach +routerBeforeEach->lock(yes)->runAPP(path1)->runapplets(path1)->beforeRouteLeave +lock(no)->runH5->beforeRouteLeave(no)->stopJump->routerErrorEach +beforeRouteLeave(yes)->beforeEach(no)->stopJump->routerErrorEach +beforeEach(yes)->beforeEnter(no)->stopJump->routerErrorEach +beforeEnter(yes)->runJump(no)->errorJump->routerErrorEach +runJump(yes)->afterEach->routerAfterEach +routerAfterEach->e +routerErrorEach->e + +``` \ No newline at end of file diff --git a/node_modules/uni-simple-router/api-extractor.json b/node_modules/uni-simple-router/api-extractor.json new file mode 100644 index 0000000..5458aab --- /dev/null +++ b/node_modules/uni-simple-router/api-extractor.json @@ -0,0 +1,50 @@ +// this the shared base config for all packages. +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + + "mainEntryPointFilePath": "./dist/src/index.d.ts", + + "apiReport": { + "enabled": true, + "reportFolder": "./temp/" + }, + + "docModel": { + "enabled": true + }, + + "dtsRollup": { + "enabled": true, + "untrimmedFilePath": "./dist/.d.ts" + }, + + "tsdocMetadata": { + "enabled": false + }, + + "messages": { + "compilerMessageReporting": { + "default": { + "logLevel": "warning" + } + }, + + "extractorMessageReporting": { + "default": { + "logLevel": "warning", + "addToApiReportFile": true + }, + + "ae-missing-release-tag": { + "logLevel": "none" + } + }, + + "tsdocMessageReporting": { + "default": { + "logLevel": "warning" + } + } + } + } + \ No newline at end of file diff --git a/node_modules/uni-simple-router/dist/link.vue b/node_modules/uni-simple-router/dist/link.vue new file mode 100644 index 0000000..873f412 --- /dev/null +++ b/node_modules/uni-simple-router/dist/link.vue @@ -0,0 +1,79 @@ + + + diff --git a/node_modules/uni-simple-router/dist/uni-simple-router.d.ts b/node_modules/uni-simple-router/dist/uni-simple-router.d.ts new file mode 100644 index 0000000..a5769eb --- /dev/null +++ b/node_modules/uni-simple-router/dist/uni-simple-router.d.ts @@ -0,0 +1,312 @@ + +export declare interface AppConfig { + registerLoadingPage?: boolean; + loadingPageStyle?: () => object; + loadingPageHook?: (view: any) => void; + launchedHook?: () => void; + animation?: startAnimationRule; +} + +export declare interface appletConfig { + animationDuration?: number; +} + +export declare type backTypeRule = 'backbutton' | 'navigateBack'; + +export declare function createRouter(params: InstantiateConfig): Router; + +export declare interface debuggerArrayConfig { + error?: boolean; + warn?: boolean; + log?: boolean; +} + +export declare type debuggerConfig = boolean | debuggerArrayConfig; + +export declare interface endAnimationRule { + animationType?: endAnimationType; + animationDuration?: number; +} + +export declare type endAnimationType = 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom' | 'pop-out' | 'fade-out' | 'zoom-in' | 'zoom-fade-in' | 'none'; + +export declare type guardHookRule = (to: totalNextRoute, from: totalNextRoute, next: (rule?: navtoRule | false) => void) => void; + +export declare interface H5Config { + paramsToQuery?: boolean; + vueRouterDev?: boolean; + vueNext?: boolean; + mode?: string; + base?: string; + linkActiveClass?: string; + linkExactActiveClass?: string; + scrollBehavior?: Function; + fallback?: boolean; +} + +export declare interface h5NextRule { + fullPath?: string | undefined; + hash?: string | undefined; + matched?: Array; + meta?: object; + name?: undefined | string; + type?: undefined | string; +} + +export declare type hookListRule = Array<(router: Router, to: totalNextRoute, from: totalNextRoute, toRoute: RoutesRule, next: Function) => void>; + +export declare interface hookObjectRule { + options: Array; + hook: Function; +} + +export declare enum hookToggle { + 'beforeHooks' = "beforeEach", + 'afterHooks' = "afterEach", + 'enterHooks' = "beforeEnter" +} + +export declare interface InstantiateConfig { + [key: string]: any; + keepUniOriginNav?: boolean; + platform: platformRule; + h5?: H5Config; + APP?: AppConfig; + applet?: appletConfig; + debugger?: debuggerConfig; + routerBeforeEach?: (to: navtoRule, from: navtoRule, next: (rule?: navtoRule | false) => void) => void; + routerAfterEach?: (to: navtoRule, from: navtoRule, next?: Function) => void; + routerErrorEach?: (error: navErrorRule, router: Router) => void; + resolveQuery?: (jsonQuery: objectAny) => objectAny; + parseQuery?: (jsonQuery: objectAny) => objectAny; + detectBeforeLock?: (router: Router, to: string | number | totalNextRoute | navRoute, navType: NAVTYPE) => void; + routes: RoutesRule[]; +} + +export declare interface LifeCycleConfig { + beforeHooks: hookListRule; + afterHooks: hookListRule; + routerBeforeHooks: hookListRule; + routerAfterHooks: hookListRule; + routerErrorHooks: Array<(error: navErrorRule, router: Router) => void>; +} + +export declare interface navErrorRule { + type: navRuleStatus; + msg: string; + to?: totalNextRoute; + from?: totalNextRoute; + nextTo?: any; + [propName: string]: any; +} + +export declare type navMethodRule = Promise; + +export declare interface navRoute extends h5NextRule, navtoRule { +} + +export declare type navRuleStatus = 0 | 1 | 2 | 3; + +export declare interface navtoRule { + NAVTYPE?: NAVTYPE; + path?: string; + name?: string | undefined; + query?: objectAny; + params?: objectAny; + animationType?: startAnimationType | endAnimationType; + animationDuration?: number; + events?: objectAny; + success?: Function; + fail?: Function; + complete?: Function; +} + +export declare type NAVTYPE = 'push' | 'replace' | 'replaceAll' | 'pushTab' | 'back'; + +export declare enum navtypeToggle { + 'push' = "navigateTo", + 'replace' = "redirectTo", + 'replaceAll' = "reLaunch", + 'pushTab' = "switchTab", + 'back' = "navigateBack" +} + +export declare type objectAny = { + [propName: string]: any; +}; + +export declare interface originMixins extends uniNavApiRule { + BACKTYPE: '' | backTypeRule; +} + +export declare type pageTypeRule = 'app' | 'page' | 'component'; + +export declare type platformRule = 'h5' | 'app-plus' | 'app-lets' | 'mp-weixin' | 'mp-baidu' | 'mp-alipay' | 'mp-toutiao' | 'mp-qq' | 'mp-360'; + +export declare type PromiseResolve = (value?: void | PromiseLike | undefined) => void; + +export declare type proxyDepsRule = { + resetIndex: Array; + hooks: { + [key: number]: { + proxyHook: () => void; + callHook: (enterPath: string) => void; + resetHook: () => void; + }; + }; + options: { + [key: number]: Array; + }; +}; + +export declare type proxyHookName = 'beforeHooks' | 'afterHooks'; + +export declare type reloadNavRule = totalNextRoute | false | undefined | string; + +export declare type reNavMethodRule = 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab'; + +export declare type reNotNavMethodRule = 'navigateBack'; + +export declare enum rewriteMethodToggle { + 'navigateTo' = "push", + 'navigate' = "push", + 'redirectTo' = "replace", + 'reLaunch' = "replaceAll", + 'switchTab' = "pushTab", + 'navigateBack' = "back" +} + +export declare interface Router { + [key: string]: any; + readonly lifeCycle: LifeCycleConfig; + readonly options: InstantiateConfig; + $lockStatus: boolean; + $route: object | null; + enterPath: string; + Vue: any; + appMain: { + NAVTYPE: reNavMethodRule | reNotNavMethodRule; + path: string; + } | {}; + proxyHookDeps: proxyDepsRule; + routesMap: routesMapRule | {}; + mount: Array<{ + app: any; + el: string; + }>; + install(Vue: any): void; + push(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void; + replace(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void; + replaceAll(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void; + pushTab(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void; + back(level: number | undefined, origin?: uniBackRule | uniBackApiRule): void; + forceGuardEach(navType: NAVTYPE | undefined, forceNav: boolean): void; + beforeEach(userGuard: guardHookRule): void; + afterEach(userGuard: (to: totalNextRoute, from: totalNextRoute) => void): void; +} + +export declare function RouterMount(Vim: any, router: Router, el?: string | undefined): void | never; + +export declare interface routeRule { + name: string | undefined; + meta: objectAny; + path: string; + query: objectAny; + params: objectAny; + fullPath: string; + NAVTYPE: NAVTYPE | ''; + BACKTYPE?: backTypeRule | ''; + [propName: string]: any; +} + +export declare type routesMapKeysRule = 'finallyPathList' | 'finallyPathMap' | 'aliasPathMap' | 'pathMap' | 'nameMap' | 'vueRouteMap'; + +export declare interface routesMapRule { + [key: string]: any; + finallyPathList: Array; + finallyPathMap: RoutesRule; + aliasPathMap: RoutesRule; + pathMap: RoutesRule; + nameMap: RoutesRule; + vueRouteMap: objectAny; +} + +export declare interface RoutesRule { + path: string; + component?: object; + name?: string; + components?: object; + redirect?: string | Function; + props?: boolean | object | Function; + aliasPath?: string; + alias?: string | Array; + children?: Array; + beforeEnter?: guardHookRule; + meta?: any; + [propName: string]: any; +} + +export declare function runtimeQuit(title?: string | undefined): void; + +export declare interface startAnimationRule { + animationType?: startAnimationType; + animationDuration?: number; +} + +export declare type startAnimationType = 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom' | 'pop-in' | 'fade-in' | 'zoom-out' | 'zoom-fade-out' | 'none'; + +export declare interface totalNextRoute extends h5NextRule, navtoRule { + path: string; + delta?: number; + [propName: string]: any; +} + +export declare interface uniBackApiRule { + delta?: number; + animationDuration?: number; + animationType?: endAnimationType; +} + +export declare interface uniBackRule { + from: backTypeRule; +} + +export declare interface uniNavApiRule { + url: string; + openType?: 'appLaunch'; + query?: objectAny; + path?: string; + delta?: number; + detail?: { + [propName: string]: any; + }; + animationType?: startAnimationType; + animationDuration?: number; + events?: { + [propName: string]: any; + }; + success?: Function; + fail?: Function; + complete?: Function; + animation?: { + animationType?: startAnimationType; + animationDuration?: number; + }; +} + +export declare type vueHookNameRule = 'onLaunch' | 'onShow' | 'onHide' | 'onError' | 'onInit' | 'onLoad' | 'onReady' | 'onUnload' | 'onResize' | 'created' | 'beforeMount' | 'mounted' | 'beforeDestroy' | 'destroyed'; + +export declare type vueOptionRule = { + [propName in vueHookNameRule]: Array | undefined; +}; + +export { } + +// @ts-ignore +declare module 'vue/types/vue' { + interface Vue { + $Router: Router; + $Route: routeRule; + } +} + \ No newline at end of file diff --git a/node_modules/uni-simple-router/dist/uni-simple-router.js b/node_modules/uni-simple-router/dist/uni-simple-router.js new file mode 100644 index 0000000..7e25d3c --- /dev/null +++ b/node_modules/uni-simple-router/dist/uni-simple-router.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Router=t():e.Router=t()}(self,(function(){return e={779:(e,t,r)=>{var o=r(173);e.exports=function e(t,r,n){return o(r)||(n=r||n,r=[]),n=n||{},t instanceof RegExp?function(e,t){var r=e.source.match(/\((?!\?)/g);if(r)for(var o=0;o{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},844:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0?t.vueEachArray[r](e,o,(function(){n&&n()})):t.myEachHook(e,o,(function(a){!1===a?n(!1):t.vueEachArray[r](e,o,(function(e){n(a)}))}),t.router,!0)}},t}(Array);t.MyArray=n,t.proxyEachHook=function(e,t){for(var r=["beforeHooks","afterHooks"],o=0;o0)return!1;window.location.reload()}),0)}else e.mount[0].app.$mount(),e.mount=[]}},814:function(e,t){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,r=1,o=arguments.length;r{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getEnterPath=void 0,t.getEnterPath=function(e,t){switch(t.options.platform){case"mp-alipay":case"mp-weixin":case"mp-toutiao":case"mp-qq":return e.$options.mpInstance.route;case"mp-baidu":return e.$options.mpInstance.is||e.$options.mpInstance.pageinstance.route}return e.$options.mpInstance.route}},282:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.proxyHookName=t.proxyHookDeps=t.lifeCycle=t.baseConfig=t.mpPlatformReg=void 0;var o=r(883);t.mpPlatformReg="(^mp-weixin$)|(^mp-baidu$)|(^mp-alipay$)|(^mp-toutiao$)|(^mp-qq$)|(^mp-360$)",t.baseConfig={h5:{paramsToQuery:!1,vueRouterDev:!1,vueNext:!1,mode:"hash",base:"/",linkActiveClass:"router-link-active",linkExactActiveClass:"router-link-exact-active",scrollBehavior:function(e,t,r){return{x:0,y:0}},fallback:!0},APP:{registerLoadingPage:!0,loadingPageStyle:function(){return JSON.parse('{"backgroundColor":"#FFF"}')},loadingPageHook:function(e){e.show()},launchedHook:function(){plus.navigator.closeSplashscreen()},animation:{}},applet:{animationDuration:300},platform:"h5",keepUniOriginNav:!1,debugger:!1,routerBeforeEach:function(e,t,r){r()},routerAfterEach:function(e,t){},routerErrorEach:function(e,t){t.$lockStatus=!1,o.err(e,t,!0)},detectBeforeLock:function(e,t,r){},routes:[{path:"/choose-location"},{path:"/open-location"},{path:"/preview-image"}]},t.lifeCycle={beforeHooks:[],afterHooks:[],routerBeforeHooks:[],routerAfterHooks:[],routerErrorHooks:[]},t.proxyHookDeps={resetIndex:[],hooks:{},options:{}},t.proxyHookName=["onLaunch","onShow","onHide","onError","onInit","onLoad","onReady","onUnload","onResize","created","beforeMount","mounted","beforeDestroy","destroyed"]},801:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createRouteMap=void 0;var o=r(883),n=r(789);t.createRouteMap=function(e,t){var r={finallyPathList:[],finallyPathMap:Object.create(null),aliasPathMap:Object.create(null),pathMap:Object.create(null),vueRouteMap:Object.create(null),nameMap:Object.create(null)};return t.forEach((function(t){var a=n.getRoutePath(t,e),i=a.finallyPath,u=a.aliasPath,l=a.path;if(null==l)throw new Error("请提供一个完整的路由对象,包括以绝对路径开始的 ‘path’ 字符串 "+JSON.stringify(t));if(i instanceof Array&&!e.options.h5.vueRouterDev&&"h5"===e.options.platform)throw new Error("非 vueRouterDev 模式下,route.alias 目前无法提供数组类型! "+JSON.stringify(t));var p=i,c=u;"h5"!==e.options.platform&&0!==p.indexOf("/")&&"*"!==l&&o.warn("当前路由对象下,route:"+JSON.stringify(t)+" 是否缺少了前缀 ‘/’",e,!0),r.finallyPathMap[p]||(r.finallyPathMap[p]=t,r.aliasPathMap[c]=t,r.pathMap[l]=t,r.finallyPathList.push(p),null!=t.name&&(r.nameMap[t.name]=t))})),r}},662:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.registerEachHooks=t.registerRouterHooks=t.registerHook=void 0;var o=r(366),n=r(169);function a(e,t){e[0]=t}t.registerHook=a,t.registerRouterHooks=function(e,t){return a(e.routerBeforeHooks,(function(e,r,o){t.routerBeforeEach(e,r,o)})),a(e.routerAfterHooks,(function(e,r){t.routerAfterEach(e,r)})),a(e.routerErrorHooks,(function(e,r){t.routerErrorEach(e,r)})),e},t.registerEachHooks=function(e,t,r){a(e.lifeCycle[t],(function(e,a,i,u,l){l?n.onTriggerEachHook(e,a,u,o.hookToggle[t],i):r(e,a,i)}))}},460:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0)return P}if(""!==u)return h(t);throw new Error(r+" 路径无法在路由表中找到!检查跳转路径及路由表")},t.getDataType=v,t.copyData=function(e){return JSON.parse(JSON.stringify(e))},t.getUniCachePage=function(e){var t=getCurrentPages();if(null==e)return t;if(0===t.length)return t;var r=t.reverse()[e];return null==r?[]:r},t.urlToJson=function(e){var t={},r=e.split("?"),o=r[0],n=r[1];if(null!=n)for(var a=0,i=n.split("&");a3},t.baseClone=y,t.deepClone=g,t.lockDetectWarn=function(e,t,r,o,n,a){if(void 0===n&&(n={}),"afterHooks"===a)o();else{var i=e.options.detectBeforeLock;i&&i(e,t,r),e.$lockStatus?e.options.routerErrorEach({type:2,msg:"当前页面正在处于跳转状态,请稍后再进行跳转....",NAVTYPE:r,uniActualData:n},e):o()}},t.assertParentChild=function(e,t){for(;null!=t.$parent;){var r=t.$parent.$mp;if(r.page&&r.page.is===e)return!0;t=t.$parent}try{if(t.$mp.page.is===e||t.$mp.page.route===e)return!0}catch(e){return!1}return!1},t.resolveAbsolutePath=function(e,t){var r=/^\/?([^\?\s]+)(\?.+)?$/,o=e.trim();if(!r.test(o))throw new Error("【"+e+"】 路径错误,请提供完整的路径(10001)。");var n=o.match(r);if(null==n)throw new Error("【"+e+"】 路径错误,请提供完整的路径(10002)。");var a=n[2]||"";if(/^\.\/[^\.]+/.test(o))return(t.currentRoute.path+e).replace(/[^\/]+\.\//,"");var i=n[1].replace(/\//g,"\\/").replace(/\.\./g,"[^\\/]+").replace(/\./g,"\\."),u=new RegExp("^\\/"+i+"$"),l=t.options.routes.filter((function(e){return u.test(e.path)}));if(1!==l.length)throw new Error("【"+e+"】 路径错误,尝试转成绝对路径失败,请手动转成绝对路径(10003)。");return l[0].path+a},t.deepDecodeQuery=function e(t){for(var r="[object Array]"===v(t)?[]:{},o=Object.keys(t),n=0;n{"use strict";function r(e,t,r,o){if(void 0===o&&(o=!1),!o){var n="[object Object]"===t.toString();if(!1===t)return!1;if(n&&!1===t[e])return!1}return console[e](r),!0}Object.defineProperty(t,"__esModule",{value:!0}),t.warnLock=t.log=t.warn=t.err=t.isLog=void 0,t.isLog=r,t.err=function(e,t,o){r("error",t.options.debugger,e,o)},t.warn=function(e,t,o){r("warn",t.options.debugger,e,o)},t.log=function(e,t,o){r("log",t.options.debugger,e,o)},t.warnLock=function(e){console.warn(e)}},607:function(e,t,r){"use strict";var o=this&&this.__createBinding||(Object.create?function(e,t,r,o){void 0===o&&(o=r),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,o){void 0===o&&(o=r),e[o]=t[r]}),n=this&&this.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||o(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.createRouter=t.RouterMount=t.runtimeQuit=void 0,n(r(366),t),n(r(309),t);var a=r(814);Object.defineProperty(t,"runtimeQuit",{enumerable:!0,get:function(){return a.runtimeQuit}});var i=r(963);Object.defineProperty(t,"RouterMount",{enumerable:!0,get:function(){return i.RouterMount}}),Object.defineProperty(t,"createRouter",{enumerable:!0,get:function(){return i.createRouter}})},366:(e,t)=>{"use strict";var r,o,n;Object.defineProperty(t,"__esModule",{value:!0}),t.rewriteMethodToggle=t.navtypeToggle=t.hookToggle=void 0,(n=t.hookToggle||(t.hookToggle={})).beforeHooks="beforeEach",n.afterHooks="afterEach",n.enterHooks="beforeEnter",(o=t.navtypeToggle||(t.navtypeToggle={})).push="navigateTo",o.replace="redirectTo",o.replaceAll="reLaunch",o.pushTab="switchTab",o.back="navigateBack",(r=t.rewriteMethodToggle||(t.rewriteMethodToggle={})).navigateTo="push",r.navigate="push",r.redirectTo="replace",r.reLaunch="replaceAll",r.switchTab="pushTab",r.navigateBack="back"},309:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},169:function(e,t,r){"use strict";var o=this&&this.__rest||function(e,t){var r={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n0){var u=void 0;switch("h5"===e.options.platform?u=i.$options.beforeRouteLeave:null!=i.$vm&&(u=i.$vm.$options.beforeRouteLeave),n.getDataType(u)){case"[object Array]":a=(a=u[0]).bind(i);break;case"[object Function]":a=u.bind(i.$vm)}}return p(a,t,r,e,o)}function p(e,t,r,o,n,a){void 0===a&&(a=!0),null!=e&&e instanceof Function?!0===a?e(t,r,n,o,!1):(e(t,r,(function(){}),o,!1),n()):n()}function c(e,t,r,o,a,i){var u=n.forMatNextToFrom(e,t,r),l=u.matTo,p=u.matFrom;"h5"===e.options.platform?s(a,0,i,e,l,p,o):s(a.slice(0,4),0,(function(){i((function(){s(a.slice(4),0,n.voidFun,e,l,p,o)}))}),e,l,p,o)}function s(e,r,i,l,p,c,f){var h=n.routesForMapRoute(l,p.path,["finallyPathMap","pathMap"]);if(e.length-1{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.resetPageHook=t.resetAndCallPageHook=t.proxyPageHook=t.createFullPath=t.createToFrom=void 0;var o=r(282),n=r(789),a=r(890),i=r(99);function u(e){for(var t=e.proxyHookDeps,r=0,o=Object.entries(t.hooks);r{[propName: string]: any;}",t):e[r]=u}else{if(!n.assertDeepObject(o))return e;var l=JSON.stringify(o);e[r]={query:l}}return e},t.parseQuery=function(e,t){var r=t.options.parseQuery;if(r)e=r(n.copyData(e)),"[object Object]"!==n.getDataType(e)&&i.warn("请按格式返回参数: parseQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}",t);else if(Reflect.get(e,"query")){var o=Reflect.get(e,"query");if("string"==typeof o)try{o=JSON.parse(o)}catch(e){i.warn("尝试解析深度对象失败,按原样输出。"+e,t)}if("object"==typeof o)return n.deepDecodeQuery(o)}return e},t.stringifyQuery=function(e){var t=e?Object.keys(e).map((function(t){var r=e[t];if(void 0===r)return"";if(null===r)return c(t);if(Array.isArray(r)){var o=[];return r.forEach((function(e){void 0!==e&&(null===e?o.push(c(t)):o.push(c(t)+"="+c(e)))})),o.join("&")}return c(t)+"="+c(r)})).filter((function(e){return e.length>0})).join("&"):null;return t?"?"+t:""}},314:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.rewriteMethod=void 0;var o=r(366),n=r(789),a=r(883),i=r(809),u=["navigateTo","redirectTo","reLaunch","switchTab","navigateBack"];t.rewriteMethod=function(e){!1===e.options.keepUniOriginNav&&u.forEach((function(t){var r=uni[t];uni[t]=function(u,l,p,c){void 0===l&&(l=!1),l?i.uniOriginJump(e,r,t,u,p,c):("app-plus"===e.options.platform&&0===Object.keys(e.appMain).length&&(e.appMain={NAVTYPE:t,path:u.url}),function(e,t,r){if("app-plus"===r.options.platform){var i=null;e&&(i=e.openType),null!=i&&"appLaunch"===i&&(t="reLaunch")}if("reLaunch"===t&&'{"url":"/"}'===JSON.stringify(e)&&(a.warn("uni-app 原生方法:reLaunch({url:'/'}) 默认被重写啦!你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch({url:'/?xxx=xxx'})",r,!0),t="navigateBack",e={from:"backbutton"}),"navigateBack"===t){var u=1;null==e&&(e={delta:1}),"[object Number]"===n.getDataType(e.delta)&&(u=e.delta),r.back(u,e)}else{var l=o.rewriteMethodToggle[t],p=e.url;if(!p.startsWith("/")){var c=n.resolveAbsolutePath(p,r);p=c,e.url=c}if("switchTab"===t){var s=n.routesForMapRoute(r,p,["pathMap","finallyPathList"]),f=n.getRoutePath(s,r).finallyPath;if("[object Array]"===n.getDataType(f)&&a.warn("uni-app 原生方法跳转路径为:"+p+"。此路为是tab页面时,不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!",r,!0),"*"===f&&a.warn("uni-app 原生方法跳转路径为:"+p+"。在路由表中找不到相关路由表!当然你可以通过通配符*解决!",r,!0),"h5"===r.options.platform){var h=e.success;e.success=function(){for(var t=[],r=0;r0&&Reflect.has(t,"index")){var r=n.getUniCachePage(0);if(0===Object.keys(r).length)return!1;var o=r,a=o.$options.onTabItemTap;if(a)for(var i=0;i0&&n[n.length-1])||6!==a[0]&&2!==a[0])){i=0;continue}if(3===a[0]&&(!n||a[1]>n[0]&&a[1] 提交信息不能为空! \n \n" + fi + done + ;; + + # 推送到服务端 + "push") + read -p "请输入提交的分支(不输入默认主分支 [master] ):" branch + printf "\n\n -------------- 正在推送github,请稍后.... --------------- \n\n" + if [[ "$branch" == "" ]]; then + git push + else + eval "git push origin ${branch}" + fi + printf "\n -------------- 推送github完成 --------------- \n\n" + ;; + + # 拉取最新代码 + "pull") + printf "\n\n -------------- 正在拉取,请稍后.... --------------- \n\n" + git pull + printf "\n -------------- 正在拉取完成 --------------- \n\n" + ;; + + # 切换分支操作 + "branch") + read -p "请输入添加更多指令 【分支】 :" branchs + if [[ "$branchs" == "" ]]; then + printf "\n分支列表如下:\n\n" + git branch + else + eval "git branch ${branchs}" + fi + printf "\n -------------- 分支操作完毕 --------------- \n\n" + ;; + # + "checkout") + read -p "请输入添加更多指令 【默认切换到master】 :" out + if [[ "$out" == "" ]]; then + git checkout master + else + eval "git checkout ${out}" + fi + printf "\n -------------- 执行完毕 --------------- \n\n" + ;; + # 自定义指令 + *) + while read -p "请输入自定义命令 【输入:q退出】:" code; do + if [[ "$code" == ":q" ]];then + printf "\n" + break + fi + printf "\n\n -------------- 正在执行,请稍后.... --------------- \n\n" + eval "$code" + printf "\n -------------- 执行完毕 --------------- \n\n" + done + esac +done diff --git a/node_modules/uni-simple-router/jest.config.js b/node_modules/uni-simple-router/jest.config.js new file mode 100644 index 0000000..6bad1fa --- /dev/null +++ b/node_modules/uni-simple-router/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + moduleDirectories:['node_modules','src'] +}; \ No newline at end of file diff --git a/node_modules/uni-simple-router/package.json b/node_modules/uni-simple-router/package.json new file mode 100644 index 0000000..c8f89cc --- /dev/null +++ b/node_modules/uni-simple-router/package.json @@ -0,0 +1,62 @@ +{ + "_from": "uni-simple-router", + "_id": "uni-simple-router@2.0.7", + "_inBundle": false, + "_integrity": "sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA==", + "_location": "/uni-simple-router", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "uni-simple-router", + "name": "uni-simple-router", + "escapedName": "uni-simple-router", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/uni-simple-router/-/uni-simple-router-2.0.7.tgz", + "_shasum": "04e0b5be6cd733a1ecb9d35a3dbe82f27f48204e", + "_spec": "uni-simple-router", + "_where": "/Users/WebTmm/Desktop/medical/medical", + "author": { + "name": "hhyang" + }, + "bugs": { + "url": "https://github.com/SilurianYang/uni-simple-router/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造", + "homepage": "https://github.com/SilurianYang/uni-simple-router#readme", + "keywords": [ + "router", + "uni-app-router", + "interceptor", + "uni-app", + "uniapp" + ], + "license": "MIT", + "main": "dist/uni-simple-router.js", + "name": "uni-simple-router", + "repository": { + "type": "git", + "url": "git+https://github.com/SilurianYang/uni-simple-router.git" + }, + "scripts": { + "build": "node ./publish/build.js", + "dev": "webpack --watch --progress --config webpack/webpack.dev.js", + "dist": "webpack --progress --config webpack/webpack.prod.js", + "dist:dts": "api-extractor run --local --verbose", + "lint": "eslint --ext .js,.ts src", + "lintFix": "eslint --ext .js,.ts src --fix", + "publish": "node ./publish/index.js", + "test": "jest test/query-toggle.spec.ts" + }, + "types": "dist/uni-simple-router.d.ts", + "version": "2.0.7" +} diff --git a/node_modules/uni-simple-router/progress.md b/node_modules/uni-simple-router/progress.md new file mode 100644 index 0000000..97f7684 --- /dev/null +++ b/node_modules/uni-simple-router/progress.md @@ -0,0 +1,16 @@ +## Fixes bug +* `小程序` 端 `onLoad`、`onShow` 执行不标准的BUG。(#206,#224,#291) +* `小程序` 端 启动页必须写 `onLoad` 才会执行的BUG。 +* `APP` 端 tab 拦截后无法自动还原选中区域现在已修复。 +* H5端设置 `aliasPath` 后,无法使用 `aliasPath` 跨端跳转 (#302) +* 重写代理生命周期逻辑、保证执行各端执行顺序 (#312) + +## Revise +* 参数可以直接传递 `null`。但是需要注意:**在非深度对象传参的情况下,小程序会将 `null` 解析为字符串`undefined`** +* 多端情况下自定义启动参数不仅限制于 `query` 传递深度参数,任何组合都可以 (#307,#301) +* 去除 `keyword` 白名单字段 +* 调整小程序启动页面生命周期的执行,让在小程序下的生命周期能更贴近App、H5 +* `routerErrorEach` 新增回调参数、包括:`NAVTYPE`、`uniActualData`、`level` + +## Known Issues +* `APP` 端启动页为tab时,拦截到其他页面后底部tabbar 还依然存在,请避免把原生 `tabbar` 页设置成启动页。你可以在 `beforeEach` 中使用 next 到tabbar页效果一致 \ No newline at end of file diff --git a/node_modules/uni-simple-router/src/H5/buildRouter.ts b/node_modules/uni-simple-router/src/H5/buildRouter.ts new file mode 100644 index 0000000..b733a2f --- /dev/null +++ b/node_modules/uni-simple-router/src/H5/buildRouter.ts @@ -0,0 +1,76 @@ +import {RoutesRule, Router, routesMapRule, totalNextRoute, hookToggle, navtoRule} from '../options/base'; +import {H5Config} from '../options/config'; +import {warn} from '../helpers/warn' +import {getDataType, getRoutePath} from '../helpers/utils' +import { onTriggerEachHook } from '../public/hooks'; + +export function buildVueRoutes(router: Router, vueRouteMap:RoutesRule):RoutesRule { + const {pathMap, finallyPathList} = (router.routesMap as routesMapRule); + const vueRoutePathList:Array = Object.keys(vueRouteMap); + for (let i = 0; i < vueRoutePathList.length; i++) { + const path = vueRoutePathList[i]; + const myRoute:RoutesRule = pathMap[path]; + const vueRoute:RoutesRule = vueRouteMap[path]; + if (!myRoute) { + warn(`${path} 路由地址在路由表中未找到,确定是否传递漏啦`, router, true); + } else { + const {finallyPath} = getRoutePath(myRoute, router); + if (finallyPath instanceof Array) { + throw new Error(`非 vueRouterDev 模式下,alias、aliasPath、path 无法提供数组类型! ${JSON.stringify(myRoute)}`); + } + if (myRoute.name != null) { + vueRoute.name = myRoute.name; + } + const vuePath = vueRoute['path']; + const vueAlias = vueRoute['alias']; + delete vueRoute['alias']; + vueRoute['path'] = (finallyPath as string); + if (vuePath === '/' && vueAlias != null) { + vueRoute['alias'] = vueAlias; + vueRoute['path'] = vuePath; + } + const beforeEnter = myRoute.beforeEnter; + if (beforeEnter) { + vueRoute['beforeEnter'] = function( + to:totalNextRoute, + from: totalNextRoute, + next:(rule?: navtoRule|false)=>void, + ):void{ + onTriggerEachHook(to, from, router, hookToggle['enterHooks'], next) + }; + } + } + } + if (finallyPathList.includes('*')) { + vueRouteMap['*'] = pathMap['*'] + } + return vueRouteMap +} + +export function buildVueRouter(router:Router, vueRouter:any, vueRouteMap:RoutesRule|RoutesRule[]) :void |never { + let routes:RoutesRule[] = []; + if (getDataType(vueRouteMap) === '[object Array]') { + routes = (vueRouteMap as RoutesRule[]); + } else { + routes = Object.values(vueRouteMap); + } + const {scrollBehavior, fallback} = router.options.h5 as H5Config; + const oldScrollBehavior = vueRouter.options.scrollBehavior; + vueRouter.options.scrollBehavior = function proxyScrollBehavior( + to:totalNextRoute, + from:totalNextRoute, + savedPosition:any + ) { + oldScrollBehavior && oldScrollBehavior(to, from, savedPosition); + return (scrollBehavior as Function)(to, from, savedPosition) + } + vueRouter.fallback = fallback; + // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465 + const newVueRouter:any = new vueRouter.constructor({ + ...router.options.h5, + base: vueRouter.options.base, + mode: vueRouter.options.mode, + routes + }); + vueRouter.matcher = newVueRouter.matcher; +} diff --git a/node_modules/uni-simple-router/src/H5/proxyHook.ts b/node_modules/uni-simple-router/src/H5/proxyHook.ts new file mode 100644 index 0000000..a1d6c29 --- /dev/null +++ b/node_modules/uni-simple-router/src/H5/proxyHook.ts @@ -0,0 +1,71 @@ +import {Router, proxyHookName, totalNextRoute, navtoRule} from '../options/base'; + +export class MyArray extends Array { + constructor( + private router:Router, + private vueEachArray:Array, + private myEachHook:Function, + private hookName:'beforeHooks'| 'afterHooks', + ) { + super(); + Object.setPrototypeOf(this, MyArray.prototype) + } + push(v:any):any { + this.vueEachArray.push(v); + const index = this.length; + this[this.length] = (to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void) => { + if (index > 0) { + this.vueEachArray[index](to, from, () => { + next && next() + }); + } else { + this.myEachHook(to, from, (nextTo?:navtoRule|false) => { + // Fixe https://github.com/SilurianYang/uni-simple-router/issues/241 2021年3月6日22:15:27 + // 目前不调用uni-app的守卫函数,因为会丢失页面栈信息 + if (nextTo === false) { + next(false); + } else { + this.vueEachArray[index](to, from, (uniNextTo?:navtoRule|false) => { + next(nextTo); + }) + } + }, this.router, true); + } + }; + } +} + +export function proxyEachHook(router:Router, vueRouter:any):void { + const hookList:Array<'beforeHooks'| 'afterHooks'> = ['beforeHooks', 'afterHooks']; + for (let i = 0; i < hookList.length; i++) { + const hookName = hookList[i]; + const myEachHook = router.lifeCycle[(hookName as proxyHookName)][0]; + if (myEachHook) { + const vueEachArray:Array = vueRouter[hookName]; + vueRouter[hookName] = new MyArray(router, vueEachArray, myEachHook, hookName); + } + } +} +export function proxyH5Mount(router:Router):void { + if (router.mount.length === 0) { + if (router.options.h5?.vueRouterDev) { + return + } + const uAgent = navigator.userAgent; + const isIos = !!uAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) + if (isIos) { + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/109 + setTimeout(() => { + const element = document.getElementsByTagName('uni-page'); + if (element.length > 0) { + return false + } + window.location.reload(); + }, 0); + } + } else { + const [{app}] = router.mount; + app.$mount(); + router.mount = []; + } +} diff --git a/node_modules/uni-simple-router/src/app/appPatch.ts b/node_modules/uni-simple-router/src/app/appPatch.ts new file mode 100644 index 0000000..c9b07ba --- /dev/null +++ b/node_modules/uni-simple-router/src/app/appPatch.ts @@ -0,0 +1,75 @@ +import { objectAny, Router, totalNextRoute } from '../options/base'; +import { AppConfig } from '../options/config'; + +let quitBefore:number|null = null; +let TABBAR:objectAny|null = null; + +export function registerLoddingPage( + router:Router, +):void{ + if (router.options.registerLoadingPage) { + const { loadingPageHook, loadingPageStyle } = router.options.APP as AppConfig; // 获取app所有配置 + const view = new plus.nativeObj.View('router-loadding', { + top: '0px', + left: '0px', + height: '100%', + width: '100%', + ...(loadingPageStyle as Function)() + }); + (loadingPageHook as Function)(view); // 触发等待页面生命周期 + } +} + +export function runtimeQuit( + title:string|undefined = '再按一次退出应用' +):void{ + const nowTime = +new Date(); + if (!quitBefore) { + quitBefore = nowTime; + uni.showToast({ + title, + icon: 'none', + position: 'bottom', + duration: 1000 + }); + setTimeout(() => { quitBefore = null }, 1000); + } else { + if (nowTime - quitBefore < 1000) { + plus.runtime.quit(); + } + } +} + +export function tabIndexSelect( + to:totalNextRoute, + from:totalNextRoute +):boolean { + if (!(__uniConfig.tabBar && Array.isArray(__uniConfig.tabBar.list))) { + return false + } + const tabBarList = __uniConfig.tabBar.list; + const routes:Array = []; + let activeIndex:number = 0; + for (let i = 0; i < tabBarList.length; i++) { + const route:totalNextRoute = tabBarList[i]; + if ('/' + route.pagePath === to.path || '/' + route.pagePath === from.path) { + if (route.pagePath === from.path) { + activeIndex = i; + } + routes.push(route); + } + if (routes.length === 2) { + break + } + } + if (routes.length !== 2) { + return false + } + if (TABBAR == null) { + TABBAR = uni.requireNativePlugin('uni-tabview') + } + (TABBAR as objectAny).switchSelect({ + index: activeIndex + }) + return true +} diff --git a/node_modules/uni-simple-router/src/applets/appletPatch.ts b/node_modules/uni-simple-router/src/applets/appletPatch.ts new file mode 100644 index 0000000..4f4f9ac --- /dev/null +++ b/node_modules/uni-simple-router/src/applets/appletPatch.ts @@ -0,0 +1,18 @@ +import { Router} from '../options/base'; + +export function getEnterPath( + vueVim:any, + router:Router, +) :string { + switch (router.options.platform) { + case 'mp-alipay': + case 'mp-weixin': + case 'mp-toutiao': + case 'mp-qq': + return vueVim.$options.mpInstance.route; + case 'mp-baidu': + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/251 + return vueVim.$options.mpInstance.is || vueVim.$options.mpInstance.pageinstance.route; + } + return vueVim.$options.mpInstance.route; // 这是暂时的 因为除了以上的小程序 其他没测试 先这样写 +} diff --git a/node_modules/uni-simple-router/src/component/link.vue b/node_modules/uni-simple-router/src/component/link.vue new file mode 100644 index 0000000..873f412 --- /dev/null +++ b/node_modules/uni-simple-router/src/component/link.vue @@ -0,0 +1,79 @@ + + + diff --git a/node_modules/uni-simple-router/src/global.d.ts b/node_modules/uni-simple-router/src/global.d.ts new file mode 100644 index 0000000..74a6427 --- /dev/null +++ b/node_modules/uni-simple-router/src/global.d.ts @@ -0,0 +1,7 @@ +declare var uni:any; +declare var plus:any; +declare var __uniConfig:any; +declare var __uniRoutes:any; +declare function getCurrentPages(isAll:boolean|undefined=false):any; +declare function getApp(args?:{allowDefault: true}):any; +declare var $npm_package_name:string; \ No newline at end of file diff --git a/node_modules/uni-simple-router/src/helpers/config.ts b/node_modules/uni-simple-router/src/helpers/config.ts new file mode 100644 index 0000000..1c376f0 --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/config.ts @@ -0,0 +1,78 @@ +import {err} from './warn' +import { InstantiateConfig, LifeCycleConfig} from '../options/config' +import { vueHookNameRule, proxyDepsRule } from '../options/base'; + +export const mpPlatformReg = '(^mp-weixin$)|(^mp-baidu$)|(^mp-alipay$)|(^mp-toutiao$)|(^mp-qq$)|(^mp-360$)' // 小程序下不能直接导出正则 需要重新组装成正则 不然bug一推 诡异 + +export const baseConfig:InstantiateConfig = { + h5: { + paramsToQuery: false, + vueRouterDev: false, + vueNext: false, + mode: 'hash', + base: '/', + linkActiveClass: 'router-link-active', + linkExactActiveClass: 'router-link-exact-active', + scrollBehavior: (to:any, from:any, savedPostion:Function) => ({ x: 0, y: 0 }), + fallback: true + }, + APP: { + registerLoadingPage: true, + loadingPageStyle: () => JSON.parse('{"backgroundColor":"#FFF"}'), + loadingPageHook: (view:any) => { view.show(); }, + launchedHook: () => { plus.navigator.closeSplashscreen(); }, + animation: {} + }, + applet: { + animationDuration: 300 + }, + platform: 'h5', + keepUniOriginNav: false, + debugger: false, + routerBeforeEach: (to, from, next) => { next() }, + routerAfterEach: (to, from) => {}, + routerErrorEach: (error, router) => { router.$lockStatus = false; err(error, router, true); }, + detectBeforeLock: (router, to, navType) => {}, + routes: [ + { + path: '/choose-location' + }, + { + path: '/open-location' + }, + { + path: '/preview-image' + } + ] +} + +export const lifeCycle:LifeCycleConfig = { + beforeHooks: [], + afterHooks: [], + routerBeforeHooks: [], + routerAfterHooks: [], + routerErrorHooks: [] +}; + +export const proxyHookDeps:proxyDepsRule = { + resetIndex: [], // 还原时执行的生命周期的索引 + hooks: {}, + options: {} +} + +export const proxyHookName:Array = [ + 'onLaunch', + 'onShow', + 'onHide', + 'onError', + 'onInit', + 'onLoad', + 'onReady', + 'onUnload', + 'onResize', + 'created', + 'beforeMount', + 'mounted', + 'beforeDestroy', + 'destroyed' +] diff --git a/node_modules/uni-simple-router/src/helpers/createRouteMap.ts b/node_modules/uni-simple-router/src/helpers/createRouteMap.ts new file mode 100644 index 0000000..288cc37 --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/createRouteMap.ts @@ -0,0 +1,47 @@ +import {RoutesRule, Router, routesMapRule} from '../options/base'; +import {H5Config} from '../options/config'; +import {warn} from './warn' +import {getRoutePath} from './utils' + +export function createRouteMap( + router: Router, + routes: RoutesRule[], +): routesMapRule|never { + const routesMap:routesMapRule = { + finallyPathList: [], + finallyPathMap: Object.create(null), + aliasPathMap: Object.create(null), + pathMap: Object.create(null), + vueRouteMap: Object.create(null), + nameMap: Object.create(null) + } + routes.forEach(route => { + const { finallyPath, aliasPath, path} = getRoutePath(route, router); + if (path == null) { + throw new Error(`请提供一个完整的路由对象,包括以绝对路径开始的 ‘path’ 字符串 ${JSON.stringify(route)}`); + } + if (finallyPath instanceof Array) { + if (!(router.options.h5 as H5Config).vueRouterDev && router.options.platform === 'h5') { + throw new Error(`非 vueRouterDev 模式下,route.alias 目前无法提供数组类型! ${JSON.stringify(route)}`); + } + } + const strFinallyPath = (finallyPath as string); + const strAliasPath = (aliasPath as string); + if (router.options.platform !== 'h5') { + if (strFinallyPath.indexOf('/') !== 0 && path !== '*') { + warn(`当前路由对象下,route:${JSON.stringify(route)} 是否缺少了前缀 ‘/’`, router, true); + } + } + if (!routesMap.finallyPathMap[strFinallyPath]) { + routesMap.finallyPathMap[strFinallyPath] = route; + routesMap.aliasPathMap[strAliasPath] = route; + routesMap.pathMap[path] = route; + routesMap.finallyPathList.push(strFinallyPath); + if (route.name != null) { + routesMap.nameMap[route.name] = route; + } + } + }) + + return routesMap; +} diff --git a/node_modules/uni-simple-router/src/helpers/lifeCycle.ts b/node_modules/uni-simple-router/src/helpers/lifeCycle.ts new file mode 100644 index 0000000..a2ab776 --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/lifeCycle.ts @@ -0,0 +1,36 @@ +import { navtoRule, navErrorRule, Router, proxyHookName, guardHookRule, totalNextRoute, hookToggle} from '../options/base'; +import { LifeCycleConfig, InstantiateConfig} from '../options/config'; +import {onTriggerEachHook} from '../public/hooks' + +export function registerHook(list:Array, fn:Function):void { + list[0] = fn; +} + +export function registerRouterHooks(cycleHooks:T, options:InstantiateConfig):T { + registerHook(cycleHooks.routerBeforeHooks, function(to:totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void):void { + (options.routerBeforeEach as Function)(to, from, next); + }) + registerHook(cycleHooks.routerAfterHooks, function(to:totalNextRoute, from: totalNextRoute):void { + (options.routerAfterEach as Function)(to, from); + }) + registerHook(cycleHooks.routerErrorHooks, function(error:navErrorRule, router:Router):void { + (options.routerErrorEach as Function)(error, router); + }) + return cycleHooks; +} + +export function registerEachHooks(router:Router, hookType:proxyHookName, userGuard:guardHookRule) { + registerHook(router.lifeCycle[hookType], function( + to:totalNextRoute, + from: totalNextRoute, + next:(rule?: navtoRule|false)=>void, + router:Router, + auto:boolean, + ):void { + if (auto) { // h5端 vue-router自动触发 非自己调用触发 + onTriggerEachHook(to, from, router, hookToggle[hookType], next) + } else { + userGuard(to, from, next) + } + }) +} diff --git a/node_modules/uni-simple-router/src/helpers/mixins.ts b/node_modules/uni-simple-router/src/helpers/mixins.ts new file mode 100644 index 0000000..9a02f34 --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/mixins.ts @@ -0,0 +1,109 @@ +import { Router, routesMapRule, RoutesRule, pageTypeRule} from '../options/base'; +import {createRouteMap} from '../helpers/createRouteMap' +import {buildVueRoutes, buildVueRouter} from '../H5/buildRouter' +import {proxyEachHook} from '../H5/proxyHook' +import {registerLoddingPage} from '../app/appPatch'; +import { proxyPageHook } from '../public/page'; +import { forceGuardEach } from '../public/methods'; +import { assertParentChild, voidFun } from './utils'; +import { getEnterPath } from '../applets/appletPatch'; +import { mpPlatformReg } from './config'; + +let registerRouter:boolean = false; +let onloadProxyOk:boolean = false; + +const appletProxy:{ + app:boolean; + page:string; +} = { + app: false, + page: '' +} + +export function getMixins(Vue:any, router: Router):{ + beforeCreate(this: any): void; +} | { + beforeCreate(): void; +} | { + onLaunch(): void; +} { + let platform = router.options.platform; + if (new RegExp(mpPlatformReg, 'g').test(platform)) { + platform = 'app-lets'; + } + const toggleHooks = { + h5: { + beforeCreate(this: any): void { + if (this.$options.router) { + router.$route = this.$options.router; // 挂载vue-router到路由对象下 + let vueRouteMap:RoutesRule[]|RoutesRule = []; + if (router.options.h5?.vueRouterDev) { + vueRouteMap = router.options.routes; + } else { + vueRouteMap = createRouteMap(router, this.$options.router.options.routes).finallyPathMap; + (router.routesMap as routesMapRule).vueRouteMap = vueRouteMap; + buildVueRoutes(router, vueRouteMap); + } + buildVueRouter(router, this.$options.router, vueRouteMap); + proxyEachHook(router, this.$options.router); + } + } + }, + 'app-plus': { + beforeCreate(this: any): void { + if (!registerRouter) { + registerRouter = true; + proxyPageHook(this, router, 'app'); + registerLoddingPage(router); + } + } + }, + 'app-lets': { + beforeCreate(this: any): void { + // 保证这个函数不会被重写 + const pluginMark = $npm_package_name; + voidFun(pluginMark); + + let isProxy:boolean = true; + const pageType:pageTypeRule = this.$options.mpType; + + if (onloadProxyOk) { + return + } + + if (pageType === 'component') { + isProxy = assertParentChild(appletProxy['page'], this); + } else { + if (pageType === 'page') { + appletProxy[pageType] = getEnterPath(this, router); + router.enterPath = appletProxy[pageType]; // 我不确定在不同端是否都是同样的变现?可能有的为非绝对路径? + } else { + appletProxy[pageType] = true; + } + } + if (isProxy) { + proxyPageHook(this, router, pageType); + } + }, + onLoad(this: any):void{ + // 保证这个函数不会被重写,否则必须在启动页写onLoad + const pluginMark = $npm_package_name; + voidFun(pluginMark); + + if (!onloadProxyOk && assertParentChild(appletProxy['page'], this)) { + onloadProxyOk = true; + forceGuardEach(router); + } + } + } + }; + return toggleHooks[(platform as 'h5'|'app-plus'|'app-lets')]; +} +export function initMixins(Vue: any, router: Router) { + const routesMap = createRouteMap(router, router.options.routes); + router.routesMap = routesMap; // 挂载自身路由表到路由对象下 + // Vue.util.defineReactive(router, '_Route', createRoute(router, 19970806)) + Vue.mixin({ + ...getMixins(Vue, router) + }); +} diff --git a/node_modules/uni-simple-router/src/helpers/utils.ts b/node_modules/uni-simple-router/src/helpers/utils.ts new file mode 100644 index 0000000..7fbd76f --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/utils.ts @@ -0,0 +1,452 @@ +import {H5Config, InstantiateConfig} from '../options/config'; +import {RoutesRule, routesMapRule, routesMapKeysRule, Router, totalNextRoute, objectAny, navErrorRule, NAVTYPE, navRoute, uniBackApiRule, uniBackRule} from '../options/base'; +import {baseConfig} from '../helpers/config'; +import {ERRORHOOK} from '../public/hooks' +import {warnLock} from '../helpers/warn' +import { createRoute, navjump } from '../public/methods'; +const Regexp = require('path-to-regexp'); + +export function voidFun(...args:any):void{} + +export function def( + defObject:objectAny, + key:string, + getValue:Function +) { + Object.defineProperty(defObject, key, { + get() { + return getValue(); + } + }) +} + +export function timeOut(time:number):Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve(); + }, time) + }) +} + +export function mergeConfig(baseConfig: T, userConfig: T): T { + const config: {[key: string]: any} = Object.create(null); + const baseConfigKeys: Array = Object.keys(baseConfig).concat(['resolveQuery', 'parseQuery']); + for (let i = 0; i < baseConfigKeys.length; i += 1) { + const key = baseConfigKeys[i]; + if (userConfig[key] != null) { + if (userConfig[key].constructor === Object) { + config[key] = { + ...baseConfig[key], + ...userConfig[key] + }; + } else if (key === 'routes') { + config[key] = [ + ...baseConfig[key], + ...userConfig[key] + ]; + } else { + config[key] = userConfig[key]; + } + } else { + config[key] = baseConfig[key]; + } + } + return config as T; +} + +export function notDeepClearNull(object:T):T { + for (const key in object) { + if (object[key] == null) { + delete object[key]; + } + } + return object; +} + +export function getRoutePath(route: RoutesRule, router:Router): { + finallyPath: string | string[]; + aliasPath: string; + path: string; + alias: string | string[] | undefined; +} { + let finallyPath = route.aliasPath || route.alias || route.path; + if (router.options.platform !== 'h5') { + finallyPath = route.path + } + return { + finallyPath, + aliasPath: route.aliasPath || route.path, + path: route.path, + alias: route.alias + } +} + +export function assertNewOptions( + options: T +): T | never { + const {platform, routes} = options; + if (platform == null) { + throw new Error(`你在实例化路由时必须传递 'platform'`); + } + if (routes == null || routes.length === 0) { + throw new Error(`你在实例化路由时必须传递 routes 为空,这是无意义的。`); + } + if (options.platform === 'h5') { + if (options.h5?.vueRouterDev) { + baseConfig.routes = []; + } + } + const mergeOptions = mergeConfig(baseConfig as T, options); + return mergeOptions; +} + +export function getWildcardRule( + router:Router, + msg?:navErrorRule +):RoutesRule|never { + const routesMap = (router.routesMap as routesMapRule); + const route = routesMap.finallyPathMap['*']; + if (route) { // 有写通配符 + return route + } + if (msg) { + ERRORHOOK[0](msg, router); + } + throw new Error(`当前路由表匹配规则已全部匹配完成,未找到满足的匹配规则。你可以使用 '*' 通配符捕捉最后的异常`); +} + +export function notRouteTo404( + router:Router, + toRoute:RoutesRule|{ + redirect:any; + path:string + }, + parseToRule:totalNextRoute, + navType:NAVTYPE +):RoutesRule|totalNextRoute|never { + if (toRoute.path !== '*') { // 不是通配符 正常匹配成功 + return (toRoute as RoutesRule); + } + + const redirect = toRoute.redirect; + + if (typeof redirect === 'undefined') { + throw new Error(` * 通配符必须配合 redirect 使用。redirect: string | Location | Function`); + } + + let newRoute = redirect; + if (typeof newRoute === 'function') { + newRoute = newRoute(parseToRule) as totalNextRoute; + } + const redirectRule = navjump(newRoute as totalNextRoute, router, navType, undefined, undefined, undefined, false); + return (redirectRule as totalNextRoute); +} + +export function routesForMapRoute( + router: Router, + path: string, + mapArrayKey:Array, + deepFind:boolean|undefined = false +):RoutesRule|never { + if (router.options.h5?.vueRouterDev) { + return {path} + } + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/252 + const startPath = path.split('?')[0]; + let wildcard = ''; + const routesMap = (router.routesMap as routesMapRule); + for (let i = 0; i < mapArrayKey.length; i++) { + const mapKey = mapArrayKey[i]; + const mapList = routesMap[mapKey]; + for (const [key, value] of Object.entries(mapList)) { + if (key === '*') { + if (wildcard === '') { + wildcard = '*' + } + continue; + } + const route:string|RoutesRule = value; + let rule:string = key; + if (getDataType|objectAny>(mapList) === '[object Array]') { + rule = (route as string); + } + const pathRule:RegExp = Regexp(rule); + const result = pathRule.exec(startPath); + if (result != null) { + if (getDataType(route) === '[object String]') { + return routesMap.finallyPathMap[(route as string)]; + } + return (route as RoutesRule); + } + } + } + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/302 2021-8-4 16:38:44 + if (deepFind) { + return ({} as RoutesRule); + } + if (routesMap['aliasPathMap']) { + const results = routesForMapRoute(router, path, ['aliasPathMap'], true); + if (Object.keys(results).length > 0) { + return results; + } + } + if (wildcard !== '') { + return getWildcardRule(router); + } + throw new Error(`${path} 路径无法在路由表中找到!检查跳转路径及路由表`); +} + +export function getDataType(data:T):string { + return Object.prototype.toString.call(data) +} + +export function copyData(object:T): T { + return JSON.parse(JSON.stringify(object)) +} + +export function getUniCachePage(pageIndex?:number):T|[] { + const pages:T = getCurrentPages(); + if (pageIndex == null) { + return pages + } + if (pages.length === 0) { + return pages; + } + const page = pages.reverse()[pageIndex]; + if (page == null) { + return [] + } + return page; +} + +export function urlToJson(url :string):{ + path:string; + query:objectAny +} { + const query:objectAny = {}; + const [path, params] = url.split('?'); + if (params != null) { + const parr = params.split('&'); + for (const i of parr) { + const arr = i.split('='); + query[arr[0]] = arr[1]; + } + } + return { + path, + query + } +} + +export function forMatNextToFrom( + router:Router, + to:T, + from:T +):{ + matTo:T; + matFrom: T; +} { + let [matTo, matFrom] = [to, from]; + if (router.options.platform === 'h5') { + const {vueNext, vueRouterDev} = (router.options.h5 as H5Config); + if (!vueNext && !vueRouterDev) { + matTo = createRoute(router, undefined, matTo) as T; + matFrom = createRoute(router, undefined, matFrom) as T; + } + } else { + matTo = createRoute(router, undefined, deepClone(matTo)) as T; + matFrom = createRoute(router, undefined, deepClone(matFrom)) as T; + } + return { + matTo: matTo, + matFrom: matFrom + } +} + +export function paramsToQuery( + router:Router, + toRule:totalNextRoute|string +):totalNextRoute|string { + if (router.options.platform === 'h5' && !router.options.h5?.paramsToQuery) { + return toRule; + } + if (getDataType(toRule) === '[object Object]') { + const {name, params, ...moreToRule} = (toRule as totalNextRoute); + let paramsQuery = params; + if (router.options.platform !== 'h5' && paramsQuery == null) { + paramsQuery = {}; + } + if (name != null && paramsQuery != null) { + let route = (router.routesMap as routesMapRule).nameMap[name]; + if (route == null) { + route = getWildcardRule(router, { type: 2, msg: `命名路由为:${name} 的路由,无法在路由表中找到!`, toRule}); + } + const {finallyPath} = getRoutePath(route, router); + if (finallyPath.includes(':')) { // 动态路由无法使用 paramsToQuery + ERRORHOOK[0]({ type: 2, msg: `动态路由:${finallyPath} 无法使用 paramsToQuery!`, toRule}, router); + } else { + return { + ...moreToRule, + path: finallyPath as string, + query: paramsQuery + } + } + } + } + return toRule +} + +export function assertDeepObject(object:objectAny):boolean { + let arrMark = null; + try { + arrMark = JSON.stringify(object).match(/\{|\[|\}|\]/g); + } catch (error) { + warnLock(`传递的参数解析对象失败。` + error) + } + if (arrMark == null) { + return false + } + if (arrMark.length > 3) { + return true; + } + return false +} + +export function baseClone< +T extends { + [key:string]:any +}, K extends keyof T +>( + source:T, + target:Array|objectAny +):Array|objectAny|null { + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/292 + // 小程序会将null解析为字符串 undefined 建议不要在参数中传递 null + if (source == null) { + target = source; + } else { + for (const key of Object.keys(source)) { + const dyKey = key as T[K]; + if (source[key] === source) continue + if (typeof source[key] === 'object') { + target[dyKey] = getDataType(source[key]) === '[object Array]' ? ([] as Array) : ({} as objectAny) + target[dyKey] = baseClone(source[key], target[dyKey]) + } else { + target[dyKey] = source[key] + } + } + } + return target; +} + +export function deepClone(source:T):T { + const __ob__ = getDataType(source) === '[object Array]' ? ([] as Array) : ({} as objectAny); + baseClone(source, __ob__) + return __ob__ as T +} + +export function lockDetectWarn( + router:Router, + to:string|number|totalNextRoute|navRoute, + navType:NAVTYPE, + next:Function, + uniActualData:uniBackApiRule|uniBackRule|undefined = {}, + passiveType?:'beforeHooks'| 'afterHooks' +):void{ + if (passiveType === 'afterHooks') { + next(); + } else { + const {detectBeforeLock} = router.options; + detectBeforeLock && detectBeforeLock(router, to, navType); + if (router.$lockStatus) { + (router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({ + type: 2, + msg: '当前页面正在处于跳转状态,请稍后再进行跳转....', + NAVTYPE: navType, + uniActualData + }, router); + } else { + next(); + } + } +} + +export function assertParentChild( + parentPath:string, + vueVim:any, +):boolean { + while (vueVim.$parent != null) { + const mpPage = vueVim.$parent.$mp; + if (mpPage.page && mpPage.page.is === parentPath) { + return true; + } + vueVim = vueVim.$parent; + } + try { + if (vueVim.$mp.page.is === parentPath || vueVim.$mp.page.route === parentPath) { + return true + } + } catch (error) { + return false + } + return false +} + +export function resolveAbsolutePath( + path:string, + router:Router +):string|never { + const reg = /^\/?([^\?\s]+)(\?.+)?$/; + const trimPath = path.trim(); + if (!reg.test(trimPath)) { + throw new Error(`【${path}】 路径错误,请提供完整的路径(10001)。`); + } + const paramsArray = trimPath.match(reg); + if (paramsArray == null) { + throw new Error(`【${path}】 路径错误,请提供完整的路径(10002)。`); + } + const query:string = paramsArray[2] || ''; + if (/^\.\/[^\.]+/.test(trimPath)) { // 当前路径下 + const navPath:string = router.currentRoute.path + path; + return navPath.replace(/[^\/]+\.\//, ''); + } + const relative = paramsArray[1].replace(/\//g, `\\/`).replace(/\.\./g, `[^\\/]+`).replace(/\./g, '\\.'); + const relativeReg = new RegExp(`^\\/${relative}$`); + const route = router.options.routes.filter(it => relativeReg.test(it.path)); + if (route.length !== 1) { + throw new Error(`【${path}】 路径错误,尝试转成绝对路径失败,请手动转成绝对路径(10003)。`); + } + return route[0].path + query; +} + +export function deepDecodeQuery( + query:objectAny +):objectAny { + const formatQuery:objectAny = getDataType(query) === '[object Array]' ? [] : {}; + const keys = Object.keys(query); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const it = query[key]; + if (typeof it === 'string') { + try { + let json = JSON.parse(decodeURIComponent(it)); + if (typeof json !== 'object') { + json = it; + } + formatQuery[key] = json; + } catch (error) { + try { + formatQuery[key] = decodeURIComponent(it) + } catch (error) { + formatQuery[key] = it + } + } + } else if (typeof it === 'object') { + const childQuery = deepDecodeQuery(it); + formatQuery[key] = childQuery + } else { + formatQuery[key] = it + } + } + return formatQuery +} diff --git a/node_modules/uni-simple-router/src/helpers/warn.ts b/node_modules/uni-simple-router/src/helpers/warn.ts new file mode 100644 index 0000000..817ffb7 --- /dev/null +++ b/node_modules/uni-simple-router/src/helpers/warn.ts @@ -0,0 +1,37 @@ + +import {debuggerConfig, debuggerArrayConfig} from '../options/config' +import {Router} from '../options/base' + +type callType='error'|'warn'|'log'; + +export function isLog(type:callType, dev:debuggerConfig, errText:any, enforce:boolean = false):boolean { + if (!enforce) { + const isObject = dev.toString() === '[object Object]'; + if (dev === false) { + return false + } else if (isObject) { + if ((dev as debuggerArrayConfig)[type] === false) { + return false; + } + } + } + console[type](errText); + return true; +} +export function err(errText:any, router:Router, enforce?:boolean):void { + const dev = (router.options.debugger as debuggerConfig); + isLog('error', dev, errText, enforce); +} + +export function warn(errText:any, router:Router, enforce?:boolean):void { + const dev = (router.options.debugger as debuggerConfig); + isLog('warn', dev, errText, enforce); +} + +export function log(errText:any, router:Router, enforce?:boolean):void { + const dev = (router.options.debugger as debuggerConfig); + isLog('log', dev, errText, enforce); +} +export function warnLock(errText:any):void { + console.warn(errText); +} diff --git a/node_modules/uni-simple-router/src/index.ts b/node_modules/uni-simple-router/src/index.ts new file mode 100644 index 0000000..3d5812f --- /dev/null +++ b/node_modules/uni-simple-router/src/index.ts @@ -0,0 +1,11 @@ +export * from './options/base' +export * from './options/config' + +export { + runtimeQuit +} from './app/appPatch' + +export { + RouterMount, + createRouter +} from './public/router' diff --git a/node_modules/uni-simple-router/src/options/base.ts b/node_modules/uni-simple-router/src/options/base.ts new file mode 100644 index 0000000..2f23883 --- /dev/null +++ b/node_modules/uni-simple-router/src/options/base.ts @@ -0,0 +1,245 @@ +import {InstantiateConfig, LifeCycleConfig} from '../options/config'; + +export enum hookToggle{ + 'beforeHooks'='beforeEach', + 'afterHooks'='afterEach', + 'enterHooks'='beforeEnter' +} +export enum navtypeToggle{ + 'push'='navigateTo', + 'replace'='redirectTo', + 'replaceAll'='reLaunch', + 'pushTab'='switchTab', + 'back'='navigateBack' +} +export enum rewriteMethodToggle{ + 'navigateTo'='push', + 'navigate'='push', + 'redirectTo'='replace', + 'reLaunch'='replaceAll', + 'switchTab'='pushTab', + 'navigateBack'='back', +} +export type proxyDepsRule={ + resetIndex:Array; + hooks: { + [key: number]:{ + proxyHook:()=>void; + callHook:(enterPath:string)=>void; + resetHook: ()=>void + } + }; + options: {[key: number]: Array;}; +}; +export type backTypeRule='backbutton'|'navigateBack' +export type pageTypeRule='app'|'page'|'component'; +export type vueHookNameRule='onLaunch'|'onShow'|'onHide'|'onError'|'onInit'|'onLoad'|'onReady'|'onUnload'|'onResize'|'created'|'beforeMount'|'mounted'|'beforeDestroy'|'destroyed' +export type reNavMethodRule='navigateTo'|'redirectTo'|'reLaunch'|'switchTab'; +export type reNotNavMethodRule='navigateBack'; +export type reloadNavRule=totalNextRoute | false | undefined|string; +export type hookListRule=Array<(router:Router, to:totalNextRoute, from: totalNextRoute, toRoute:RoutesRule,next:Function)=>void> +export type guardHookRule=(to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void)=>void; +export type navRuleStatus= 0|1|2|3; //0: next(false) 1:next(unknownType) 2:加锁状态,禁止跳转 3:在获取页面栈的时候,页面栈不够level获取 +export type proxyHookName='beforeHooks'|'afterHooks'; +export type navMethodRule = Promise; +export type objectAny={[propName: string]: any;}; +export type NAVTYPE = 'push' | 'replace' | 'replaceAll' | 'pushTab'|'back'; +export type startAnimationType = + | 'slide-in-right' + | 'slide-in-left' + | 'slide-in-top' + | 'slide-in-bottom' + | 'pop-in' + | 'fade-in' + | 'zoom-out' + | 'zoom-fade-out' + | 'none'; +export type endAnimationType = + | 'slide-out-right' + | 'slide-out-left' + | 'slide-out-top' + | 'slide-out-bottom' + | 'pop-out' + | 'fade-out' + | 'zoom-in' + | 'zoom-fade-in' + | 'none'; + +export type vueOptionRule = { + [propName in vueHookNameRule]: Array | undefined; +}; + +// 跳转api时,传递的跳转规则 +export interface navtoRule { + NAVTYPE?: NAVTYPE; // 跳转类型 v1.1.0+ + path?: string; // 跳转路径 绝对路径 + name?: string | undefined; // 跳转路径名称 + query?: objectAny; // 跳转使用path时 query包含需要传递的参数 + params?: objectAny; // 跳转使用name时 params包含需要传递的参数 + animationType?: startAnimationType|endAnimationType; + animationDuration?: number; + events?: objectAny; + success?: Function; + fail?: Function; + complete?: Function; +} +// h5 next管道函数中传递的from及to对象 +export interface h5NextRule { + fullPath?: string | undefined; + hash?: string | undefined; + matched?: Array; + meta?: object; + name?: undefined | string; + type?: undefined | string; +} + +export interface totalNextRoute extends h5NextRule, navtoRule { + path:string; + delta?:number; + [propName: string]: any; +} +export interface navRoute extends h5NextRule, navtoRule { + +} + +// 开始切换窗口动画 app端可用 +export interface startAnimationRule { + animationType?: startAnimationType; // 窗口关闭的动画效果 + animationDuration?: number; // 窗口关闭动画的持续时间 +} +// 关闭窗口时的动画 app端可用 +export interface endAnimationRule { + animationType?: endAnimationType; // 窗口关闭的动画效果 + animationDuration?: number; // 窗口关闭动画的持续时间 +} +export interface hookObjectRule { + options:Array; + hook:Function; +} + +// 执行路由跳转失败或者 next(false) 时走的规则 +export interface navErrorRule { + type: navRuleStatus; + msg: string; + to?:totalNextRoute; + from?:totalNextRoute; + nextTo?:any; + [propName:string]:any; +} +// uni原生api跳转时的规则 +export interface uniNavApiRule { + url: string; + openType?:'appLaunch', + query?:objectAny; + path?:string; + delta?:number; + detail?:{[propName:string]:any}; + animationType?:startAnimationType; + animationDuration?:number; + events?:{[propName:string]:any}; + success?:Function; + fail?:Function; + complete?:Function; + animation?:{ + animationType?:startAnimationType; + animationDuration?:number; + } +} + +export interface originMixins extends uniNavApiRule{ + BACKTYPE:''|backTypeRule +} + +// uni-app 原始返回api 回调参数 +export interface uniBackRule{ + from:backTypeRule; +} + +export interface uniBackApiRule{ + delta?: number; + animationDuration?: number; + animationType?:endAnimationType; +} + +export type routesMapKeysRule= + 'finallyPathList'| + 'finallyPathMap'| + 'aliasPathMap'| + 'pathMap'| + 'nameMap'| + 'vueRouteMap'; + +export interface routesMapRule{ + [key:string]:any; + finallyPathList: Array; + finallyPathMap:RoutesRule; + aliasPathMap: RoutesRule; + pathMap: RoutesRule; + nameMap:RoutesRule, + vueRouteMap:objectAny +} + +export interface routeRule{ + name:string|undefined; + meta:objectAny; + path:string; + query:objectAny; + params:objectAny; + fullPath:string; + NAVTYPE:NAVTYPE|''; + BACKTYPE?:backTypeRule|''; // v2.0.5 + + [propName: string]: any; +} + + +export interface RoutesRule { + path: string; // pages.json中的path 必须加上 '/' 开头 + component?: object; // H5端可用 + name?: string; // 命名路由 + components?: object; // 命名视图组件,H5端可用 + redirect?: string | Function; // H5端可用 + props?: boolean | object | Function; // H5端可用 + aliasPath?: string; // h5端 设置一个别名路径来替换 uni-app的默认路径 + alias?: string | Array; // H5端可用 + children?: Array; // 嵌套路由,H5端可用 + beforeEnter?:guardHookRule; // 路由元守卫 + meta?: any; // 其他格外参数 + [propName: string]: any; +} + +export interface Router { + [key:string]:any; + readonly lifeCycle: LifeCycleConfig; + readonly options: InstantiateConfig; + $lockStatus:boolean; + $route: object | null; + enterPath:string; + Vue:any; + appMain:{ + NAVTYPE:reNavMethodRule|reNotNavMethodRule, + path:string + }|{}; + proxyHookDeps: proxyDepsRule; + routesMap: routesMapRule|{}; + mount: Array<{app: any; el: string}>; + install(Vue: any): void; + push(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 保留浏览历史 + replace(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。 + replaceAll(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面 + pushTab(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 url 关闭所有页面,打开到应用内的某个tab + back(level:number|undefined,origin?:uniBackRule|uniBackApiRule):void; + forceGuardEach(navType:NAVTYPE|undefined,forceNav:boolean):void; //强制触发当前守卫 + beforeEach(userGuard:guardHookRule): void; // 添加全局前置路由守卫 + afterEach(userGuard:(to: totalNextRoute, from: totalNextRoute)=>void): void; // 添加全局后置路由守卫 +} + + +export type PromiseResolve=(value?: void | PromiseLike | undefined) => void; + +// @ts-ignore +declare module 'vue/types/vue' { + interface Vue { + $Router: Router; + $Route: routeRule; + } +} \ No newline at end of file diff --git a/node_modules/uni-simple-router/src/options/config.ts b/node_modules/uni-simple-router/src/options/config.ts new file mode 100644 index 0000000..fc7efdc --- /dev/null +++ b/node_modules/uni-simple-router/src/options/config.ts @@ -0,0 +1,57 @@ +import {startAnimationRule, hookListRule, RoutesRule, navtoRule, navErrorRule, Router, objectAny, NAVTYPE, totalNextRoute, navRoute} from './base'; + +export type debuggerConfig=boolean|debuggerArrayConfig; +export type platformRule='h5'|'app-plus'|'app-lets'|'mp-weixin'|'mp-baidu'|'mp-alipay'|'mp-toutiao'|'mp-qq'|'mp-360'; + +export interface H5Config { + paramsToQuery?: boolean; // h5端上通过params传参时规则是vue-router 刷新会丢失 开启此开关将变成?连接的方式 + vueRouterDev?: boolean; // 完全使用采用vue-router的开发模式 + vueNext?: boolean; // 在next管道函数中是否获取vueRouter next的原本参数 + mode?: string; + base?: string; + linkActiveClass?: string; + linkExactActiveClass?: string; + scrollBehavior?: Function; + fallback?: boolean; +} +export interface AppConfig { + registerLoadingPage?:boolean; // 是否注册过渡加载页 +v2.0.6 + loadingPageStyle?: () => object; // 当前等待页面的样式 必须返回一个json + loadingPageHook?: (view:any)=>void; // 刚刚打开页面处于等待状态,会触发此函数 + launchedHook?:()=>void; // 首次启动app完成 + animation?: startAnimationRule; // 页面切换动画 +} +export interface appletConfig { + animationDuration?:number; // 页面切换时间,有助于路由锁精准解锁 +} + +export interface debuggerArrayConfig{ + error?:boolean; + warn?:boolean; + log?:boolean; +} + +export interface InstantiateConfig { + [key:string]:any; + keepUniOriginNav?:boolean; // 重写uni-app的跳转方法;关闭后使用uni-app的原始方法跳转和插件api跳转等同 + platform:platformRule; // 当前运行平台 + h5?: H5Config; + APP?: AppConfig; + applet?:appletConfig; + debugger?: debuggerConfig; // 是否处于开发阶段 设置为true则打印日志 + routerBeforeEach?: (to:navtoRule, from:navtoRule, next:(rule?: navtoRule|false)=>void) => void; // router 前置路由函数 每次触发跳转前先会触发此函数 + routerAfterEach?: (to:navtoRule, from:navtoRule, next?: Function) => void; // router 后置路由函数 每次触发跳转后会触发此函数 + routerErrorEach?: (error: navErrorRule, router:Router) => void; + resolveQuery?:(jsonQuery:objectAny)=>objectAny; // 跳转之前把参数传递给此函数、返回最终的数据!有此函数不走默认方法 + parseQuery?:(jsonQuery:objectAny)=>objectAny; // 读取值之前把参数传递给此函数,返回最终的数据!有此函数不走默认方法 + detectBeforeLock?:(router:Router, to:string|number|totalNextRoute|navRoute, navType:NAVTYPE)=>void; // 在检测路由锁之前触发的函数 + routes: RoutesRule[]; +} +export interface LifeCycleConfig{ + beforeHooks: hookListRule; + afterHooks: hookListRule; + routerBeforeHooks: hookListRule; + routerAfterHooks: hookListRule; + routerErrorHooks: Array<(error:navErrorRule, router:Router)=>void>; +} + diff --git a/node_modules/uni-simple-router/src/public/hooks.ts b/node_modules/uni-simple-router/src/public/hooks.ts new file mode 100644 index 0000000..e784b42 --- /dev/null +++ b/node_modules/uni-simple-router/src/public/hooks.ts @@ -0,0 +1,177 @@ +import { + Router, + hookListRule, + navtoRule, + reloadNavRule, + totalNextRoute, + hookToggle, + NAVTYPE, + navErrorRule, + objectAny +} from '../options/base'; +import { + routesForMapRoute, + getDataType, + forMatNextToFrom, + getUniCachePage, + voidFun +} from '../helpers/utils' +import { navjump } from './methods'; +import { proxyH5Mount } from '../H5/proxyHook'; +import { tabIndexSelect } from '../app/appPatch'; + +export const ERRORHOOK:Array<(error:navErrorRule, router:Router)=>void> = [ + (error, router) => router.lifeCycle.routerErrorHooks[0](error, router) +] +export const HOOKLIST: hookListRule = [ + (router, to, from, toRoute, next) => callHook(router.lifeCycle.routerBeforeHooks[0], to, from, router, next), + (router, to, from, toRoute, next) => callBeforeRouteLeave(router, to, from, next), + (router, to, from, toRoute, next) => callHook(router.lifeCycle.beforeHooks[0], to, from, router, next), + (router, to, from, toRoute, next) => callHook(toRoute.beforeEnter, to, from, router, next), + (router, to, from, toRoute, next) => callHook(router.lifeCycle.afterHooks[0], to, from, router, next, false), + (router, to, from, toRoute, next) => { + router.$lockStatus = false; + if (router.options.platform === 'h5') { + proxyH5Mount(router); + } + return callHook(router.lifeCycle.routerAfterHooks[0], to, from, router, next, false) + } +]; + +export function callBeforeRouteLeave( + router:Router, + to:totalNextRoute, + from:totalNextRoute, + resolve:Function +):void { + const page = getUniCachePage(0); + let beforeRouteLeave; + if (Object.keys(page).length > 0) { + let leaveHooks:Array|undefined|Function; + if (router.options.platform === 'h5') { + leaveHooks = (page as objectAny).$options.beforeRouteLeave; + } else { + if ((page as objectAny).$vm != null) { + leaveHooks = (page as objectAny).$vm.$options.beforeRouteLeave; + } + } + switch (getDataType>((leaveHooks as Array))) { + case '[object Array]': // h5端表现 + beforeRouteLeave = (leaveHooks as Array)[0]; + beforeRouteLeave = beforeRouteLeave.bind(page) + break; + case '[object Function]': // 目前app端表现 + beforeRouteLeave = (leaveHooks as Function).bind((page as objectAny).$vm); + break + } + } + return callHook(beforeRouteLeave, to, from, router, resolve); +} + +export function callHook( + hook:Function|undefined, + to:totalNextRoute, + from: totalNextRoute, + router:Router, + resolve:Function, + hookAwait:boolean|undefined = true +):void { + if (hook != null && hook instanceof Function) { + if (hookAwait === true) { + hook(to, from, resolve, router, false); + } else { + hook(to, from, () => {}, router, false); + resolve(); + } + } else { + resolve(); + } +} + +export function onTriggerEachHook( + to:totalNextRoute, + from: totalNextRoute, + router:Router, + hookType:hookToggle, + next:(rule?: navtoRule|false)=>void, +):void { + let callHookList:hookListRule = []; + switch (hookType) { + case 'beforeEach': + callHookList = HOOKLIST.slice(0, 3); + break; + case 'afterEach': + callHookList = HOOKLIST.slice(4); + break + case 'beforeEnter': + callHookList = HOOKLIST.slice(3, 4); + break; + } + transitionTo(router, to, from, 'push', callHookList, next); +} + +export function transitionTo( + router:Router, + to:totalNextRoute, + from: totalNextRoute, + navType:NAVTYPE, + callHookList:hookListRule, + hookCB:Function +) :void{ + const {matTo, matFrom} = forMatNextToFrom(router, to, from); + if (router.options.platform === 'h5') { + loopCallHook(callHookList, 0, hookCB, router, matTo, matFrom, navType); + } else { + loopCallHook(callHookList.slice(0, 4), 0, () => { + hookCB(() => { // 非H5端等他跳转完才触发最后两个生命周期 + loopCallHook(callHookList.slice(4), 0, voidFun, router, matTo, matFrom, navType); + }); + }, router, matTo, matFrom, navType); + } +} + +export function loopCallHook( + hooks:hookListRule, + index:number, + next:Function, + router:Router, + matTo:totalNextRoute, + matFrom: totalNextRoute, + navType:NAVTYPE, +): void|Function { + const toRoute = routesForMapRoute(router, matTo.path, ['finallyPathMap', 'pathMap']); + if (hooks.length - 1 < index) { + return next(); + } + const hook = hooks[index]; + const errHook = ERRORHOOK[0]; + hook(router, matTo, matFrom, toRoute, (nextTo:reloadNavRule) => { + if (router.options.platform === 'app-plus') { + if (nextTo === false || (typeof nextTo === 'string' || typeof nextTo === 'object')) { + tabIndexSelect(matTo, matFrom); + } + } + if (nextTo === false) { + if (router.options.platform === 'h5') { + next(false); + } + errHook({ type: 0, msg: '管道函数传递 false 导航被终止!', matTo, matFrom, nextTo }, router) + } else if (typeof nextTo === 'string' || typeof nextTo === 'object') { + let newNavType = navType; + let newNextTo = nextTo; + if (typeof nextTo === 'object') { + const {NAVTYPE: type, ...moreTo} = nextTo; + newNextTo = moreTo; + if (type != null) { + newNavType = type; + } + } + navjump(newNextTo, router, newNavType, {from: matFrom, next}) + } else if (nextTo == null) { + index++; + loopCallHook(hooks, index, next, router, matTo, matFrom, navType) + } else { + errHook({ type: 1, msg: '管道函数传递未知类型,无法被识别。导航被终止!', matTo, matFrom, nextTo }, router) + } + }); +} diff --git a/node_modules/uni-simple-router/src/public/methods.ts b/node_modules/uni-simple-router/src/public/methods.ts new file mode 100644 index 0000000..39cbc98 --- /dev/null +++ b/node_modules/uni-simple-router/src/public/methods.ts @@ -0,0 +1,258 @@ +import { + NAVTYPE, + Router, + totalNextRoute, + objectAny, + routeRule, + reNavMethodRule, + rewriteMethodToggle, + navtypeToggle, + navErrorRule, + uniBackApiRule, + uniBackRule, + navRoute +} from '../options/base' +import { + queryPageToMap, + resolveQuery, + parseQuery +} from './query' +import { + voidFun, + paramsToQuery, + getUniCachePage, + routesForMapRoute, + copyData, + lockDetectWarn, + getDataType, + notRouteTo404, + deepDecodeQuery +} from '../helpers/utils' +import { transitionTo } from './hooks'; +import {createFullPath, createToFrom} from '../public/page' +import {HOOKLIST} from './hooks' + +export function lockNavjump( + to:string|totalNextRoute|navRoute, + router:Router, + navType:NAVTYPE, + forceNav?:boolean, + animation?:uniBackApiRule|uniBackRule +):void{ + lockDetectWarn(router, to, navType, () => { + if (router.options.platform !== 'h5') { + router.$lockStatus = true; + } + navjump(to as totalNextRoute, router, navType, undefined, forceNav, animation); + }, animation); +} +export function navjump( + to:string|totalNextRoute, + router:Router, + navType:NAVTYPE, + nextCall?:{ + from:totalNextRoute; + next:Function; + }, + forceNav?:boolean, + animation?:uniBackApiRule|uniBackRule, + callHook:boolean|undefined = true +) :void|never|totalNextRoute { + if (navType === 'back') { + let level:number = 1; + if (typeof to === 'string') { + level = +to; + } else { + level = to.delta || 1; + } + if (router.options.platform === 'h5') { + (router.$route as any).go(-level); + + // Fixe https://github.com/SilurianYang/uni-simple-router/issues/266 2021年6月3日11:14:38 + // @ts-ignore + const success = (animation || {success: voidFun}).success || voidFun; + // @ts-ignore + const complete = (animation || {complete: voidFun}).complete || voidFun; + success({errMsg: 'navigateBack:ok'}); + complete({errMsg: 'navigateBack:ok'}); + return; + } else { + to = backOptionsBuild(router, level, animation); + } + } + const {rule} = queryPageToMap(to, router); + rule.type = navtypeToggle[navType]; + const toRule = paramsToQuery(router, rule); + let parseToRule = resolveQuery(toRule as totalNextRoute, router); + if (router.options.platform === 'h5') { + if (navType !== 'push') { + navType = 'replace'; + } + if (nextCall != null) { // next 管道函数拦截时 直接next即可 + nextCall.next({ + replace: navType !== 'push', + ...parseToRule + }) + } else { + // Fixe https://github.com/SilurianYang/uni-simple-router/issues/240 2021年3月7日14:45:36 + if (navType === 'push' && Reflect.has(parseToRule, 'events')) { + if (Reflect.has(parseToRule, 'name')) { + throw new Error(`在h5端上使用 'push'、'navigateTo' 跳转时,如果包含 events 不允许使用 name 跳转,因为 name 实现了动态路由。请更换为 path 或者 url 跳转!`); + } else { + uni['navigateTo'](parseToRule, true, voidFun, forceNav); + } + } else { + (router.$route as any)[navType](parseToRule, (parseToRule as totalNextRoute).success || voidFun, (parseToRule as totalNextRoute).fail || voidFun) + } + } + } else { + let from:totalNextRoute = {path: ''}; + if (nextCall == null) { + let toRoute = routesForMapRoute(router, parseToRule.path, ['finallyPathMap', 'pathMap']); + toRoute = notRouteTo404(router, toRoute, parseToRule, navType); + parseToRule = { ...toRoute, ...{params: {}}, ...parseToRule, ...{path: toRoute.path} } + from = createToFrom(parseToRule, router); + } else { + from = nextCall.from; + } + createFullPath(parseToRule, from); + if (callHook === false) { + return parseToRule; + } + transitionTo(router, parseToRule, from, navType, HOOKLIST, function( + callOkCb:Function + ):void { + uni[navtypeToggle[navType]](parseToRule, true, callOkCb, forceNav); + }) + } +} + +export function backOptionsBuild( + router:Router, + level:number, + animation:uniBackApiRule|uniBackRule|undefined = {}, +):totalNextRoute { + const toRule = createRoute(router, level, undefined, {NAVTYPE: 'back', ...animation}); + const navjumpRule:totalNextRoute = { + ...animation, + path: toRule.path, + query: toRule.query, + delta: level + } + if (getDataType(animation) === '[object Object]') { + const {animationDuration, animationType} = (animation as uniBackApiRule) + if (animationDuration != null) { + navjumpRule.animationDuration = animationDuration; + } + if (animationType != null) { + navjumpRule.animationType = animationType; + } + + const {from} = (animation as uniBackRule) + if (from != null) { + navjumpRule.BACKTYPE = from; + } + } + return navjumpRule; +} + +export function forceGuardEach( + router:Router, + navType:NAVTYPE|undefined = 'replaceAll', + forceNav:undefined|boolean = false +):void|never { + if (router.options.platform === 'h5') { + throw new Error(`在h5端上使用:forceGuardEach 是无意义的,目前 forceGuardEach 仅支持在非h5端上使用`); + } + const currentPage = getUniCachePage(0); + if (Object.keys(currentPage).length === 0) { + (router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({ + type: 3, + NAVTYPE: navType, + uniActualData: {}, + level: 0, + msg: `不存在的页面栈,请确保有足够的页面可用,当前 level:0` + }, router); + } + const {route, options} = currentPage as objectAny; + lockNavjump({ + path: `/${route}`, + query: deepDecodeQuery(options || {}) + }, router, navType, forceNav); +} + +export function createRoute( + router:Router, + level:number|undefined = 0, + orignRule?:totalNextRoute, + uniActualData:objectAny|undefined = {}, +):routeRule|never { + const route:routeRule = { + name: '', + meta: {}, + path: '', + fullPath: '', + NAVTYPE: '', + query: {}, + params: {}, + BACKTYPE: (orignRule || {BACKTYPE: ''}).BACKTYPE || '' // v2.0.5 + + }; + + if (level === 19970806) { // 首次构建响应式 页面不存在 直接返回 + return route + } + if (router.options.platform === 'h5') { + let vueRoute:totalNextRoute = {path: ''}; + if (orignRule != null) { + vueRoute = orignRule; + } else { + vueRoute = (router.$route as objectAny).currentRoute; + } + const matRouteParams = copyData(vueRoute.params as objectAny); + delete matRouteParams.__id__; + const toQuery = parseQuery({...matRouteParams, ...copyData(vueRoute.query as objectAny)}, router); + vueRoute = {...vueRoute, query: toQuery} + route.path = vueRoute.path; + route.fullPath = vueRoute.fullPath || ''; + route.query = deepDecodeQuery(vueRoute.query || {}); + route.NAVTYPE = rewriteMethodToggle[vueRoute.type as reNavMethodRule || 'reLaunch']; + } else { + let appPage:objectAny = {}; + if (orignRule != null) { + appPage = {...orignRule, openType: orignRule.type}; + } else { + const page = getUniCachePage(level); + if (Object.keys(page).length === 0) { + const {NAVTYPE: _NAVTYPE, ..._args} = uniActualData; + const errorMsg:string = `不存在的页面栈,请确保有足够的页面可用,当前 level:${level}`; + (router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({ + type: 3, + msg: errorMsg, + NAVTYPE: _NAVTYPE, + level, + uniActualData: _args + }, router); + throw new Error(errorMsg); + } + // Fixes: https://github.com/SilurianYang/uni-simple-router/issues/196 + const pageOptions:objectAny = (page as objectAny).options || {}; + appPage = { + ...(page as objectAny).$page || {}, + query: deepDecodeQuery(pageOptions), + fullPath: decodeURIComponent(((page as objectAny).$page || {}).fullPath || '/' + (page as objectAny).route) + } + if (router.options.platform !== 'app-plus') { + appPage.path = `/${(page as objectAny).route}` + } + } + const openType:reNavMethodRule|'navigateBack' = appPage.openType; + route.query = appPage.query; + route.path = appPage.path; + route.fullPath = appPage.fullPath; + route.NAVTYPE = rewriteMethodToggle[openType || 'reLaunch']; + } + const tableRoute = routesForMapRoute(router, route.path, ['finallyPathMap', 'pathMap']) + const perfectRoute = { ...route, ...tableRoute}; + perfectRoute.query = parseQuery(perfectRoute.query, router); + return perfectRoute; +} diff --git a/node_modules/uni-simple-router/src/public/page.ts b/node_modules/uni-simple-router/src/public/page.ts new file mode 100644 index 0000000..3a32bf3 --- /dev/null +++ b/node_modules/uni-simple-router/src/public/page.ts @@ -0,0 +1,103 @@ +import { proxyHookName } from '../helpers/config'; +import { getDataType, getUniCachePage, deepClone} from '../helpers/utils'; +import { objectAny, pageTypeRule, Router, totalNextRoute, vueOptionRule } from '../options/base'; +import {createRoute} from './methods' +import { stringifyQuery } from './query'; + +export function createToFrom( + to:totalNextRoute, + router:Router, +):totalNextRoute { + let fromRoute:totalNextRoute = {path: ''}; + const page = getUniCachePage|objectAny>(0); + if (getDataType|objectAny>(page) === '[object Array]') { + fromRoute = deepClone(to) + } else { + fromRoute = createRoute(router) as totalNextRoute; + } + return fromRoute; +} + +export function createFullPath( + to:totalNextRoute, + from:totalNextRoute +):void{ + if (to.fullPath == null) { + const strQuery = stringifyQuery(to.query as objectAny); + to.fullPath = to.path + strQuery; + } + if (from.fullPath == null) { + const strQuery = stringifyQuery(from.query as objectAny); + from.fullPath = from.path + strQuery; + } +} + +export function proxyPageHook( + vueVim:any, + router:Router, + pageType:pageTypeRule +):void { + const hookDeps = router.proxyHookDeps; + const pageHook:vueOptionRule = vueVim.$options; + for (let i = 0; i < proxyHookName.length; i++) { + const hookName = proxyHookName[i]; + const hookList = pageHook[hookName]; + if (hookList) { + for (let k = 0; k < hookList.length; k++) { + const originHook = hookList[k]; + if (originHook.toString().includes($npm_package_name)) { + continue + } + const resetIndex = Object.keys(hookDeps.hooks).length + 1 + const proxyHook = (...args:Array):void => { + hookDeps.resetIndex.push(resetIndex); + hookDeps.options[resetIndex] = args; + } + const [resetHook] = hookList.splice(k, 1, proxyHook); + hookDeps.hooks[resetIndex] = { + proxyHook, + callHook: (enterPath:string) :void => { + if (router.enterPath.replace(/^\//, '') !== enterPath.replace(/^\//, '') && pageType !== 'app') { + return; + } + const options = hookDeps.options[resetIndex]; + resetHook.apply(vueVim, options); + }, + resetHook: () :void => { + hookList.splice(k, 1, resetHook) + } + }; + } + } + } +} +export function resetAndCallPageHook( + router:Router, + enterPath:string, + reset:boolean|undefined = true +):void{ + // Fixe: https://github.com/SilurianYang/uni-simple-router/issues/206 + const pathInfo = enterPath.trim().match(/^(\/?[^\?\s]+)(\?[\s\S]*$)?$/); + if (pathInfo == null) { + throw new Error(`还原hook失败。请检查 【${enterPath}】 路径是否正确。`); + } + enterPath = pathInfo[1]; + const proxyHookDeps = router.proxyHookDeps; + const resetHooksArray = proxyHookDeps.resetIndex + for (let i = 0; i < resetHooksArray.length; i++) { + const index = resetHooksArray[i]; + const {callHook} = proxyHookDeps.hooks[index]; + callHook(enterPath); + } + if (reset) { + resetPageHook(router); + } +} +export function resetPageHook( + router:Router +) { + const proxyHookDeps = router.proxyHookDeps; + for (const [, {resetHook}] of Object.entries(proxyHookDeps.hooks)) { + resetHook(); + } +} diff --git a/node_modules/uni-simple-router/src/public/query.ts b/node_modules/uni-simple-router/src/public/query.ts new file mode 100644 index 0000000..a0354fa --- /dev/null +++ b/node_modules/uni-simple-router/src/public/query.ts @@ -0,0 +1,200 @@ +import { + objectAny, + Router, + routesMapRule, + RoutesRule, + totalNextRoute +} from '../options/base'; +import { + getDataType, + urlToJson, + routesForMapRoute, + getRoutePath, + assertDeepObject, + copyData, + getWildcardRule, + deepDecodeQuery +} from '../helpers/utils' +import {ERRORHOOK} from './hooks' +import {warn} from '../helpers/warn' + +const encodeReserveRE = /[!'()*]/g +const encodeReserveReplacer = (c:string) => '%' + c.charCodeAt(0).toString(16) +const commaRE = /%2C/g + +const encode = (str:string) => + encodeURIComponent(str) + .replace(encodeReserveRE, encodeReserveReplacer) + .replace(commaRE, ',') + +export function queryPageToMap( + toRule:string|totalNextRoute, + router:Router +) :{ + rule:totalNextRoute; + route:RoutesRule, + query:objectAny +} { + let query:objectAny = {}; + let route:RoutesRule|string = ''; + let successCb = (toRule as totalNextRoute).success; + let failCb = (toRule as totalNextRoute).fail; + if (getDataType(toRule) === '[object Object]') { + const objNavRule = (toRule as totalNextRoute); + if (objNavRule.path != null) { + const {path, query: newQuery} = urlToJson(objNavRule.path); + route = routesForMapRoute(router, path, ['finallyPathList', 'pathMap']); + query = {...newQuery, ...((toRule as totalNextRoute).query || {})}; + objNavRule.path = path; + objNavRule.query = query; + delete (toRule as totalNextRoute).params; + } else if (objNavRule.name != null) { + route = (router.routesMap as routesMapRule).nameMap[objNavRule.name]; + if (route == null) { + route = getWildcardRule(router, { type: 2, msg: `命名路由为:${objNavRule.name} 的路由,无法在路由表中找到!`, toRule}); + } else { + query = (toRule as totalNextRoute).params || {}; + delete (toRule as totalNextRoute).query; + } + } else { + route = getWildcardRule(router, { type: 2, msg: `${toRule} 解析失败,请检测当前路由表下是否有包含。`, toRule}); + } + } else { + toRule = urlToJson((toRule as string)) as totalNextRoute; + route = routesForMapRoute(router, toRule.path, ['finallyPathList', 'pathMap']) + query = toRule.query as objectAny; + } + if (router.options.platform === 'h5') { + const {finallyPath} = getRoutePath(route as RoutesRule, router); + if (finallyPath.includes(':') && (toRule as totalNextRoute).name == null) { + ERRORHOOK[0]({ type: 2, msg: `当有设置 alias或者aliasPath 为动态路由时,不允许使用 path 跳转。请使用 name 跳转!`, route}, router) + } + const completeCb = (toRule as totalNextRoute).complete; + const cacheSuccess = (toRule as totalNextRoute).success; + const cacheFail = (toRule as totalNextRoute).fail; + if (getDataType(completeCb) === '[object Function]') { + const publicCb = function(this:any, args:Array, callHook:Function|undefined):void { + if (getDataType(callHook) === '[object Function]') { + (callHook as Function).apply(this, args); + } + (completeCb as Function).apply(this, args); + } + successCb = function(this:any, ...args:any):void{ + publicCb.call(this, args, cacheSuccess); + }; + failCb = function(this:any, ...args:any):void{ + publicCb.call(this, args, cacheFail); + }; + } + } + const rule = (toRule as totalNextRoute); + if (getDataType(rule.success) === '[object Function]') { + rule.success = successCb; + } + if (getDataType(rule.fail) === '[object Function]') { + rule.fail = failCb; + } + return { + rule, + route: (route as RoutesRule), + query + } +} + +export function resolveQuery( + toRule:totalNextRoute, + router:Router +):totalNextRoute { + let queryKey:'params'|'query' = 'query'; + if (toRule.params as objectAny != null) { + queryKey = 'params'; + } + if (toRule.query as objectAny != null) { + queryKey = 'query'; + } + const query = copyData(toRule[queryKey] || {}); + const {resolveQuery: userResolveQuery} = router.options; + if (userResolveQuery) { + const jsonQuery = userResolveQuery(query); + if (getDataType(jsonQuery) !== '[object Object]') { + warn('请按格式返回参数: resolveQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router) + } else { + toRule[queryKey] = jsonQuery; + } + } else { + const deepObj = assertDeepObject(query as objectAny); + if (!deepObj) { + return toRule; + } + const encode = JSON.stringify(query); + toRule[queryKey] = { + query: encode + } + } + return toRule +} + +export function parseQuery( + query:objectAny, + router:Router, +):objectAny { + const {parseQuery: userParseQuery} = router.options; + if (userParseQuery) { + query = userParseQuery(copyData(query)); + if (getDataType(query) !== '[object Object]') { + warn('请按格式返回参数: parseQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router) + } + } else { + if (Reflect.get(query, 'query')) { // 验证一下是不是深度对象 + let deepQuery = Reflect.get(query, 'query'); + if (typeof deepQuery === 'string') { + try { + deepQuery = JSON.parse(deepQuery); + } catch (error) { + warn('尝试解析深度对象失败,按原样输出。' + error, router) + } + } + if (typeof deepQuery === 'object') { + return deepDecodeQuery(deepQuery); + } + } + } + return query +} + +export function stringifyQuery(obj:objectAny): string { + const res = obj + ? Object.keys(obj) + .map(key => { + const val = obj[key] + + if (val === undefined) { + return '' + } + + if (val === null) { + return encode(key) + } + + if (Array.isArray(val)) { + const result:Array = [] + val.forEach(val2 => { + if (val2 === undefined) { + return + } + if (val2 === null) { + result.push(encode(key)) + } else { + result.push(encode(key) + '=' + encode(val2)) + } + }) + return result.join('&') + } + + return encode(key) + '=' + encode(val) + }) + .filter(x => x.length > 0) + .join('&') + : null + return res ? `?${res}` : '' +} diff --git a/node_modules/uni-simple-router/src/public/rewrite.ts b/node_modules/uni-simple-router/src/public/rewrite.ts new file mode 100644 index 0000000..5ab8bb2 --- /dev/null +++ b/node_modules/uni-simple-router/src/public/rewrite.ts @@ -0,0 +1,158 @@ +import { + uniNavApiRule, + reNavMethodRule, + reNotNavMethodRule, + Router, + rewriteMethodToggle, + uniBackRule, + uniBackApiRule, + navtoRule, + totalNextRoute, + originMixins, + objectAny +} from '../options/base' + +import { + routesForMapRoute, + getRoutePath, + getDataType, + notDeepClearNull, + resolveAbsolutePath, + getUniCachePage, + timeOut +} from '../helpers/utils' + +import { + warn +} from '../helpers/warn' + +import {uniOriginJump} from './uniOrigin' + +const rewrite: Array = [ + 'navigateTo', + 'redirectTo', + 'reLaunch', + 'switchTab', + 'navigateBack' +]; + +export function rewriteMethod( + router:Router +): void { + if (router.options.keepUniOriginNav === false) { + rewrite.forEach(name => { + const oldMethod: Function = uni[name]; + uni[name] = function( + params:originMixins|{from:string}|navtoRule, + originCall:boolean = false, + callOkCb?:Function, + forceNav?:boolean + ):void { + if (originCall) { + uniOriginJump(router, oldMethod, name, params as originMixins, callOkCb, forceNav) + } else { + if (router.options.platform === 'app-plus') { + if (Object.keys(router.appMain).length === 0) { + router.appMain = { + NAVTYPE: name, + path: (params as uniNavApiRule).url + } + } + } + callRouterMethod(params as uniNavApiRule, name, router); + } + }; + }) + } +} +function callRouterMethod( + option: uniNavApiRule|uniBackRule|uniBackApiRule, + funName:reNavMethodRule|reNotNavMethodRule, + router:Router +): void { + if (router.options.platform === 'app-plus') { + let openType = null; + if (option) { + openType = (option as uniNavApiRule).openType; + } + if (openType != null && openType === 'appLaunch') { + funName = 'reLaunch' + } + } + if (funName === 'reLaunch' && JSON.stringify(option) === '{"url":"/"}') { + warn( + `uni-app 原生方法:reLaunch({url:'/'}) 默认被重写啦!你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch({url:'/?xxx=xxx'})`, + router, + true + ); + funName = 'navigateBack'; + option = { + from: 'backbutton' + } + } + if (funName === 'navigateBack') { + let level:number = 1; + if (option == null) { + option = {delta: 1}; + } + if (getDataType((option as uniBackApiRule).delta) === '[object Number]') { + level = ((option as uniBackApiRule).delta as number); + } + router.back(level, (option as uniBackRule|uniBackApiRule)); + } else { + const routerMethodName = rewriteMethodToggle[(funName as reNavMethodRule)] + let path = (option as uniNavApiRule).url; + if (!path.startsWith('/')) { + const absolutePath = resolveAbsolutePath(path, router); + path = absolutePath; + (option as uniNavApiRule).url = absolutePath; + } + if (funName === 'switchTab') { + const route = routesForMapRoute(router, path, ['pathMap', 'finallyPathList']) + const {finallyPath} = getRoutePath(route, router); + if (getDataType(finallyPath) === '[object Array]') { + warn( + `uni-app 原生方法跳转路径为:${path}。此路为是tab页面时,不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!`, + router, + true + ); + } + if ((finallyPath as string) === '*') { + warn( + `uni-app 原生方法跳转路径为:${path}。在路由表中找不到相关路由表!当然你可以通过通配符*解决!`, + router, + true + ); + } + // Fixe h5 端无法触发 onTabItemTap hook 2021年6月3日17:26:47 + if (router.options.platform === 'h5') { + const {success: userSuccess} = option as uniNavApiRule; + (option as uniNavApiRule).success = (...args:Array) => { + userSuccess?.apply(null, args); + timeOut(150).then(() => { + const cbArgs = (option as uniNavApiRule).detail || {}; + if (Object.keys(cbArgs).length > 0 && Reflect.has(cbArgs, 'index')) { + const cachePage = getUniCachePage(0); + if (Object.keys(cachePage).length === 0) { + return false + } + const page = cachePage as objectAny; + const hooks = page.$options.onTabItemTap; + if (hooks) { + for (let j = 0; j < hooks.length; j++) { + hooks[j].call(page, cbArgs) + } + } + } + }); + } + } + path = (finallyPath as string); + } + const {events, success, fail, complete, animationType, animationDuration} = option as uniNavApiRule; + const jumpOptions:totalNextRoute = {path, events, success, fail, complete, animationDuration, animationType}; + router[routerMethodName]( + notDeepClearNull(jumpOptions) + ) + } +} diff --git a/node_modules/uni-simple-router/src/public/router.ts b/node_modules/uni-simple-router/src/public/router.ts new file mode 100644 index 0000000..220d96a --- /dev/null +++ b/node_modules/uni-simple-router/src/public/router.ts @@ -0,0 +1,129 @@ +import {PromiseResolve, Router, uniBackApiRule, uniBackRule} from '../options/base'; +import {InstantiateConfig, LifeCycleConfig} from '../options/config'; +import { lifeCycle, proxyHookDeps} from '../helpers/config'; +import {assertNewOptions, def, getDataType} from '../helpers/utils'; +import {registerRouterHooks, registerEachHooks} from '../helpers/lifeCycle'; +import {initMixins} from '../helpers/mixins' +import {lockNavjump, forceGuardEach, createRoute} from '../public/methods' +import {rewriteMethod} from '../public/rewrite' + +let AppReadyResolve:PromiseResolve = () => {}; +const AppReady:Promise = new Promise(resolve => (AppReadyResolve = resolve)); + +function createRouter(params: InstantiateConfig):Router { + const options = assertNewOptions(params); + const router:Router = { + options, + mount: [], + Vue: null, + proxyHookDeps: proxyHookDeps, + appMain: {}, + enterPath: '', + $route: null, + $lockStatus: false, + routesMap: {}, + lifeCycle: registerRouterHooks(lifeCycle, options), + push(to) { + lockNavjump(to, router, 'push'); + }, + replace(to) { + lockNavjump(to, router, 'replace'); + }, + replaceAll(to) { + lockNavjump(to, router, 'replaceAll'); + }, + pushTab(to) { + lockNavjump(to, router, 'pushTab'); + }, + back(level = 1, animation) { + if (getDataType(animation) !== '[object Object]') { + const backRule:uniBackRule = { + from: 'navigateBack' + } + animation = backRule; + } else { + if (!Reflect.has((animation as uniBackRule | uniBackApiRule), 'from')) { + animation = { + ...animation, + from: 'navigateBack' + }; + } + } + lockNavjump(level + '', router, 'back', undefined, animation) + }, + forceGuardEach(navType, forceNav) { + forceGuardEach(router, navType, forceNav) + }, + beforeEach(userGuard):void { + registerEachHooks(router, 'beforeHooks', userGuard); + }, + afterEach(userGuard):void { + registerEachHooks(router, 'afterHooks', userGuard); + }, + install(Vue:any):void{ + router.Vue = Vue; + rewriteMethod(this); + initMixins(Vue, this); + Object.defineProperty(Vue.prototype, '$Router', { + get() { + const actualData = router; + + Object.defineProperty(this, '$Router', { + value: actualData, + writable: false, + configurable: false, + enumerable: false + }); + + return Object.seal(actualData); + } + }); + Object.defineProperty(Vue.prototype, '$Route', { + get() { + return createRoute(router); + } + }); + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254 + Object.defineProperty(Vue.prototype, '$AppReady', { + get() { + if (router.options.platform === 'h5') { + return Promise.resolve(); + } + return AppReady; + }, + set(value:boolean) { + if (value === true) { + AppReadyResolve(); + } + } + }); + } + } + def(router, 'currentRoute', () => createRoute(router)); + + router.beforeEach((to, from, next) => next()); + router.afterEach(() => {}); + return router; +} + +function RouterMount(Vim:any, router:Router, el:string | undefined = '#app') :void|never { + if (getDataType>(router.mount) === '[object Array]') { + router.mount.push({ + app: Vim, + el + }) + } else { + throw new Error(`挂载路由失败,router.app 应该为数组类型。当前类型:${typeof router.mount}`); + } + if (router.options.platform === 'h5') { + const vueRouter = (router.$route as any); + vueRouter.replace({ + path: vueRouter.currentRoute.fullPath + }); + } // 其他端目前不需要做啥 +} + +export { + RouterMount, + createRouter +} diff --git a/node_modules/uni-simple-router/src/public/uniOrigin.ts b/node_modules/uni-simple-router/src/public/uniOrigin.ts new file mode 100644 index 0000000..25c975f --- /dev/null +++ b/node_modules/uni-simple-router/src/public/uniOrigin.ts @@ -0,0 +1,112 @@ +import { originMixins, reNavMethodRule, reNotNavMethodRule, Router, startAnimationRule, uniNavApiRule } from '../options/base'; +import { stringifyQuery } from './query'; +import {notDeepClearNull, timeOut} from '../helpers/utils' +import { mpPlatformReg } from '../helpers/config'; +import { resetAndCallPageHook, resetPageHook } from './page'; + +let routerNavCount:number = 0; +let lastNavType:reNavMethodRule|reNotNavMethodRule = 'reLaunch' + +export function uniOriginJump( + router:Router, + originMethod:Function, + funName:reNavMethodRule|reNotNavMethodRule, + options: originMixins, + callOkCb?:Function, + forceNav?:boolean +):void { + const {complete, ...originRule} = formatOriginURLQuery(router, options, funName); + const platform = router.options.platform; + if (forceNav != null && forceNav === false) { + if (routerNavCount === 0) { + routerNavCount++ + if (platform !== 'h5') { + resetAndCallPageHook(router, originRule.url) // 还原及执行app.vue及首页下已经重写后的生命周期 + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254 + // 在小程序端 next 直接放行会执行这个 + router.Vue.prototype.$AppReady = true; + } + } + complete && complete.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'}); + callOkCb && callOkCb.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'}) + } else { + if (routerNavCount === 0) { + if (platform === 'app-plus') { + resetAndCallPageHook(router, originRule.url) // 还原及执行app.vue下已经重写后的生命周期 + } else { + if (new RegExp(mpPlatformReg, 'g').test(platform)) { + // 其他就是在小程序下,首次启动发生跳转会走这里 + // 我们先将app.vue的生命周期执行 + resetAndCallPageHook(router, originRule.url, false) + } + } + } + originMethod({ + ...originRule, + from: options.BACKTYPE, + complete: async function(...args:Array) { + if (routerNavCount === 0) { + routerNavCount++ + + if (platform !== 'h5') { + if (new RegExp(mpPlatformReg, 'g').test(platform)) { // 跳转完成后小程序下还原生命周期 + resetPageHook(router); + } + // 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254 + // 在小程序端 第一次 next 做跳转 会触发这个 、在app端首次必定会触发这个 + router.Vue.prototype.$AppReady = true; + + if (platform === 'app-plus') { + const waitPage = plus.nativeObj.View.getViewById('router-loadding'); + waitPage && waitPage.close(); + const launchedHook = router.options.APP?.launchedHook; + launchedHook && launchedHook(); + } + } + } + let time:number = 0; + if (new RegExp(mpPlatformReg, 'g').test(platform)) { + time = (router.options.applet?.animationDuration) as number + } else if (platform === 'app-plus') { + if (funName === 'navigateBack' && lastNavType === 'navigateTo') { + time = (router.options.APP?.animation?.animationDuration) as number + } + } + if (funName === 'navigateTo' || funName === 'navigateBack') { + if (time !== 0) { + await timeOut(time); + } + } + lastNavType = funName; + complete && complete.apply(null, args); + callOkCb && callOkCb.apply(null, args) + } + }); + } +} +export function formatOriginURLQuery( + router:Router, + options:uniNavApiRule, + funName:reNavMethodRule|reNotNavMethodRule +):uniNavApiRule { + const {url, path, query, animationType, animationDuration, events, success, fail, complete, delta, animation} = options; + const strQuery = stringifyQuery(query || {}); + const queryURL = strQuery === '' ? (path || url) : (path || url) + strQuery; + let animationRule:startAnimationRule = {}; + if (router.options.platform === 'app-plus') { + if (funName !== 'navigateBack') { + animationRule = router.options.APP?.animation || {}; + animationRule = {...animationRule, ...animation || {}}; + } + } + return notDeepClearNull({ + delta, + url: queryURL, + animationType: animationType || animationRule.animationType, + animationDuration: animationDuration || animationRule.animationDuration, + events, + success, + fail, + complete + }) +} diff --git a/node_modules/uni-simple-router/test/path-to-regexp.spec.ts b/node_modules/uni-simple-router/test/path-to-regexp.spec.ts new file mode 100644 index 0000000..c8f7c2f --- /dev/null +++ b/node_modules/uni-simple-router/test/path-to-regexp.spec.ts @@ -0,0 +1,70 @@ +import {createRouter, routesMapKeysRule} from '../src/index'; + +import {routesForMapRoute} from '../src/helpers/utils'; + +const routes = [ + {path: '/pages/login/login', name: 'login', aliasPath: '/'}, + {path: '/pages/page2/page2', name: 'page2', aliasPath: '/page2/:id'}, + {path: '/pages/page3/page3', aliasPath: '/:name/page3/:id'}, + {path: '/pages/animation/animation', aliasPath: '/an-(\\d+)-on'}, + {path: '/static/1/1', aliasPath: '/static/(.*)'}, + {path: '/dynamic/1/1', aliasPath: '/dynamic-*'}, + {path: '/dynamic/3/3', aliasPath: '/dynamic3'}, + {path: '*'} +]; + +const router = createRouter({ + platform: 'app-plus', + keepUniOriginNav: true, + routes, +}); + +const Vue = function () {}; +Vue.mixin = () => {}; + +router.install(Vue); + +const rules: routesMapKeysRule[] = ['finallyPathMap', 'pathMap']; + +it('别名路径匹配',()=>{ + const toRoute1 = routesForMapRoute(router, '/dynamic3', rules); + expect(toRoute1).toEqual(routes[6]); + + const toRoute2 = routesForMapRoute(router, '/dynamic/3/3', rules); + expect(toRoute2).toEqual(routes[6]); +}) + +it('全局匹配', () => { + const toRoute1 = routesForMapRoute(router, '/pages/login/login', rules); + expect(toRoute1).toEqual(routes[0]); + + const toRoute2 = routesForMapRoute(router,'/pages/login/login?id=666',rules); + expect(toRoute2).toEqual(routes[0]); + + const toRoute3 = routesForMapRoute(router, '/page2/6666', rules); + expect(toRoute3).toEqual(routes[1]); + + const toRoute4 = routesForMapRoute(router, '/page2/6666?id=555', rules); + expect(toRoute4).toEqual(routes[1]); + + const toRoute5 = routesForMapRoute(router, '/pages/page3/page3', rules); + expect(toRoute5).toEqual(routes[2]); + + const toRoute6 = routesForMapRoute(router, '/test/page3/123', rules); + expect(toRoute6).toEqual(routes[2]); + + const toRoute7 = routesForMapRoute(router, '/an-123-on', rules); + expect(toRoute7).toEqual(routes[3]); + + const toRoute8 = routesForMapRoute(router, '/static/aaa/bbb?id=1444&name=999', rules); + expect(toRoute8).toEqual(routes[4]); + + const toRoute9 = routesForMapRoute(router, '/dynamic-6666-5555', rules); + expect(toRoute9).toEqual(routes[5]); + + const toRoute10 = routesForMapRoute(router, '/aaaaaa', rules); + expect(toRoute10).toEqual(routes[7]); + + const toRoute11 = routesForMapRoute(router, '---48848--14545', rules); + expect(toRoute11).toEqual(routes[7]); +}); diff --git a/node_modules/uni-simple-router/test/query-toggle.spec.ts b/node_modules/uni-simple-router/test/query-toggle.spec.ts new file mode 100644 index 0000000..91b09d8 --- /dev/null +++ b/node_modules/uni-simple-router/test/query-toggle.spec.ts @@ -0,0 +1,83 @@ +import {deepDecodeQuery} from '../src/helpers/utils'; + + +it('编码回转',()=>{ + const query={ + str:'%E7%9A%84%E6%8C%A5%E6%B4%92U%E7%9B%BE%E5%A5%BD%E6%92%92%E7%AC%AC%E4%B8%89%E5%A4%A7%E5%8E%A6%E5%8F%91%E7%9A%84%E6%92%92321312%2a%EF%BC%88%EF%BF%A5%23%254' + } + const result = deepDecodeQuery(query); + expect(JSON.stringify(result)).toEqual(JSON.stringify({ + str:'的挥洒U盾好撒第三大厦发的撒321312*(¥#%4' + })) +}) + +it('一些乱码字符',()=>{ + const query={ + str:`~!@#$%^&*()_+-,./|][]` + } + const result = deepDecodeQuery(query); + expect(JSON.stringify(result)).toEqual(JSON.stringify({ + str:`~!@#$%^&*()_+-,./|][]` + })) +}) + +it('单个加密参数',()=>{ + const query={ + name:'%7B%22status%22%3Atrue%2C%22list%22%3A%5B%7B%22id%22%3A1%7D%5D%7D' + } + const result = deepDecodeQuery(query); + expect(JSON.stringify(result)).toEqual(JSON.stringify({ + name:{ + status:true, + list:[ + { + id:1 + }, + ] + } + })); +}) + +it('单个普通参数',()=>{ + const query={ + name:'hhyang', + ages:22, + open:true + } + const result = deepDecodeQuery(query); + + expect(JSON.stringify(result)).toEqual(JSON.stringify(query)); +}) + +it('深度参数加混乱',()=>{ + const query={ + list:[ + 1,'2',true,encodeURIComponent(JSON.stringify({name:111})),{ + name:'hhyang', + strObj:encodeURIComponent(JSON.stringify({name:222})) + } + ], + obj:{ + strObj2:encodeURIComponent(JSON.stringify({name:333})), + number:1, + boolean:false, + }, + str4:encodeURIComponent(JSON.stringify({name:444})) + } + const result = deepDecodeQuery(query); + + expect(JSON.stringify(result)).toEqual(JSON.stringify({ + list:[ + 1,'2',true,{name:111},{ + name:'hhyang', + strObj:{name:222} + } + ], + obj:{ + strObj2:{name:333}, + number:1, + boolean:false, + }, + str4:{name:444} + })); +}) \ No newline at end of file diff --git a/node_modules/uni-simple-router/tsconfig.json b/node_modules/uni-simple-router/tsconfig.json new file mode 100644 index 0000000..0a076f1 --- /dev/null +++ b/node_modules/uni-simple-router/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "CommonJS", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "lib": ["ES2015", "DOM"], + "outDir": "dist/src", + "declaration": true, + "declarationMap": false, + "rootDir": "./src", + "baseUrl": ".", + "paths": {} + }, + "include": ["./src/global.d.ts", "./src/*"], + "exclude": ["node_modules", "**/*.spec.ts"] +} diff --git a/node_modules/uni-simple-router/webpack/webpack.common.js b/node_modules/uni-simple-router/webpack/webpack.common.js new file mode 100644 index 0000000..344fc05 --- /dev/null +++ b/node_modules/uni-simple-router/webpack/webpack.common.js @@ -0,0 +1,41 @@ +const {resolve} = require('path'); +const CopyPlugin = require('copy-webpack-plugin'); +const webpack =require('webpack'); + +module.exports = { + entry: './src/index.ts', + output: { + library: 'Router', + libraryTarget: 'umd', + }, + resolve: { + extensions: ['.tsx', '.ts', 'd.ts', '.js', '.json'], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: [ + { + loader: 'ts-loader', + }, + ], + exclude: /node_modules/, + }, + ], + }, + plugins: [ + new CopyPlugin([ + { + force: true, + from: resolve(__dirname, '../src/component'), + to: resolve(__dirname, '../dist'), + }, + ]), + new webpack.DefinePlugin({ + $npm_package_name: webpack.DefinePlugin.runtimeValue(() => { + return JSON.stringify(process.env.npm_package_name.toLocaleUpperCase()) + }, true ) + }) + ], +}; diff --git a/node_modules/uni-simple-router/webpack/webpack.dev.js b/node_modules/uni-simple-router/webpack/webpack.dev.js new file mode 100644 index 0000000..79b1374 --- /dev/null +++ b/node_modules/uni-simple-router/webpack/webpack.dev.js @@ -0,0 +1,22 @@ +const {merge} = require("webpack-merge"); +const {resolve} = require('path'); +const common = require("./webpack.common.js"); +const CopyPlugin = require('copy-webpack-plugin'); + +const output=resolve(__dirname, '../examples/uni-simple-router2.0/dist'); + +module.exports = merge(common, { + mode: 'development', + devtool: 'source-map', + output: { + path:output , + filename: 'uni-simple-router.js', + }, + plugins: [ + new CopyPlugin([{ + force: true, + from: resolve(__dirname, '../src/component'), + to: output, + }]), + ] +}); \ No newline at end of file diff --git a/node_modules/uni-simple-router/webpack/webpack.prod.js b/node_modules/uni-simple-router/webpack/webpack.prod.js new file mode 100644 index 0000000..4d65e8f --- /dev/null +++ b/node_modules/uni-simple-router/webpack/webpack.prod.js @@ -0,0 +1,19 @@ +const {resolve} = require('path'); +const {merge} = require("webpack-merge"); +const common = require("./webpack.common.js"); +const rimraf = require('rimraf'); + + +function resolvePath(dir) { + return resolve(__dirname, '../', dir) +} + +rimraf('dist', () => {}); + +module.exports = merge(common, { + mode: "production", + output: { + path: resolvePath('dist'), + filename: 'uni-simple-router.js', + }, +}) \ No newline at end of file diff --git a/node_modules/uview-ui/LICENSE b/node_modules/uview-ui/LICENSE new file mode 100644 index 0000000..7456959 --- /dev/null +++ b/node_modules/uview-ui/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 www.uviewui.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/node_modules/uview-ui/README.md b/node_modules/uview-ui/README.md new file mode 100644 index 0000000..c930e03 --- /dev/null +++ b/node_modules/uview-ui/README.md @@ -0,0 +1,106 @@ +

+ logo +

+

uView

+

多平台快速开发的UI框架

+ + +## 说明 + +uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 + +## 特性 + +- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序 +- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用 +- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨 +- 众多的常用页面和布局,让您专注逻辑,事半功倍 +- 详尽的文档支持,现代化的演示效果 +- 按需引入,精简打包体积 + + +## 安装 + +```bash +# npm方式安装 +npm i uview-ui +``` + +## 快速上手 + +1. `main.js`引入uView库 +```js +// main.js +import uView from 'uview-ui'; +Vue.use(uView); +``` + +2. `App.vue`引入基础样式(注意style标签需声明scss属性支持) +```css +/* App.vue */ + +``` + +3. `uni.scss`引入全局scss变量文件 +```css +/* uni.scss */ +@import "uview-ui/theme.scss"; +``` + +4. `pages.json`配置easycom规则(按需引入) + +```js +// pages.json +{ + "easycom": { + // npm安装的方式不需要前面的"@/",下载安装的方式需要"@/" + // npm安装方式 + "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" + // 下载安装方式 + // "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" + }, + // 此为本身已有的内容 + "pages": [ + // ...... + ] +} +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 使用方法 +配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 + +```html + +``` + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 链接 + +- [官方文档](https://uviewui.com/) +- [更新日志](https://uviewui.com/components/changelog.html) +- [升级指南](https://uviewui.com/components/changelog.html) +- [关于我们](https://uviewui.com/cooperation/about.html) + +## 预览 + +您可以通过**微信**扫码,查看最佳的演示效果。 +
+
+ + + +## 版权信息 +uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 diff --git a/node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue b/node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue new file mode 100644 index 0000000..bfeb4cc --- /dev/null +++ b/node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-alert-tips/u-alert-tips.vue b/node_modules/uview-ui/components/u-alert-tips/u-alert-tips.vue new file mode 100644 index 0000000..640d99a --- /dev/null +++ b/node_modules/uview-ui/components/u-alert-tips/u-alert-tips.vue @@ -0,0 +1,256 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue b/node_modules/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue new file mode 100644 index 0000000..b249015 --- /dev/null +++ b/node_modules/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-avatar-cropper/weCropper.js b/node_modules/uview-ui/components/u-avatar-cropper/weCropper.js new file mode 100644 index 0000000..7402f8d --- /dev/null +++ b/node_modules/uview-ui/components/u-avatar-cropper/weCropper.js @@ -0,0 +1,1265 @@ +/** + * we-cropper v1.3.9 + * (c) 2020 dlhandsome + * @license MIT + */ +(function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.WeCropper = factory()); +}(this, (function() { + 'use strict'; + + var device = void 0; + var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended']; + + function firstLetterUpper(str) { + return str.charAt(0).toUpperCase() + str.slice(1) + } + + function setTouchState(instance) { + var arg = [], + len = arguments.length - 1; + while (len-- > 0) arg[len] = arguments[len + 1]; + + TOUCH_STATE.forEach(function(key, i) { + if (arg[i] !== undefined) { + instance[key] = arg[i]; + } + }); + } + + function validator(instance, o) { + Object.defineProperties(instance, o); + } + + function getDevice() { + if (!device) { + device = uni.getSystemInfoSync(); + } + return device + } + + var tmp = {}; + + var ref = getDevice(); + var pixelRatio = ref.pixelRatio; + + var DEFAULT = { + id: { + default: 'cropper', + get: function get() { + return tmp.id + }, + set: function set(value) { + if (typeof(value) !== 'string') { + console.error(("id:" + value + " is invalid")); + } + tmp.id = value; + } + }, + width: { + default: 750, + get: function get() { + return tmp.width + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("width:" + value + " is invalid")); + } + tmp.width = value; + } + }, + height: { + default: 750, + get: function get() { + return tmp.height + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("height:" + value + " is invalid")); + } + tmp.height = value; + } + }, + pixelRatio: { + default: pixelRatio, + get: function get() { + return tmp.pixelRatio + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("pixelRatio:" + value + " is invalid")); + } + tmp.pixelRatio = value; + } + }, + scale: { + default: 2.5, + get: function get() { + return tmp.scale + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("scale:" + value + " is invalid")); + } + tmp.scale = value; + } + }, + zoom: { + default: 5, + get: function get() { + return tmp.zoom + }, + set: function set(value) { + if (typeof(value) !== 'number') { + console.error(("zoom:" + value + " is invalid")); + } else if (value < 0 || value > 10) { + console.error("zoom should be ranged in 0 ~ 10"); + } + tmp.zoom = value; + } + }, + src: { + default: '', + get: function get() { + return tmp.src + }, + set: function set(value) { + if (typeof(value) !== 'string') { + console.error(("src:" + value + " is invalid")); + } + tmp.src = value; + } + }, + cut: { + default: {}, + get: function get() { + return tmp.cut + }, + set: function set(value) { + if (typeof(value) !== 'object') { + console.error(("cut:" + value + " is invalid")); + } + tmp.cut = value; + } + }, + boundStyle: { + default: {}, + get: function get() { + return tmp.boundStyle + }, + set: function set(value) { + if (typeof(value) !== 'object') { + console.error(("boundStyle:" + value + " is invalid")); + } + tmp.boundStyle = value; + } + }, + onReady: { + default: null, + get: function get() { + return tmp.ready + }, + set: function set(value) { + tmp.ready = value; + } + }, + onBeforeImageLoad: { + default: null, + get: function get() { + return tmp.beforeImageLoad + }, + set: function set(value) { + tmp.beforeImageLoad = value; + } + }, + onImageLoad: { + default: null, + get: function get() { + return tmp.imageLoad + }, + set: function set(value) { + tmp.imageLoad = value; + } + }, + onBeforeDraw: { + default: null, + get: function get() { + return tmp.beforeDraw + }, + set: function set(value) { + tmp.beforeDraw = value; + } + } + }; + + var ref$1 = getDevice(); + var windowWidth = ref$1.windowWidth; + + function prepare() { + var self = this; + + // v1.4.0 版本中将不再自动绑定we-cropper实例 + self.attachPage = function() { + var pages = getCurrentPages(); + // 获取到当前page上下文 + var pageContext = pages[pages.length - 1]; + // 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问 + Object.defineProperty(pageContext, 'wecropper', { + get: function get() { + console.warn( + 'Instance will not be automatically bound to the page after v1.4.0\n\n' + + 'Please use a custom instance name instead\n\n' + + 'Example: \n' + + 'this.mycropper = new WeCropper(options)\n\n' + + '// ...\n' + + 'this.mycropper.getCropperImage()' + ); + return self + }, + configurable: true + }); + }; + + self.createCtx = function() { + var id = self.id; + var targetId = self.targetId; + + if (id) { + self.ctx = self.ctx || uni.createCanvasContext(id); + self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId); + } else { + console.error("constructor: create canvas context failed, 'id' must be valuable"); + } + }; + + self.deviceRadio = windowWidth / 750; + } + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== + 'undefined' ? self : {}; + + + + + + function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + + var tools = createCommonjsModule(function(module, exports) { + /** + * String type check + */ + exports.isStr = function(v) { + return typeof v === 'string'; + }; + /** + * Number type check + */ + exports.isNum = function(v) { + return typeof v === 'number'; + }; + /** + * Array type check + */ + exports.isArr = Array.isArray; + /** + * undefined type check + */ + exports.isUndef = function(v) { + return v === undefined; + }; + + exports.isTrue = function(v) { + return v === true; + }; + + exports.isFalse = function(v) { + return v === false; + }; + /** + * Function type check + */ + exports.isFunc = function(v) { + return typeof v === 'function'; + }; + /** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ + exports.isObj = exports.isObject = function(obj) { + return obj !== null && typeof obj === 'object' + }; + + /** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ + var _toString = Object.prototype.toString; + exports.isPlainObject = function(obj) { + return _toString.call(obj) === '[object Object]' + }; + + /** + * Check whether the object has the property. + */ + var hasOwnProperty = Object.prototype.hasOwnProperty; + exports.hasOwn = function(obj, key) { + return hasOwnProperty.call(obj, key) + }; + + /** + * Perform no operation. + * Stubbing args to make Flow happy without leaving useless transpiled code + * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) + */ + exports.noop = function(a, b, c) {}; + + /** + * Check if val is a valid array index. + */ + exports.isValidArrayIndex = function(val) { + var n = parseFloat(String(val)); + return n >= 0 && Math.floor(n) === n && isFinite(val) + }; + }); + + var tools_7 = tools.isFunc; + var tools_10 = tools.isPlainObject; + + var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad']; + + function observer() { + var self = this; + + self.on = function(event, fn) { + if (EVENT_TYPE.indexOf(event) > -1) { + if (tools_7(fn)) { + event === 'ready' ? + fn(self) : + self[("on" + (firstLetterUpper(event)))] = fn; + } + } else { + console.error(("event: " + event + " is invalid")); + } + return self + }; + } + + function wxPromise(fn) { + return function(obj) { + var args = [], + len = arguments.length - 1; + while (len-- > 0) args[len] = arguments[len + 1]; + + if (obj === void 0) obj = {}; + return new Promise(function(resolve, reject) { + obj.success = function(res) { + resolve(res); + }; + obj.fail = function(err) { + reject(err); + }; + fn.apply(void 0, [obj].concat(args)); + }) + } + } + + function draw(ctx, reserve) { + if (reserve === void 0) reserve = false; + + return new Promise(function(resolve) { + ctx.draw(reserve, resolve); + }) + } + + var getImageInfo = wxPromise(uni.getImageInfo); + + var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath); + + var base64 = createCommonjsModule(function(module, exports) { + /*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */ + (function(root) { + + // Detect free variables `exports`. + var freeExports = 'object' == 'object' && exports; + + // Detect free variable `module`. + var freeModule = 'object' == 'object' && module && + module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, and use + // it as `root`. + var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var InvalidCharacterError = function(message) { + this.message = message; + }; + InvalidCharacterError.prototype = new Error; + InvalidCharacterError.prototype.name = 'InvalidCharacterError'; + + var error = function(message) { + // Note: the error messages used throughout this file match those used by + // the native `atob`/`btoa` implementation in Chromium. + throw new InvalidCharacterError(message); + }; + + var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + // http://whatwg.org/html/common-microsyntaxes.html#space-character + var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g; + + // `decode` is designed to be fully compatible with `atob` as described in the + // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob + // The optimized base64-decoding algorithm used is based on @atk’s excellent + // implementation. https://gist.github.com/atk/1020396 + var decode = function(input) { + input = String(input) + .replace(REGEX_SPACE_CHARACTERS, ''); + var length = input.length; + if (length % 4 == 0) { + input = input.replace(/==?$/, ''); + length = input.length; + } + if ( + length % 4 == 1 || + // http://whatwg.org/C#alphanumeric-ascii-characters + /[^+a-zA-Z0-9/]/.test(input) + ) { + error( + 'Invalid character: the string to be decoded is not correctly encoded.' + ); + } + var bitCounter = 0; + var bitStorage; + var buffer; + var output = ''; + var position = -1; + while (++position < length) { + buffer = TABLE.indexOf(input.charAt(position)); + bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer; + // Unless this is the first of a group of 4 characters… + if (bitCounter++ % 4) { + // …convert the first 8 bits to a single ASCII character. + output += String.fromCharCode( + 0xFF & bitStorage >> (-2 * bitCounter & 6) + ); + } + } + return output; + }; + + // `encode` is designed to be fully compatible with `btoa` as described in the + // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa + var encode = function(input) { + input = String(input); + if (/[^\0-\xFF]/.test(input)) { + // Note: no need to special-case astral symbols here, as surrogates are + // matched, and the input is supposed to only contain ASCII anyway. + error( + 'The string to be encoded contains characters outside of the ' + + 'Latin1 range.' + ); + } + var padding = input.length % 3; + var output = ''; + var position = -1; + var a; + var b; + var c; + var buffer; + // Make sure any padding is handled outside of the loop. + var length = input.length - padding; + + while (++position < length) { + // Read three bytes, i.e. 24 bits. + a = input.charCodeAt(position) << 16; + b = input.charCodeAt(++position) << 8; + c = input.charCodeAt(++position); + buffer = a + b + c; + // Turn the 24 bits into four chunks of 6 bits each, and append the + // matching character for each of them to the output. + output += ( + TABLE.charAt(buffer >> 18 & 0x3F) + + TABLE.charAt(buffer >> 12 & 0x3F) + + TABLE.charAt(buffer >> 6 & 0x3F) + + TABLE.charAt(buffer & 0x3F) + ); + } + + if (padding == 2) { + a = input.charCodeAt(position) << 8; + b = input.charCodeAt(++position); + buffer = a + b; + output += ( + TABLE.charAt(buffer >> 10) + + TABLE.charAt((buffer >> 4) & 0x3F) + + TABLE.charAt((buffer << 2) & 0x3F) + + '=' + ); + } else if (padding == 1) { + buffer = input.charCodeAt(position); + output += ( + TABLE.charAt(buffer >> 2) + + TABLE.charAt((buffer << 4) & 0x3F) + + '==' + ); + } + + return output; + }; + + var base64 = { + 'encode': encode, + 'decode': decode, + 'version': '0.1.0' + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof undefined == 'function' && + typeof undefined.amd == 'object' && + undefined.amd + ) { + undefined(function() { + return base64; + }); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = base64; + } else { // in Narwhal or RingoJS v0.7.0- + for (var key in base64) { + base64.hasOwnProperty(key) && (freeExports[key] = base64[key]); + } + } + } else { // in Rhino or a web browser + root.base64 = base64; + } + + }(commonjsGlobal)); + }); + + function makeURI(strData, type) { + return 'data:' + type + ';base64,' + strData + } + + function fixType(type) { + type = type.toLowerCase().replace(/jpg/i, 'jpeg'); + var r = type.match(/png|jpeg|bmp|gif/)[0]; + return 'image/' + r + } + + function encodeData(data) { + var str = ''; + if (typeof data === 'string') { + str = data; + } else { + for (var i = 0; i < data.length; i++) { + str += String.fromCharCode(data[i]); + } + } + return base64.encode(str) + } + + /** + * 获取图像区域隐含的像素数据 + * @param canvasId canvas标识 + * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 + * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 + * @param width 将要被提取的图像数据矩形区域的宽度 + * @param height 将要被提取的图像数据矩形区域的高度 + * @param done 完成回调 + */ + function getImageData(canvasId, x, y, width, height, done) { + uni.canvasGetImageData({ + canvasId: canvasId, + x: x, + y: y, + width: width, + height: height, + success: function success(res) { + done(res, null); + }, + fail: function fail(res) { + done(null, res); + } + }); + } + + /** + * 生成bmp格式图片 + * 按照规则生成图片响应头和响应体 + * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData + * @returns {*} base64字符串 + */ + function genBitmapImage(oData) { + // + // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx + // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx + // + var biWidth = oData.width; + var biHeight = oData.height; + var biSizeImage = biWidth * biHeight * 3; + var bfSize = biSizeImage + 54; // total header size = 54 bytes + + // + // typedef struct tagBITMAPFILEHEADER { + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + // } BITMAPFILEHEADER; + // + var BITMAPFILEHEADER = [ + // WORD bfType -- The file type signature; must be "BM" + 0x42, 0x4D, + // DWORD bfSize -- The size, in bytes, of the bitmap file + bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff, + // WORD bfReserved1 -- Reserved; must be zero + 0, 0, + // WORD bfReserved2 -- Reserved; must be zero + 0, 0, + // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits. + 54, 0, 0, 0 + ]; + + // + // typedef struct tagBITMAPINFOHEADER { + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + // } BITMAPINFOHEADER, *PBITMAPINFOHEADER; + // + var BITMAPINFOHEADER = [ + // DWORD biSize -- The number of bytes required by the structure + 40, 0, 0, 0, + // LONG biWidth -- The width of the bitmap, in pixels + biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff, + // LONG biHeight -- The height of the bitmap, in pixels + biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff, + // WORD biPlanes -- The number of planes for the target device. This value must be set to 1 + 1, 0, + // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap + // has a maximum of 2^24 colors (16777216, Truecolor) + 24, 0, + // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed + 0, 0, 0, 0, + // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps + biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff, + // LONG biXPelsPerMeter, unused + 0, 0, 0, 0, + // LONG biYPelsPerMeter, unused + 0, 0, 0, 0, + // DWORD biClrUsed, the number of color indexes of palette, unused + 0, 0, 0, 0, + // DWORD biClrImportant, unused + 0, 0, 0, 0 + ]; + + var iPadding = (4 - ((biWidth * 3) % 4)) % 4; + + var aImgData = oData.data; + + var strPixelData = ''; + var biWidth4 = biWidth << 2; + var y = biHeight; + var fromCharCode = String.fromCharCode; + + do { + var iOffsetY = biWidth4 * (y - 1); + var strPixelRow = ''; + for (var x = 0; x < biWidth; x++) { + var iOffsetX = x << 2; + strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) + + fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) + + fromCharCode(aImgData[iOffsetY + iOffsetX]); + } + + for (var c = 0; c < iPadding; c++) { + strPixelRow += String.fromCharCode(0); + } + + strPixelData += strPixelRow; + } while (--y) + + var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData); + + return strEncoded + } + + /** + * 转换为图片base64 + * @param canvasId canvas标识 + * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 + * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 + * @param width 将要被提取的图像数据矩形区域的宽度 + * @param height 将要被提取的图像数据矩形区域的高度 + * @param type 转换图片类型 + * @param done 完成回调 + */ + function convertToImage(canvasId, x, y, width, height, type, done) { + if (done === void 0) done = function() {}; + + if (type === undefined) { + type = 'png'; + } + type = fixType(type); + if (/bmp/.test(type)) { + getImageData(canvasId, x, y, width, height, function(data, err) { + var strData = genBitmapImage(data); + tools_7(done) && done(makeURI(strData, 'image/' + type), err); + }); + } else { + console.error('暂不支持生成\'' + type + '\'类型的base64图片'); + } + } + + var CanvasToBase64 = { + convertToImage: convertToImage, + // convertToPNG: function (width, height, done) { + // return convertToImage(width, height, 'png', done) + // }, + // convertToJPEG: function (width, height, done) { + // return convertToImage(width, height, 'jpeg', done) + // }, + // convertToGIF: function (width, height, done) { + // return convertToImage(width, height, 'gif', done) + // }, + convertToBMP: function(ref, done) { + if (ref === void 0) ref = {}; + var canvasId = ref.canvasId; + var x = ref.x; + var y = ref.y; + var width = ref.width; + var height = ref.height; + if (done === void 0) done = function() {}; + + return convertToImage(canvasId, x, y, width, height, 'bmp', done) + } + }; + + function methods() { + var self = this; + + var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度 + var boundHeight = self.height; // 裁剪框默认高度,即整个画布高度 + + var id = self.id; + var targetId = self.targetId; + var pixelRatio = self.pixelRatio; + + var ref = self.cut; + var x = ref.x; + if (x === void 0) x = 0; + var y = ref.y; + if (y === void 0) y = 0; + var width = ref.width; + if (width === void 0) width = boundWidth; + var height = ref.height; + if (height === void 0) height = boundHeight; + + self.updateCanvas = function(done) { + if (self.croperTarget) { + // 画布绘制图片 + self.ctx.drawImage( + self.croperTarget, + self.imgLeft, + self.imgTop, + self.scaleWidth, + self.scaleHeight + ); + } + tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self); + + self.setBoundStyle(self.boundStyle); // 设置边界样式 + + self.ctx.draw(false, done); + return self + }; + + self.pushOrigin = self.pushOrign = function(src) { + self.src = src; + + tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self); + + return getImageInfo({ + src: src + }) + .then(function(res) { + var innerAspectRadio = res.width / res.height; + var customAspectRadio = width / height; + + self.croperTarget = res.path; + + if (innerAspectRadio < customAspectRadio) { + self.rectX = x; + self.baseWidth = width; + self.baseHeight = width / innerAspectRadio; + self.rectY = y - Math.abs((height - self.baseHeight) / 2); + } else { + self.rectY = y; + self.baseWidth = height * innerAspectRadio; + self.baseHeight = height; + self.rectX = x - Math.abs((width - self.baseWidth) / 2); + } + + self.imgLeft = self.rectX; + self.imgTop = self.rectY; + self.scaleWidth = self.baseWidth; + self.scaleHeight = self.baseHeight; + + self.update(); + + return new Promise(function(resolve) { + self.updateCanvas(resolve); + }) + }) + .then(function() { + tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self); + }) + }; + + self.removeImage = function() { + self.src = ''; + self.croperTarget = ''; + return draw(self.ctx) + }; + + self.getCropperBase64 = function(done) { + if (done === void 0) done = function() {}; + + CanvasToBase64.convertToBMP({ + canvasId: id, + x: x, + y: y, + width: width, + height: height + }, done); + }; + + self.getCropperImage = function(opt, fn) { + var customOptions = opt; + + var canvasOptions = { + canvasId: id, + x: x, + y: y, + width: width, + height: height + }; + + var task = function() { + return Promise.resolve(); + }; + + if ( + tools_10(customOptions) && + customOptions.original + ) { + // original mode + task = function() { + self.targetCtx.drawImage( + self.croperTarget, + self.imgLeft * pixelRatio, + self.imgTop * pixelRatio, + self.scaleWidth * pixelRatio, + self.scaleHeight * pixelRatio + ); + + canvasOptions = { + canvasId: targetId, + x: x * pixelRatio, + y: y * pixelRatio, + width: width * pixelRatio, + height: height * pixelRatio + }; + + return draw(self.targetCtx) + }; + } + + return task() + .then(function() { + if (tools_10(customOptions)) { + canvasOptions = Object.assign({}, canvasOptions, customOptions); + } + + if (tools_7(customOptions)) { + fn = customOptions; + } + + var arg = canvasOptions.componentContext ? + [canvasOptions, canvasOptions.componentContext] : + [canvasOptions]; + + return canvasToTempFilePath.apply(null, arg) + }) + .then(function(res) { + var tempFilePath = res.tempFilePath; + + return tools_7(fn) ? + fn.call(self, tempFilePath, null) : + tempFilePath + }) + .catch(function(err) { + if (tools_7(fn)) { + fn.call(self, null, err); + } else { + throw err + } + }) + }; + } + + /** + * 获取最新缩放值 + * @param oldScale 上一次触摸结束后的缩放值 + * @param oldDistance 上一次触摸结束后的双指距离 + * @param zoom 缩放系数 + * @param touch0 第一指touch对象 + * @param touch1 第二指touch对象 + * @returns {*} + */ + var getNewScale = function(oldScale, oldDistance, zoom, touch0, touch1) { + var xMove, yMove, newDistance; + // 计算二指最新距离 + xMove = Math.round(touch1.x - touch0.x); + yMove = Math.round(touch1.y - touch0.y); + newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); + + return oldScale + 0.001 * zoom * (newDistance - oldDistance) + }; + + function update() { + var self = this; + + if (!self.src) { + return + } + + self.__oneTouchStart = function(touch) { + self.touchX0 = Math.round(touch.x); + self.touchY0 = Math.round(touch.y); + }; + + self.__oneTouchMove = function(touch) { + var xMove, yMove; + // 计算单指移动的距离 + if (self.touchended) { + return self.updateCanvas() + } + xMove = Math.round(touch.x - self.touchX0); + yMove = Math.round(touch.y - self.touchY0); + + var imgLeft = Math.round(self.rectX + xMove); + var imgTop = Math.round(self.rectY + yMove); + + self.outsideBound(imgLeft, imgTop); + + self.updateCanvas(); + }; + + self.__twoTouchStart = function(touch0, touch1) { + var xMove, yMove, oldDistance; + + self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2); + self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2); + + // 计算两指距离 + xMove = Math.round(touch1.x - touch0.x); + yMove = Math.round(touch1.y - touch0.y); + oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); + + self.oldDistance = oldDistance; + }; + + self.__twoTouchMove = function(touch0, touch1) { + var oldScale = self.oldScale; + var oldDistance = self.oldDistance; + var scale = self.scale; + var zoom = self.zoom; + + self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1); + + // 设定缩放范围 + self.newScale <= 1 && (self.newScale = 1); + self.newScale >= scale && (self.newScale = scale); + + self.scaleWidth = Math.round(self.newScale * self.baseWidth); + self.scaleHeight = Math.round(self.newScale * self.baseHeight); + var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2); + var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2); + + self.outsideBound(imgLeft, imgTop); + + self.updateCanvas(); + }; + + self.__xtouchEnd = function() { + self.oldScale = self.newScale; + self.rectX = self.imgLeft; + self.rectY = self.imgTop; + }; + } + + var handle = { + // 图片手势初始监测 + touchStart: function touchStart(e) { + var self = this; + var ref = e.touches; + var touch0 = ref[0]; + var touch1 = ref[1]; + + if (!self.src) { + return + } + + setTouchState(self, true, null, null); + + // 计算第一个触摸点的位置,并参照改点进行缩放 + self.__oneTouchStart(touch0); + + // 两指手势触发 + if (e.touches.length >= 2) { + self.__twoTouchStart(touch0, touch1); + } + }, + + // 图片手势动态缩放 + touchMove: function touchMove(e) { + var self = this; + var ref = e.touches; + var touch0 = ref[0]; + var touch1 = ref[1]; + + if (!self.src) { + return + } + + setTouchState(self, null, true); + + // 单指手势时触发 + if (e.touches.length === 1) { + self.__oneTouchMove(touch0); + } + // 两指手势触发 + if (e.touches.length >= 2) { + self.__twoTouchMove(touch0, touch1); + } + }, + + touchEnd: function touchEnd(e) { + var self = this; + + if (!self.src) { + return + } + + setTouchState(self, false, false, true); + self.__xtouchEnd(); + } + }; + + function cut() { + var self = this; + var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度 + var boundHeight = self.height; + // 裁剪框默认高度,即整个画布高度 + var ref = self.cut; + var x = ref.x; + if (x === void 0) x = 0; + var y = ref.y; + if (y === void 0) y = 0; + var width = ref.width; + if (width === void 0) width = boundWidth; + var height = ref.height; + if (height === void 0) height = boundHeight; + + /** + * 设置边界 + * @param imgLeft 图片左上角横坐标值 + * @param imgTop 图片左上角纵坐标值 + */ + self.outsideBound = function(imgLeft, imgTop) { + self.imgLeft = imgLeft >= x ? + x : + self.scaleWidth + imgLeft - x <= width ? + x + width - self.scaleWidth : + imgLeft; + + self.imgTop = imgTop >= y ? + y : + self.scaleHeight + imgTop - y <= height ? + y + height - self.scaleHeight : + imgTop; + }; + + /** + * 设置边界样式 + * @param color 边界颜色 + */ + self.setBoundStyle = function(ref) { + if (ref === void 0) ref = {}; + var color = ref.color; + if (color === void 0) color = '#04b00f'; + var mask = ref.mask; + if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)'; + var lineWidth = ref.lineWidth; + if (lineWidth === void 0) lineWidth = 1; + + var half = lineWidth / 2; + var boundOption = [{ + start: { + x: x - half, + y: y + 10 - half + }, + step1: { + x: x - half, + y: y - half + }, + step2: { + x: x + 10 - half, + y: y - half + } + }, + { + start: { + x: x - half, + y: y + height - 10 + half + }, + step1: { + x: x - half, + y: y + height + half + }, + step2: { + x: x + 10 - half, + y: y + height + half + } + }, + { + start: { + x: x + width - 10 + half, + y: y - half + }, + step1: { + x: x + width + half, + y: y - half + }, + step2: { + x: x + width + half, + y: y + 10 - half + } + }, + { + start: { + x: x + width + half, + y: y + height - 10 + half + }, + step1: { + x: x + width + half, + y: y + height + half + }, + step2: { + x: x + width - 10 + half, + y: y + height + half + } + } + ]; + + // 绘制半透明层 + self.ctx.beginPath(); + self.ctx.setFillStyle(mask); + self.ctx.fillRect(0, 0, x, boundHeight); + self.ctx.fillRect(x, 0, width, y); + self.ctx.fillRect(x, y + height, width, boundHeight - y - height); + self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight); + self.ctx.fill(); + + boundOption.forEach(function(op) { + self.ctx.beginPath(); + self.ctx.setStrokeStyle(color); + self.ctx.setLineWidth(lineWidth); + self.ctx.moveTo(op.start.x, op.start.y); + self.ctx.lineTo(op.step1.x, op.step1.y); + self.ctx.lineTo(op.step2.x, op.step2.y); + self.ctx.stroke(); + }); + }; + } + + var version = "1.3.9"; + + var WeCropper = function WeCropper(params) { + var self = this; + var _default = {}; + + validator(self, DEFAULT); + + Object.keys(DEFAULT).forEach(function(key) { + _default[key] = DEFAULT[key].default; + }); + Object.assign(self, _default, params); + + self.prepare(); + self.attachPage(); + self.createCtx(); + self.observer(); + self.cutt(); + self.methods(); + self.init(); + self.update(); + + return self + }; + + WeCropper.prototype.init = function init() { + var self = this; + var src = self.src; + + self.version = version; + + typeof self.onReady === 'function' && self.onReady(self.ctx, self); + + if (src) { + self.pushOrign(src); + } else { + self.updateCanvas(); + } + setTouchState(self, false, false, false); + + self.oldScale = 1; + self.newScale = 1; + + return self + }; + + Object.assign(WeCropper.prototype, handle); + + WeCropper.prototype.prepare = prepare; + WeCropper.prototype.observer = observer; + WeCropper.prototype.methods = methods; + WeCropper.prototype.cutt = cut; + WeCropper.prototype.update = update; + + return WeCropper; + +}))); diff --git a/node_modules/uview-ui/components/u-avatar/u-avatar.vue b/node_modules/uview-ui/components/u-avatar/u-avatar.vue new file mode 100644 index 0000000..c441a82 --- /dev/null +++ b/node_modules/uview-ui/components/u-avatar/u-avatar.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-back-top/u-back-top.vue b/node_modules/uview-ui/components/u-back-top/u-back-top.vue new file mode 100644 index 0000000..11f3181 --- /dev/null +++ b/node_modules/uview-ui/components/u-back-top/u-back-top.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-badge/u-badge.vue b/node_modules/uview-ui/components/u-badge/u-badge.vue new file mode 100644 index 0000000..0e0e938 --- /dev/null +++ b/node_modules/uview-ui/components/u-badge/u-badge.vue @@ -0,0 +1,216 @@ + + + + + \ No newline at end of file diff --git a/node_modules/uview-ui/components/u-button/u-button.vue b/node_modules/uview-ui/components/u-button/u-button.vue new file mode 100644 index 0000000..dad207b --- /dev/null +++ b/node_modules/uview-ui/components/u-button/u-button.vue @@ -0,0 +1,596 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-calendar/u-calendar.vue b/node_modules/uview-ui/components/u-calendar/u-calendar.vue new file mode 100644 index 0000000..b2faa8d --- /dev/null +++ b/node_modules/uview-ui/components/u-calendar/u-calendar.vue @@ -0,0 +1,639 @@ + + + + \ No newline at end of file diff --git a/node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue new file mode 100644 index 0000000..ff0cb6e --- /dev/null +++ b/node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-card/u-card.vue b/node_modules/uview-ui/components/u-card/u-card.vue new file mode 100644 index 0000000..9c78fab --- /dev/null +++ b/node_modules/uview-ui/components/u-card/u-card.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-cell-group/u-cell-group.vue b/node_modules/uview-ui/components/u-cell-group/u-cell-group.vue new file mode 100644 index 0000000..b7cde8b --- /dev/null +++ b/node_modules/uview-ui/components/u-cell-group/u-cell-group.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-cell-item/u-cell-item.vue b/node_modules/uview-ui/components/u-cell-item/u-cell-item.vue new file mode 100644 index 0000000..1476e2a --- /dev/null +++ b/node_modules/uview-ui/components/u-cell-item/u-cell-item.vue @@ -0,0 +1,316 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue new file mode 100644 index 0000000..2eb1de9 --- /dev/null +++ b/node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-checkbox/u-checkbox.vue b/node_modules/uview-ui/components/u-checkbox/u-checkbox.vue new file mode 100644 index 0000000..68896c9 --- /dev/null +++ b/node_modules/uview-ui/components/u-checkbox/u-checkbox.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue b/node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue new file mode 100644 index 0000000..71d85f0 --- /dev/null +++ b/node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue b/node_modules/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue new file mode 100644 index 0000000..708c684 --- /dev/null +++ b/node_modules/uview-ui/components/u-circle-progress/u-line-progress/u-line-progress.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-col/u-col.vue b/node_modules/uview-ui/components/u-col/u-col.vue new file mode 100644 index 0000000..6ee276b --- /dev/null +++ b/node_modules/uview-ui/components/u-col/u-col.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue b/node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue new file mode 100644 index 0000000..7273108 --- /dev/null +++ b/node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-collapse/u-collapse.vue b/node_modules/uview-ui/components/u-collapse/u-collapse.vue new file mode 100644 index 0000000..16f6506 --- /dev/null +++ b/node_modules/uview-ui/components/u-collapse/u-collapse.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-column-notice/u-column-notice.vue b/node_modules/uview-ui/components/u-column-notice/u-column-notice.vue new file mode 100644 index 0000000..4435f60 --- /dev/null +++ b/node_modules/uview-ui/components/u-column-notice/u-column-notice.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-count-down/u-count-down.vue b/node_modules/uview-ui/components/u-count-down/u-count-down.vue new file mode 100644 index 0000000..c6f7cea --- /dev/null +++ b/node_modules/uview-ui/components/u-count-down/u-count-down.vue @@ -0,0 +1,318 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-count-to/u-count-to.vue b/node_modules/uview-ui/components/u-count-to/u-count-to.vue new file mode 100644 index 0000000..16b7271 --- /dev/null +++ b/node_modules/uview-ui/components/u-count-to/u-count-to.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-divider/u-divider.vue b/node_modules/uview-ui/components/u-divider/u-divider.vue new file mode 100644 index 0000000..38297cc --- /dev/null +++ b/node_modules/uview-ui/components/u-divider/u-divider.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/node_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue new file mode 100644 index 0000000..3a0d72c --- /dev/null +++ b/node_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-dropdown/u-dropdown.vue b/node_modules/uview-ui/components/u-dropdown/u-dropdown.vue new file mode 100644 index 0000000..5ee7cb1 --- /dev/null +++ b/node_modules/uview-ui/components/u-dropdown/u-dropdown.vue @@ -0,0 +1,298 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-empty/u-empty.vue b/node_modules/uview-ui/components/u-empty/u-empty.vue new file mode 100644 index 0000000..f9b4db4 --- /dev/null +++ b/node_modules/uview-ui/components/u-empty/u-empty.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/node_modules/uview-ui/components/u-field/u-field.vue b/node_modules/uview-ui/components/u-field/u-field.vue new file mode 100644 index 0000000..34e2d2a --- /dev/null +++ b/node_modules/uview-ui/components/u-field/u-field.vue @@ -0,0 +1,384 @@ +