修复node包
This commit is contained in:
22
node_modules/.package-lock.json
generated
vendored
22
node_modules/.package-lock.json
generated
vendored
@@ -3,5 +3,25 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {}
|
"packages": {
|
||||||
|
"node_modules/uni-read-pages": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/uni-read-pages/-/uni-read-pages-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==",
|
||||||
|
"hasInstallScript": true
|
||||||
|
},
|
||||||
|
"node_modules/uni-simple-router": {
|
||||||
|
"version": "2.0.8-beta.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/uni-simple-router/-/uni-simple-router-2.0.8-beta.4.tgz",
|
||||||
|
"integrity": "sha512-ipTHhOaRvjV8qrt3HosX5pNMhwFYBnFOuKyV5joH0evfXubjrGI5tjdwpmwzfW5h3VBth3iAqScv+pW/QmIJXw=="
|
||||||
|
},
|
||||||
|
"node_modules/uview-ui": {
|
||||||
|
"version": "2.0.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.31.tgz",
|
||||||
|
"integrity": "sha512-I/0fGuvtiKHH/mBb864SGYk+SJ7WaF32tsBgYgeBOsxlUp+Th+Ac2tgz2cTvsQJl6eZYWsKZ3ixiSXCAcxZ8Sw==",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
node_modules/uni-read-pages/README.md
generated
vendored
Normal file
108
node_modules/uni-read-pages/README.md
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# uni-read-pages
|
||||||
|
|
||||||
|
   
|
||||||
|
|
||||||
|
通过 [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
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
title: 'Hello'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
console.log(ROUTES)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
## 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
|
||||||
83
node_modules/uni-read-pages/index.js
generated
vendored
Normal file
83
node_modules/uni-read-pages/index.js
generated
vendored
Normal file
@@ -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
|
||||||
25
node_modules/uni-read-pages/package.json
generated
vendored
Normal file
25
node_modules/uni-read-pages/package.json
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "uni-read-pages",
|
||||||
|
"version": "1.0.5",
|
||||||
|
"description": "read `pages.json` file to generate the routes table",
|
||||||
|
"main": "index.js",
|
||||||
|
"directories": {
|
||||||
|
"example": "examples"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "node -e \"console.log('\\x1b[91m','\\n\\n uni-simple-router 垫脚片,欢迎下载!\\n \\n 开源不易,需要鼓励。去给 uni-read-pages 项目 点个 star 吧 \\n\\n')\"",
|
||||||
|
"dev": "webpack --watch --progress --config webpack/webpack.dev.js",
|
||||||
|
"build": "webpack --progress --config webpack/webpack.prod.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/SilurianYang/uni-read-pages.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/SilurianYang/uni-read-pages/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/SilurianYang/uni-read-pages#readme"
|
||||||
|
}
|
||||||
7
node_modules/uni-simple-router/.eslintignore
generated
vendored
Normal file
7
node_modules/uni-simple-router/.eslintignore
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
dist
|
||||||
|
/node_modules
|
||||||
|
/webpack
|
||||||
|
/src/global.d.ts
|
||||||
|
/test
|
||||||
|
/jest.config.js
|
||||||
|
/plugins
|
||||||
259
node_modules/uni-simple-router/.eslintrc.js
generated
vendored
Normal file
259
node_modules/uni-simple-router/.eslintrc.js
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
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,
|
||||||
|
$npm_package_version: true,
|
||||||
|
$npm_package_last_version: 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']
|
||||||
|
}
|
||||||
|
};
|
||||||
39
node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/bug_report.md
generated
vendored
Normal file
39
node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/bug_report.md
generated
vendored
Normal file
@@ -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]
|
||||||
|
|
||||||
|
|
||||||
|
**补充信息**
|
||||||
|
[可选]
|
||||||
|
[根据你的分析,出现这个问题的原因可能在哪里?]
|
||||||
21
node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/feature_request.md
generated
vendored
Normal file
21
node_modules/uni-simple-router/.github/ISSUE_TEMPLATE/feature_request.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: 建议新功能(Feature Request)
|
||||||
|
about: 对 uni-simple-router 提出改善建议
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**新功能描述**
|
||||||
|
简洁描述你希望补充完善的增强功能
|
||||||
|
|
||||||
|
**现状及问题**
|
||||||
|
[当前现状及由此导致的不便]
|
||||||
|
|
||||||
|
**尝试方案**
|
||||||
|
[如果你有尝试绕开或其它解决方案,在这里描述你的建议方案]
|
||||||
|
|
||||||
|
**补充信息**
|
||||||
|
[其它你认为有参考价值的信息]
|
||||||
|
|
||||||
76
node_modules/uni-simple-router/CODE_OF_CONDUCT.md
generated
vendored
Normal file
76
node_modules/uni-simple-router/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@@ -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
|
||||||
21
node_modules/uni-simple-router/LICENSE
generated
vendored
Normal file
21
node_modules/uni-simple-router/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
49
node_modules/uni-simple-router/README.md
generated
vendored
Normal file
49
node_modules/uni-simple-router/README.md
generated
vendored
Normal file
@@ -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) 一直以来对文档和相关测试的维护。
|
||||||
|
|
||||||
|
## 技术交流
|
||||||
|
|
||||||
|
<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=0f4d7f38e5d15dd49bf7c3032c80ed3f54ecfa3dd800053d6ae145c869f9eb47"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="uni-app 插件" title="uni-app 插件"></a>
|
||||||
|
|
||||||
|
|
||||||
|
## 成品预览
|
||||||
|
|
||||||
|
<div style="display: -webkit-box;display: flex; flex-direction: column;align-items: center;">
|
||||||
|
<p style="color: #3eaf7c;font-size:18px">uni-simple-router@2.0+ts+uni-app</p>
|
||||||
|
<img src="https://hhyang.cn/images/ad1.jpg" width="200" height="200">
|
||||||
|
</div>
|
||||||
38
node_modules/uni-simple-router/RFC.md
generated
vendored
Normal file
38
node_modules/uni-simple-router/RFC.md
generated
vendored
Normal file
@@ -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
|
||||||
|
|
||||||
|
```
|
||||||
50
node_modules/uni-simple-router/api-extractor.json
generated
vendored
Normal file
50
node_modules/uni-simple-router/api-extractor.json
generated
vendored
Normal file
@@ -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/<unscopedPackageName>.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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
85
node_modules/uni-simple-router/dist/link.vue
generated
vendored
Normal file
85
node_modules/uni-simple-router/dist/link.vue
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<view @click="gotoPage()"><slot></slot></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const navType = {
|
||||||
|
push: 'push',
|
||||||
|
replace: 'replace',
|
||||||
|
replaceAll: 'replaceAll',
|
||||||
|
pushTab: 'pushTab',
|
||||||
|
back:'back'
|
||||||
|
};
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
to: {
|
||||||
|
type: [String, Object],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
stopNavto: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
navType: {
|
||||||
|
type: String,
|
||||||
|
default: 'push',
|
||||||
|
},
|
||||||
|
level: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
append: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatNav(text) {
|
||||||
|
if (text != null && text.constructor === String) {
|
||||||
|
const keyArray = [];
|
||||||
|
text = text.replace(/((\w+)|('\s*(\w+)\s*')|("\s*(\w+)\s*"))\s*(?=:)/g, function (val) {
|
||||||
|
const key = `"${val.trim().replace(/"|'/g, '')}"`;
|
||||||
|
keyArray.push(key);
|
||||||
|
return key
|
||||||
|
});
|
||||||
|
const removeReg=/('|")/g;
|
||||||
|
for (let i = 0; i < keyArray.length; i++) {
|
||||||
|
const key = keyArray[i];
|
||||||
|
text=text.replace(new RegExp(`${key}\\s*:\\s*('[^']+')`, 'g'),(...args)=>{
|
||||||
|
const $1=args[1];
|
||||||
|
return `${key}:"${$1.replace(removeReg,'')}"`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
text=JSON.parse(text);
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
if (this.append) {
|
||||||
|
let pathArr = this.$Route.path.split('/');
|
||||||
|
pathArr.splice(pathArr.length - this.level, this.level);
|
||||||
|
pathArr = pathArr.join('/');
|
||||||
|
if (text.constructor === Object) {
|
||||||
|
if (text.path) {
|
||||||
|
text.path = pathArr + text.path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = pathArr + text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
},
|
||||||
|
gotoPage() {
|
||||||
|
if (this.stopNavto) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const type = navType[this.navType];
|
||||||
|
if (type == null) {
|
||||||
|
return console.error(` "navType" unknown type \n\n value:${Object.values(navType).join('、')}`);
|
||||||
|
}
|
||||||
|
const navInfo = this.formatNav(this.to);
|
||||||
|
|
||||||
|
this.$Router[type](navInfo);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
397
node_modules/uni-simple-router/dist/uni-simple-router.d.ts
generated
vendored
Normal file
397
node_modules/uni-simple-router/dist/uni-simple-router.d.ts
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
|
||||||
|
export declare interface AppConfig {
|
||||||
|
registerLoadingPage?: boolean;
|
||||||
|
loadingPageStyle?: () => object;
|
||||||
|
loadingPageHook?: (view: any) => void;
|
||||||
|
launchedHook?: () => void;
|
||||||
|
animation?: startAnimationRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface appletConfig {
|
||||||
|
animationDuration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function assertDeepObject(object: objectAny): boolean;
|
||||||
|
|
||||||
|
export declare function assertNewOptions<T extends InstantiateConfig>(options: T): T | never;
|
||||||
|
|
||||||
|
export declare function assertParentChild(parentPath: string, vueVim: any): boolean;
|
||||||
|
|
||||||
|
export declare type backTypeRule = 'backbutton' | 'navigateBack';
|
||||||
|
|
||||||
|
export declare function baseClone<T extends {
|
||||||
|
[key: string]: any;
|
||||||
|
}, K extends keyof T>(source: T, target: Array<any> | objectAny): Array<any> | objectAny | null;
|
||||||
|
|
||||||
|
export declare function copyData<T>(object: T): T;
|
||||||
|
|
||||||
|
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 function deepClone<T>(source: T): T;
|
||||||
|
|
||||||
|
export declare function deepDecodeQuery(query: objectAny): objectAny;
|
||||||
|
|
||||||
|
export declare function def(defObject: objectAny, key: string, getValue: Function): void;
|
||||||
|
|
||||||
|
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 function forMatNextToFrom<T extends totalNextRoute>(router: Router, to: T, from: T): {
|
||||||
|
matTo: T;
|
||||||
|
matFrom: T;
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare function getDataType<T>(data: T): string;
|
||||||
|
|
||||||
|
export declare function getRoutePath(route: RoutesRule, router: Router): {
|
||||||
|
finallyPath: string | string[];
|
||||||
|
aliasPath: string;
|
||||||
|
path: string;
|
||||||
|
alias: string | string[] | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare function getUniCachePage<T extends objectAny>(pageIndex?: number): T | [];
|
||||||
|
|
||||||
|
export declare function getWildcardRule(router: Router, msg?: navErrorRule): RoutesRule | never;
|
||||||
|
|
||||||
|
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<object>;
|
||||||
|
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<any>;
|
||||||
|
hook: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare type hookRule = (args: Array<any>, next: (args: Array<any>) => void, router: Router) => void;
|
||||||
|
|
||||||
|
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;
|
||||||
|
beforeProxyHooks?: proxyHooksConfig;
|
||||||
|
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 function lockDetectWarn(router: Router, to: string | number | totalNextRoute | navRoute, navType: NAVTYPE, next: Function, uniActualData?: uniBackApiRule | uniBackRule | undefined, passiveType?: 'beforeHooks' | 'afterHooks'): void;
|
||||||
|
|
||||||
|
export declare function mergeConfig<T extends InstantiateConfig>(baseConfig: T, userConfig: T): T;
|
||||||
|
|
||||||
|
export declare interface navErrorRule {
|
||||||
|
type: navRuleStatus;
|
||||||
|
msg: string;
|
||||||
|
to?: totalNextRoute;
|
||||||
|
from?: totalNextRoute;
|
||||||
|
nextTo?: any;
|
||||||
|
[propName: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type navMethodRule = Promise<void | undefined | navRuleStatus>;
|
||||||
|
|
||||||
|
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 function notDeepClearNull<T>(object: T): T;
|
||||||
|
|
||||||
|
export declare function notRouteTo404(router: Router, toRoute: RoutesRule | {
|
||||||
|
redirect: any;
|
||||||
|
path: string;
|
||||||
|
}, parseToRule: totalNextRoute, navType: NAVTYPE): RoutesRule | totalNextRoute | never;
|
||||||
|
|
||||||
|
export declare type objectAny = {
|
||||||
|
[propName: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare interface originMixins extends uniNavApiRule {
|
||||||
|
BACKTYPE: '' | backTypeRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type pageTypeRule = 'app' | 'page' | 'component';
|
||||||
|
|
||||||
|
export declare function paramsToQuery(router: Router, toRule: totalNextRoute | string): totalNextRoute | string;
|
||||||
|
|
||||||
|
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<void> | undefined) => void;
|
||||||
|
|
||||||
|
export declare type proxyDepsRule = {
|
||||||
|
resetIndex: Array<number>;
|
||||||
|
hooks: {
|
||||||
|
[key: number]: {
|
||||||
|
proxyHook: () => void;
|
||||||
|
callHook: (enterPath: string) => void;
|
||||||
|
resetHook: () => void;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
options: {
|
||||||
|
[key: number]: Array<any>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare type proxyHookName = 'beforeHooks' | 'afterHooks';
|
||||||
|
|
||||||
|
export declare interface proxyHooksConfig {
|
||||||
|
onLaunch?: hookRule;
|
||||||
|
onShow?: hookRule;
|
||||||
|
onHide?: hookRule;
|
||||||
|
onError?: hookRule;
|
||||||
|
onInit?: hookRule;
|
||||||
|
onLoad?: hookRule;
|
||||||
|
onReady?: hookRule;
|
||||||
|
onUnload?: hookRule;
|
||||||
|
onResize?: hookRule;
|
||||||
|
destroyed?: hookRule;
|
||||||
|
created?: hookRule;
|
||||||
|
beforeCreate?: hookRule;
|
||||||
|
beforeMount?: hookRule;
|
||||||
|
mounted?: hookRule;
|
||||||
|
beforeDestroy?: hookRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type reloadNavRule = totalNextRoute | false | undefined | string;
|
||||||
|
|
||||||
|
export declare function removeSimpleValue(array: Array<string | number>, value: string): Boolean;
|
||||||
|
|
||||||
|
export declare type reNavMethodRule = 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab';
|
||||||
|
|
||||||
|
export declare type reNotNavMethodRule = 'navigateBack';
|
||||||
|
|
||||||
|
export declare function resolveAbsolutePath(path: string, router: Router): string | never;
|
||||||
|
|
||||||
|
export declare enum rewriteMethodToggle {
|
||||||
|
'navigateTo' = "push",
|
||||||
|
'navigate' = "push",
|
||||||
|
'redirectTo' = "replace",
|
||||||
|
'reLaunch' = "replaceAll",
|
||||||
|
'switchTab' = "pushTab",
|
||||||
|
'navigateBack' = "back"
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface Router {
|
||||||
|
readonly lifeCycle: LifeCycleConfig;
|
||||||
|
readonly options: InstantiateConfig;
|
||||||
|
$lockStatus: boolean;
|
||||||
|
$route: object | null;
|
||||||
|
enterPath: string;
|
||||||
|
runId: number;
|
||||||
|
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 function routesForMapRoute(router: Router, path: string, mapArrayKey: Array<routesMapKeysRule>, deepFind?: boolean | undefined): RoutesRule | never;
|
||||||
|
|
||||||
|
export declare type routesMapKeysRule = 'finallyPathList' | 'finallyPathMap' | 'aliasPathMap' | 'pathMap' | 'nameMap' | 'vueRouteMap';
|
||||||
|
|
||||||
|
export declare interface routesMapRule {
|
||||||
|
[key: string]: any;
|
||||||
|
finallyPathList: Array<string>;
|
||||||
|
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<string>;
|
||||||
|
children?: Array<RoutesRule>;
|
||||||
|
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 function timeOut(time: number): Promise<void>;
|
||||||
|
|
||||||
|
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 function urlToJson(url: string): {
|
||||||
|
path: string;
|
||||||
|
query: objectAny;
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare function voidFun(...args: any): void;
|
||||||
|
|
||||||
|
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<Function> | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { }
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
declare module 'vue/types/vue' {
|
||||||
|
interface Vue {
|
||||||
|
$Router: Router;
|
||||||
|
$Route: routeRule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1
node_modules/uni-simple-router/dist/uni-simple-router.js
generated
vendored
Normal file
1
node_modules/uni-simple-router/dist/uni-simple-router.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
107
node_modules/uni-simple-router/github.sh
generated
vendored
Normal file
107
node_modules/uni-simple-router/github.sh
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# author hhyang
|
||||||
|
# home https://github.com/SilurianYang
|
||||||
|
|
||||||
|
printf "\n -------------- Ctrl+D可以退出程序 --------------- \n\n"
|
||||||
|
|
||||||
|
select name in "auto" "status" "add" "commit" "push" "pull" "branch" "checkout" "*"; do
|
||||||
|
case "$name" in
|
||||||
|
# 自动同步文件
|
||||||
|
"auto")
|
||||||
|
cp -avx ./examples/node_modules/uni-simple-router/* ./npm-package
|
||||||
|
rm -rf ./npm-package/package-lock.json
|
||||||
|
cp -avx ./README.md ./npm-package
|
||||||
|
cp -avx ./package.json ./npm-package
|
||||||
|
cp -avx ./npm-package/* ./src
|
||||||
|
rm -rf ./src/README.md
|
||||||
|
rm -rf ./src/package.json
|
||||||
|
|
||||||
|
printf "\n -------------- 自动化构建目录完毕 --------------- \n\n"
|
||||||
|
;;
|
||||||
|
|
||||||
|
# 查询status
|
||||||
|
"status")
|
||||||
|
git status
|
||||||
|
printf "\n -------------- 查询完毕 --------------- \n\n"
|
||||||
|
;;
|
||||||
|
|
||||||
|
# 添加文件 .或* 全部文件 可自定义文件路径
|
||||||
|
"add")
|
||||||
|
while read -p "请输入更多提交命令 【默认全部.】 :" add; do
|
||||||
|
if [[ "$add" == "" ]]; then
|
||||||
|
eval "git add ."
|
||||||
|
else
|
||||||
|
eval "git add ${add}"
|
||||||
|
fi
|
||||||
|
printf "\n -------------- 添加完成 --------------- \n\n"
|
||||||
|
break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
# 提交文件
|
||||||
|
"commit")
|
||||||
|
while read -p "请输入提交信息:" readme; do
|
||||||
|
if [[ "$readme" != "" ]]; then
|
||||||
|
eval "git commit -m '${readme}'"
|
||||||
|
printf "\n -------------- 提交本地完成 --------------- \n\n"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
printf "\n警告====> 提交信息不能为空! \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
|
||||||
5
node_modules/uni-simple-router/jest.config.js
generated
vendored
Normal file
5
node_modules/uni-simple-router/jest.config.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
moduleDirectories:['node_modules','src']
|
||||||
|
};
|
||||||
34
node_modules/uni-simple-router/package.json
generated
vendored
Normal file
34
node_modules/uni-simple-router/package.json
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "uni-simple-router",
|
||||||
|
"version": "2.0.8-beta.4",
|
||||||
|
"description": "> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造",
|
||||||
|
"main": "dist/uni-simple-router.js",
|
||||||
|
"types": "dist/uni-simple-router.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"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",
|
||||||
|
"test": "jest test/query-toggle.spec.ts",
|
||||||
|
"publish": "node ./publish/index.js",
|
||||||
|
"build": "node ./publish/build.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/SilurianYang/uni-simple-router.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"router",
|
||||||
|
"uni-app-router",
|
||||||
|
"interceptor",
|
||||||
|
"uni-app",
|
||||||
|
"uniapp"
|
||||||
|
],
|
||||||
|
"author": "hhyang",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/SilurianYang/uni-simple-router/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/SilurianYang/uni-simple-router#readme"
|
||||||
|
}
|
||||||
76
node_modules/uni-simple-router/src/H5/buildRouter.ts
generated
vendored
Normal file
76
node_modules/uni-simple-router/src/H5/buildRouter.ts
generated
vendored
Normal file
@@ -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<string> = 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<RoutesRule|RoutesRule[]>(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;
|
||||||
|
}
|
||||||
32
node_modules/uni-simple-router/src/H5/patch.ts
generated
vendored
Normal file
32
node_modules/uni-simple-router/src/H5/patch.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { removeSimpleValue } from '../helpers/utils';
|
||||||
|
import { Router} from '../options/base';
|
||||||
|
|
||||||
|
let [dynamicCacheName, __id__] = ['', ''];
|
||||||
|
|
||||||
|
export const addKeepAliveInclude = function(
|
||||||
|
router:Router
|
||||||
|
):void{
|
||||||
|
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/316 2021年12月10日14:30:13
|
||||||
|
const app = getApp();
|
||||||
|
const keepAliveInclude:Array<string> = app.keepAliveInclude;
|
||||||
|
if (router.runId === 0 && keepAliveInclude.length === 0) {
|
||||||
|
__id__ = app.$route.params.__id__;
|
||||||
|
dynamicCacheName = app.$route.meta.name;
|
||||||
|
const cacheId = dynamicCacheName + '-' + __id__;
|
||||||
|
app.keepAliveInclude.push(cacheId)
|
||||||
|
} else {
|
||||||
|
if (dynamicCacheName !== '') {
|
||||||
|
const arrayCacheId = app.keepAliveInclude;
|
||||||
|
for (let i = 0; i < arrayCacheId.length; i++) {
|
||||||
|
const cacheId:string = arrayCacheId[i];
|
||||||
|
const cacheIdReg = new RegExp(`${dynamicCacheName}-(\\d+)$`);
|
||||||
|
const firstCacheId = `${dynamicCacheName}-${__id__}`;
|
||||||
|
if (cacheIdReg.test(cacheId) && cacheId !== firstCacheId) {
|
||||||
|
removeSimpleValue(arrayCacheId, firstCacheId);
|
||||||
|
dynamicCacheName = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
node_modules/uni-simple-router/src/H5/proxyHook.ts
generated
vendored
Normal file
71
node_modules/uni-simple-router/src/H5/proxyHook.ts
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import {Router, proxyHookName, totalNextRoute, navtoRule} from '../options/base';
|
||||||
|
|
||||||
|
export class MyArray extends Array {
|
||||||
|
constructor(
|
||||||
|
private router:Router,
|
||||||
|
private vueEachArray:Array<Function>,
|
||||||
|
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<Function> = 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 = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
98
node_modules/uni-simple-router/src/app/appPatch.ts
generated
vendored
Normal file
98
node_modules/uni-simple-router/src/app/appPatch.ts
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { navtoRule, 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.APP?.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 HomeNvueSwitchTab(
|
||||||
|
router:Router,
|
||||||
|
to:navtoRule,
|
||||||
|
oldMethod:Function
|
||||||
|
):Promise<Boolean> {
|
||||||
|
return new Promise((
|
||||||
|
resolve:(value:boolean)=>void
|
||||||
|
) => {
|
||||||
|
if (router.runId !== 0) {
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
if (!(__uniConfig.tabBar && Array.isArray(__uniConfig.tabBar.list))) {
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/373 2022-4-3 19:40:59
|
||||||
|
oldMethod({
|
||||||
|
url: __uniConfig.entryPagePath,
|
||||||
|
animationDuration:0,
|
||||||
|
complete: () => resolve(true)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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<totalNextRoute> = [];
|
||||||
|
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
|
||||||
|
}
|
||||||
18
node_modules/uni-simple-router/src/applets/appletPatch.ts
generated
vendored
Normal file
18
node_modules/uni-simple-router/src/applets/appletPatch.ts
generated
vendored
Normal file
@@ -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; // 这是暂时的 因为除了以上的小程序 其他没测试 先这样写
|
||||||
|
}
|
||||||
85
node_modules/uni-simple-router/src/component/link.vue
generated
vendored
Normal file
85
node_modules/uni-simple-router/src/component/link.vue
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<view @click="gotoPage()"><slot></slot></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const navType = {
|
||||||
|
push: 'push',
|
||||||
|
replace: 'replace',
|
||||||
|
replaceAll: 'replaceAll',
|
||||||
|
pushTab: 'pushTab',
|
||||||
|
back:'back'
|
||||||
|
};
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
to: {
|
||||||
|
type: [String, Object],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
stopNavto: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
navType: {
|
||||||
|
type: String,
|
||||||
|
default: 'push',
|
||||||
|
},
|
||||||
|
level: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
append: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatNav(text) {
|
||||||
|
if (text != null && text.constructor === String) {
|
||||||
|
const keyArray = [];
|
||||||
|
text = text.replace(/((\w+)|('\s*(\w+)\s*')|("\s*(\w+)\s*"))\s*(?=:)/g, function (val) {
|
||||||
|
const key = `"${val.trim().replace(/"|'/g, '')}"`;
|
||||||
|
keyArray.push(key);
|
||||||
|
return key
|
||||||
|
});
|
||||||
|
const removeReg=/('|")/g;
|
||||||
|
for (let i = 0; i < keyArray.length; i++) {
|
||||||
|
const key = keyArray[i];
|
||||||
|
text=text.replace(new RegExp(`${key}\\s*:\\s*('[^']+')`, 'g'),(...args)=>{
|
||||||
|
const $1=args[1];
|
||||||
|
return `${key}:"${$1.replace(removeReg,'')}"`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
text=JSON.parse(text);
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
if (this.append) {
|
||||||
|
let pathArr = this.$Route.path.split('/');
|
||||||
|
pathArr.splice(pathArr.length - this.level, this.level);
|
||||||
|
pathArr = pathArr.join('/');
|
||||||
|
if (text.constructor === Object) {
|
||||||
|
if (text.path) {
|
||||||
|
text.path = pathArr + text.path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = pathArr + text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
},
|
||||||
|
gotoPage() {
|
||||||
|
if (this.stopNavto) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const type = navType[this.navType];
|
||||||
|
if (type == null) {
|
||||||
|
return console.error(` "navType" unknown type \n\n value:${Object.values(navType).join('、')}`);
|
||||||
|
}
|
||||||
|
const navInfo = this.formatNav(this.to);
|
||||||
|
|
||||||
|
this.$Router[type](navInfo);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
9
node_modules/uni-simple-router/src/global.d.ts
generated
vendored
Normal file
9
node_modules/uni-simple-router/src/global.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
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;
|
||||||
|
declare var $npm_package_version:string;
|
||||||
|
declare var $npm_package_last_version:string;
|
||||||
84
node_modules/uni-simple-router/src/helpers/config.ts
generated
vendored
Normal file
84
node_modules/uni-simple-router/src/helpers/config.ts
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import {err} from './warn'
|
||||||
|
import { InstantiateConfig, LifeCycleConfig} from '../options/config'
|
||||||
|
import { vueHookNameRule, proxyDepsRule } from '../options/base';
|
||||||
|
import { parseQuery } from '../public/query';
|
||||||
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
beforeProxyHooks: {
|
||||||
|
onLoad: ([options], next, router) => {
|
||||||
|
next([parseQuery({query: options}, router)])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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<vueHookNameRule> = [
|
||||||
|
'onLaunch',
|
||||||
|
'onShow',
|
||||||
|
'onHide',
|
||||||
|
'onError',
|
||||||
|
'onInit',
|
||||||
|
'onLoad',
|
||||||
|
'onReady',
|
||||||
|
'onUnload',
|
||||||
|
'onResize',
|
||||||
|
'created',
|
||||||
|
'beforeMount',
|
||||||
|
'mounted',
|
||||||
|
'beforeDestroy',
|
||||||
|
'destroyed'
|
||||||
|
]
|
||||||
47
node_modules/uni-simple-router/src/helpers/createRouteMap.ts
generated
vendored
Normal file
47
node_modules/uni-simple-router/src/helpers/createRouteMap.ts
generated
vendored
Normal file
@@ -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;
|
||||||
|
}
|
||||||
36
node_modules/uni-simple-router/src/helpers/lifeCycle.ts
generated
vendored
Normal file
36
node_modules/uni-simple-router/src/helpers/lifeCycle.ts
generated
vendored
Normal file
@@ -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<Function>, fn:Function):void {
|
||||||
|
list[0] = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerRouterHooks<T extends LifeCycleConfig>(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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
114
node_modules/uni-simple-router/src/helpers/mixins.ts
generated
vendored
Normal file
114
node_modules/uni-simple-router/src/helpers/mixins.ts
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
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';
|
||||||
|
import {beforeProxyHook} from '../public/beforeProxyHook'
|
||||||
|
|
||||||
|
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 {
|
||||||
|
beforeProxyHook(this, router);
|
||||||
|
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 {
|
||||||
|
beforeProxyHook(this, router);
|
||||||
|
if (!registerRouter) {
|
||||||
|
registerRouter = true;
|
||||||
|
proxyPageHook(this, router, 'app');
|
||||||
|
registerLoddingPage(router);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'app-lets': {
|
||||||
|
beforeCreate(this: any): void {
|
||||||
|
beforeProxyHook(this, router);
|
||||||
|
|
||||||
|
// 保证这个函数不会被重写
|
||||||
|
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)
|
||||||
|
});
|
||||||
|
}
|
||||||
466
node_modules/uni-simple-router/src/helpers/utils.ts
generated
vendored
Normal file
466
node_modules/uni-simple-router/src/helpers/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,466 @@
|
|||||||
|
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<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve();
|
||||||
|
}, time)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mergeConfig<T extends InstantiateConfig>(baseConfig: T, userConfig: T): T {
|
||||||
|
const config: {[key: string]: any} = Object.create(null);
|
||||||
|
const baseConfigKeys: Array<string> = 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<T>(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<T extends InstantiateConfig>(
|
||||||
|
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<T>(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<routesMapKeysRule>,
|
||||||
|
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<Array<string>|objectAny>(mapList) === '[object Array]') {
|
||||||
|
rule = (route as string);
|
||||||
|
}
|
||||||
|
const pathRule:RegExp = Regexp(rule);
|
||||||
|
const result = pathRule.exec(startPath);
|
||||||
|
if (result != null) {
|
||||||
|
if (getDataType<string|RoutesRule>(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<T>(data:T):string {
|
||||||
|
return Object.prototype.toString.call(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function copyData<T>(object:T): T {
|
||||||
|
return JSON.parse(JSON.stringify(object))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeSimpleValue(
|
||||||
|
array:Array<string|number>,
|
||||||
|
value:string
|
||||||
|
):Boolean {
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
const it = array[i];
|
||||||
|
if (it === value) {
|
||||||
|
array.splice(i, 1);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUniCachePage<T extends objectAny>(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<T extends totalNextRoute>(
|
||||||
|
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<T>(matTo)) as T;
|
||||||
|
matFrom = createRoute(router, undefined, deepClone<T>(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<totalNextRoute|string>(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<any>|objectAny
|
||||||
|
):Array<any>|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<T>(source[key]) === '[object Array]' ? ([] as Array<any>) : ({} as objectAny)
|
||||||
|
target[dyKey] = baseClone(source[key], target[dyKey])
|
||||||
|
} else {
|
||||||
|
target[dyKey] = source[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deepClone<T>(source:T):T {
|
||||||
|
const __ob__ = getDataType<T>(source) === '[object Array]' ? ([] as Array<any>) : ({} 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 as unknown as {currentRoute:{path:string}}).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<objectAny>(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
|
||||||
|
}
|
||||||
37
node_modules/uni-simple-router/src/helpers/warn.ts
generated
vendored
Normal file
37
node_modules/uni-simple-router/src/helpers/warn.ts
generated
vendored
Normal file
@@ -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);
|
||||||
|
}
|
||||||
17
node_modules/uni-simple-router/src/index.ts
generated
vendored
Normal file
17
node_modules/uni-simple-router/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export * from './options/base'
|
||||||
|
export * from './options/config'
|
||||||
|
export * from './helpers/utils'
|
||||||
|
|
||||||
|
export {
|
||||||
|
runtimeQuit
|
||||||
|
} from './app/appPatch'
|
||||||
|
|
||||||
|
export {
|
||||||
|
RouterMount,
|
||||||
|
createRouter
|
||||||
|
} from './public/router'
|
||||||
|
|
||||||
|
const version = $npm_package_version;
|
||||||
|
if (/[A-Z]/g.test(version)) {
|
||||||
|
console.warn(`【${$npm_package_name.toLocaleLowerCase()} 提示】:当前版本 ${version.toLocaleLowerCase()} 此版本为测试版。有BUG请退回正式版,线上正式版本:${$npm_package_last_version}`)
|
||||||
|
}
|
||||||
245
node_modules/uni-simple-router/src/options/base.ts
generated
vendored
Normal file
245
node_modules/uni-simple-router/src/options/base.ts
generated
vendored
Normal file
@@ -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<number>;
|
||||||
|
hooks: {
|
||||||
|
[key: number]:{
|
||||||
|
proxyHook:()=>void;
|
||||||
|
callHook:(enterPath:string)=>void;
|
||||||
|
resetHook: ()=>void
|
||||||
|
}
|
||||||
|
};
|
||||||
|
options: {[key: number]: Array<any>;};
|
||||||
|
};
|
||||||
|
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<void | undefined | navRuleStatus>;
|
||||||
|
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<Function> | 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<object>;
|
||||||
|
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<any>;
|
||||||
|
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<string>;
|
||||||
|
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<string>; // H5端可用
|
||||||
|
children?: Array<RoutesRule>; // 嵌套路由,H5端可用
|
||||||
|
beforeEnter?:guardHookRule; // 路由元守卫
|
||||||
|
meta?: any; // 其他格外参数
|
||||||
|
[propName: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Router {
|
||||||
|
readonly lifeCycle: LifeCycleConfig;
|
||||||
|
readonly options: InstantiateConfig;
|
||||||
|
$lockStatus:boolean;
|
||||||
|
$route: object | null;
|
||||||
|
enterPath:string;
|
||||||
|
runId:number;
|
||||||
|
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<void> | undefined) => void;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
declare module 'vue/types/vue' {
|
||||||
|
interface Vue {
|
||||||
|
$Router: Router;
|
||||||
|
$Route: routeRule;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
node_modules/uni-simple-router/src/options/config.ts
generated
vendored
Normal file
77
node_modules/uni-simple-router/src/options/config.ts
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
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; // 页面切换时间,有助于路由锁精准解锁
|
||||||
|
}
|
||||||
|
|
||||||
|
type hookRule=(args:Array<any>, next:(args:Array<any>)=>void, router:Router)=>void;
|
||||||
|
export interface proxyHooksConfig{
|
||||||
|
onLaunch?:hookRule;
|
||||||
|
onShow?:hookRule;
|
||||||
|
onHide?:hookRule;
|
||||||
|
onError?:hookRule;
|
||||||
|
onInit?:hookRule;
|
||||||
|
onLoad?:hookRule;
|
||||||
|
onReady?:hookRule;
|
||||||
|
onUnload?:hookRule;
|
||||||
|
onResize?:hookRule;
|
||||||
|
destroyed?:hookRule;
|
||||||
|
created?:hookRule;
|
||||||
|
beforeCreate?:hookRule;
|
||||||
|
beforeMount?:hookRule;
|
||||||
|
mounted?:hookRule;
|
||||||
|
beforeDestroy?:hookRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
beforeProxyHooks?:proxyHooksConfig;
|
||||||
|
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>;
|
||||||
|
}
|
||||||
|
|
||||||
46
node_modules/uni-simple-router/src/public/beforeProxyHook.ts
generated
vendored
Normal file
46
node_modules/uni-simple-router/src/public/beforeProxyHook.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { voidFun } from '../helpers/utils';
|
||||||
|
import { warn } from '../helpers/warn';
|
||||||
|
import { Router, vueHookNameRule } from '../options/base';
|
||||||
|
|
||||||
|
export function beforeProxyHook(
|
||||||
|
Vim:any,
|
||||||
|
router:Router
|
||||||
|
):boolean {
|
||||||
|
const hookOptions = Vim.$options;
|
||||||
|
const {beforeProxyHooks} = router.options;
|
||||||
|
if (hookOptions == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (beforeProxyHooks == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const keyArray = Object.keys(beforeProxyHooks) as Array<vueHookNameRule>;
|
||||||
|
for (let i = 0; i < keyArray.length; i++) {
|
||||||
|
const key = keyArray[i];
|
||||||
|
const hooksArray:Array<Function>|null = hookOptions[key];
|
||||||
|
if (hooksArray) {
|
||||||
|
const beforeProxyFun = beforeProxyHooks[key];
|
||||||
|
for (let j = 0; j < hooksArray.length; j++) {
|
||||||
|
const hookFun = hooksArray[j];
|
||||||
|
if (hookFun.toString().includes($npm_package_name)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const [oldHook] = hooksArray.splice(j, 1, function myReplace(this: any, ...args:Array<any>) {
|
||||||
|
const pluginMarkId = $npm_package_name;
|
||||||
|
voidFun(pluginMarkId);
|
||||||
|
|
||||||
|
if (beforeProxyFun) {
|
||||||
|
beforeProxyFun.call(this, args, (options) => {
|
||||||
|
oldHook.apply(this, options)
|
||||||
|
}, router);
|
||||||
|
} else {
|
||||||
|
oldHook.apply(this, args)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn(`beforeProxyHooks ===> 当前组件不适合${key},或者 hook: ${key} 不存在,已为你规避处理,可以忽略。`, router)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
181
node_modules/uni-simple-router/src/public/hooks.ts
generated
vendored
Normal file
181
node_modules/uni-simple-router/src/public/hooks.ts
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
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 { addKeepAliveInclude } from '../H5/patch';
|
||||||
|
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);
|
||||||
|
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/316 2021年12月10日14:30:13
|
||||||
|
addKeepAliveInclude(router);
|
||||||
|
}
|
||||||
|
router.runId++;
|
||||||
|
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<objectAny>(0);
|
||||||
|
let beforeRouteLeave;
|
||||||
|
if (Object.keys(page).length > 0) {
|
||||||
|
let leaveHooks:Array<Function>|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<Array<Function>>((leaveHooks as Array<Function>))) {
|
||||||
|
case '[object Array]': // h5端表现
|
||||||
|
beforeRouteLeave = (leaveHooks as Array<Function>)[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<totalNextRoute>(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)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
263
node_modules/uni-simple-router/src/public/methods.ts
generated
vendored
Normal file
263
node_modules/uni-simple-router/src/public/methods.ts
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
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;
|
||||||
|
// 主要剥离事件函数
|
||||||
|
animation = {
|
||||||
|
...animation || {},
|
||||||
|
...(to as uniBackApiRule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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<any>(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<objectAny>(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<objectAny>(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;
|
||||||
|
}
|
||||||
103
node_modules/uni-simple-router/src/public/page.ts
generated
vendored
Normal file
103
node_modules/uni-simple-router/src/public/page.ts
generated
vendored
Normal file
@@ -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<Array<any>|objectAny>(0);
|
||||||
|
if (getDataType<Array<any>|objectAny>(page) === '[object Array]') {
|
||||||
|
fromRoute = deepClone<totalNextRoute>(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<any>):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();
|
||||||
|
}
|
||||||
|
}
|
||||||
200
node_modules/uni-simple-router/src/public/query.ts
generated
vendored
Normal file
200
node_modules/uni-simple-router/src/public/query.ts
generated
vendored
Normal file
@@ -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<string|totalNextRoute>(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<Function|undefined>(completeCb) === '[object Function]') {
|
||||||
|
const publicCb = function(this:any, args:Array<any>, callHook:Function|undefined):void {
|
||||||
|
if (getDataType<Function|undefined>(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<Function|undefined>(rule.success) === '[object Function]') {
|
||||||
|
rule.success = successCb;
|
||||||
|
}
|
||||||
|
if (getDataType<Function|undefined>(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<objectAny>(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<objectAny>(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<any> = []
|
||||||
|
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}` : ''
|
||||||
|
}
|
||||||
177
node_modules/uni-simple-router/src/public/rewrite.ts
generated
vendored
Normal file
177
node_modules/uni-simple-router/src/public/rewrite.ts
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
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'
|
||||||
|
import { HomeNvueSwitchTab } from '../app/appPatch';
|
||||||
|
|
||||||
|
const rewrite: Array<reNavMethodRule|reNotNavMethodRule> = [
|
||||||
|
'navigateTo',
|
||||||
|
'redirectTo',
|
||||||
|
'reLaunch',
|
||||||
|
'switchTab',
|
||||||
|
'navigateBack'
|
||||||
|
];
|
||||||
|
const cacheOldMethod:{
|
||||||
|
navigateTo:Function;
|
||||||
|
redirectTo:Function;
|
||||||
|
reLaunch:Function;
|
||||||
|
switchTab:Function;
|
||||||
|
navigateBack:Function;
|
||||||
|
} = {
|
||||||
|
navigateTo: () => {},
|
||||||
|
redirectTo: () => {},
|
||||||
|
reLaunch: () => {},
|
||||||
|
switchTab: () => {},
|
||||||
|
navigateBack: () => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rewriteMethod(
|
||||||
|
router:Router
|
||||||
|
): void {
|
||||||
|
if (router.options.keepUniOriginNav === false) {
|
||||||
|
rewrite.forEach(name => {
|
||||||
|
const oldMethod: Function = uni[name];
|
||||||
|
cacheOldMethod[name] = oldMethod;
|
||||||
|
uni[name] = async function(
|
||||||
|
params:originMixins|{from:string}|navtoRule,
|
||||||
|
originCall:boolean = false,
|
||||||
|
callOkCb?:Function,
|
||||||
|
forceNav?:boolean
|
||||||
|
):Promise<void> {
|
||||||
|
|
||||||
|
if (originCall) {
|
||||||
|
if (router.options.platform === 'app-plus') {
|
||||||
|
await HomeNvueSwitchTab(router, (params as navtoRule), cacheOldMethod['reLaunch']);
|
||||||
|
}
|
||||||
|
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
|
||||||
|
);
|
||||||
|
funName = 'navigateBack';
|
||||||
|
option = {
|
||||||
|
from: 'backbutton'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (funName === 'navigateBack') {
|
||||||
|
let level:number = 1;
|
||||||
|
if (option == null) {
|
||||||
|
option = {delta: 1};
|
||||||
|
}
|
||||||
|
if (getDataType<number|undefined>((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<string | string[]>(finallyPath) === '[object Array]') {
|
||||||
|
warn(
|
||||||
|
`uni-app 原生方法跳转路径为:${path}。此路为是tab页面时,不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!`,
|
||||||
|
router
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ((finallyPath as string) === '*') {
|
||||||
|
warn(
|
||||||
|
`uni-app 原生方法跳转路径为:${path}。在路由表中找不到相关路由表!当然你可以通过通配符*解决!`,
|
||||||
|
router
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 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<any>) => {
|
||||||
|
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<totalNextRoute>(jumpOptions)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
136
node_modules/uni-simple-router/src/public/router.ts
generated
vendored
Normal file
136
node_modules/uni-simple-router/src/public/router.ts
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
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<void> = new Promise(resolve => (AppReadyResolve = resolve));
|
||||||
|
|
||||||
|
function createRouter(
|
||||||
|
params: InstantiateConfig
|
||||||
|
):Router {
|
||||||
|
const options = assertNewOptions<InstantiateConfig>(params);
|
||||||
|
const router:Router = {
|
||||||
|
options,
|
||||||
|
mount: [],
|
||||||
|
runId: 0,
|
||||||
|
Vue: null,
|
||||||
|
proxyHookDeps: proxyHookDeps,
|
||||||
|
appMain: {},
|
||||||
|
enterPath: '',
|
||||||
|
$route: null,
|
||||||
|
$lockStatus: false,
|
||||||
|
routesMap: {},
|
||||||
|
lifeCycle: registerRouterHooks<LifeCycleConfig>(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<Array<any>>(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
|
||||||
|
}
|
||||||
112
node_modules/uni-simple-router/src/public/uniOrigin.ts
generated
vendored
Normal file
112
node_modules/uni-simple-router/src/public/uniOrigin.ts
generated
vendored
Normal file
@@ -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<any>) {
|
||||||
|
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<uniNavApiRule>({
|
||||||
|
delta,
|
||||||
|
url: queryURL,
|
||||||
|
animationType: animationType || animationRule.animationType,
|
||||||
|
animationDuration: animationDuration || animationRule.animationDuration,
|
||||||
|
events,
|
||||||
|
success,
|
||||||
|
fail,
|
||||||
|
complete
|
||||||
|
})
|
||||||
|
}
|
||||||
70
node_modules/uni-simple-router/test/path-to-regexp.spec.ts
generated
vendored
Normal file
70
node_modules/uni-simple-router/test/path-to-regexp.spec.ts
generated
vendored
Normal file
@@ -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]);
|
||||||
|
});
|
||||||
83
node_modules/uni-simple-router/test/query-toggle.spec.ts
generated
vendored
Normal file
83
node_modules/uni-simple-router/test/query-toggle.spec.ts
generated
vendored
Normal file
@@ -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}
|
||||||
|
}));
|
||||||
|
})
|
||||||
19
node_modules/uni-simple-router/tsconfig.json
generated
vendored
Normal file
19
node_modules/uni-simple-router/tsconfig.json
generated
vendored
Normal file
@@ -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"]
|
||||||
|
}
|
||||||
65
node_modules/uni-simple-router/webpack/webpack.common.js
generated
vendored
Normal file
65
node_modules/uni-simple-router/webpack/webpack.common.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
const {resolve} = require('path');
|
||||||
|
const CopyPlugin = require('copy-webpack-plugin');
|
||||||
|
const webpack =require('webpack');
|
||||||
|
const cmd = require('node-cmd');
|
||||||
|
|
||||||
|
|
||||||
|
const {data:versions,err} = cmd.runSync('npm v uni-simple-router versions');
|
||||||
|
|
||||||
|
if(err){
|
||||||
|
console.log('获取线上版本失败,无法继续打包。。。')
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastVersion='';
|
||||||
|
const list=JSON.parse(versions.replace(/'/g,'"')).reverse();
|
||||||
|
for(let i=0;i<list.length;i++){
|
||||||
|
if (!/[A-Za-z]/g.test(list[i])) {
|
||||||
|
lastVersion=list[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ),
|
||||||
|
$npm_package_version: webpack.DefinePlugin.runtimeValue(() => {
|
||||||
|
return JSON.stringify(process.env.npm_package_version.toLocaleUpperCase())
|
||||||
|
}, true ),
|
||||||
|
$npm_package_last_version: webpack.DefinePlugin.runtimeValue(() => {
|
||||||
|
return JSON.stringify(lastVersion)
|
||||||
|
}, true ),
|
||||||
|
})
|
||||||
|
],
|
||||||
|
};
|
||||||
24
node_modules/uni-simple-router/webpack/webpack.dev.js
generated
vendored
Normal file
24
node_modules/uni-simple-router/webpack/webpack.dev.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
});
|
||||||
19
node_modules/uni-simple-router/webpack/webpack.prod.js
generated
vendored
Normal file
19
node_modules/uni-simple-router/webpack/webpack.prod.js
generated
vendored
Normal file
@@ -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',
|
||||||
|
},
|
||||||
|
})
|
||||||
21
node_modules/uview-ui/LICENSE
generated
vendored
Normal file
21
node_modules/uview-ui/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
104
node_modules/uview-ui/README.md
generated
vendored
Normal file
104
node_modules/uview-ui/README.md
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
|
||||||
|
</p>
|
||||||
|
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
|
||||||
|
<h3 align="center">多平台快速开发的UI框架</h3>
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
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 */
|
||||||
|
<style lang="scss">
|
||||||
|
@import "uview-ui/index.scss";
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
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://www.uviewui.com/components/quickstart.html)了解更详细的内容
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<u-button text="按钮"></u-button>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
请通过[快速上手](https://www.uviewui.com/components/quickstart.html)了解更详细的内容
|
||||||
|
|
||||||
|
## 链接
|
||||||
|
|
||||||
|
- [官方文档](https://www.uviewui.com/)
|
||||||
|
- [更新日志](https://www.www.uviewui.com/components/changelog.html)
|
||||||
|
- [升级指南](https://www.uviewui.com/components/changelog.html)
|
||||||
|
- [关于我们](https://www.uviewui.com/cooperation/about.html)
|
||||||
|
|
||||||
|
## 预览
|
||||||
|
|
||||||
|
您可以通过**微信**扫码,查看最佳的演示效果。
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
|
||||||
|
|
||||||
|
## 捐赠uView的研发
|
||||||
|
|
||||||
|
uView文档和源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
|
||||||
|
|
||||||
|
<img src="https://uviewui.com/common/alipay.png" width="220" ><img style="margin-left: 100px;" src="https://uviewui.com/common/wechat.png" width="220" >
|
||||||
|
|
||||||
|
## 版权信息
|
||||||
|
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。
|
||||||
326
node_modules/uview-ui/changelog.md
generated
vendored
Normal file
326
node_modules/uview-ui/changelog.md
generated
vendored
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
## 2.0.31(2022-04-19)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复`upload`在`vue`页面上传成功后没有成功标志的问题
|
||||||
|
2. 解决演示项目中微信小程序模拟上传图片一直出于上传中问题
|
||||||
|
3. 修复`u-code-input`组件在`nvue`页面编译到`app`平台上光标异常问题(`app`去除此功能)
|
||||||
|
4. 修复`actionSheet`组件标题关闭按钮点击事件名称错误的问题
|
||||||
|
5. 其他修复
|
||||||
|
## 2.0.30(2022-04-04)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. `u-rate`增加`readonly`属性
|
||||||
|
2. `tabs`滑块支持设置背景图片
|
||||||
|
3. 修复`u-subsection` `mode`为`subsection`时,滑块样式不正确的问题
|
||||||
|
4. `u-code-input`添加光标效果动画
|
||||||
|
5. 修复`popup`的`open`事件不触发
|
||||||
|
6. 修复`u-flex-column`无效的问题
|
||||||
|
7. 修复`u-datetime-picker`索引在特定场合异常问题
|
||||||
|
8. 修复`u-datetime-picker`最小时间字符串模板错误问题
|
||||||
|
9. `u-swiper`添加`m3u8`验证
|
||||||
|
10. `u-swiper`修改判断image和video逻辑
|
||||||
|
11. 修复`swiper`无法使用本地图片问题,增加`type`参数
|
||||||
|
12. 修复`u-row-notice`格式错误问题
|
||||||
|
13. 修复`u-switch`组件当`unit`为`rpx`时,`nodeStyle`消失的问题
|
||||||
|
14. 修复`datetime-picker`组件`showToolbar`与`visibleItemCount`属性无效的问题
|
||||||
|
15. 修复`upload`组件条件编译位置判断错误,导致`previewImage`属性设置为`false`时,整个组件都会被隐藏的问题
|
||||||
|
16. 修复`u-checkbox-group`设置`shape`属性无效的问题
|
||||||
|
17. 修复`u-upload`的`capture`传入字符串的时候不生效的问题
|
||||||
|
18. 修复`u-action-sheet`组件,关闭事件逻辑错误的问题
|
||||||
|
19. 修复`u-list`触顶事件的触发错误的问题
|
||||||
|
20. 修复`u-text`只有手机号可拨打的问题
|
||||||
|
21. 修复`u-textarea`不能换行的问题
|
||||||
|
22. 其他修复
|
||||||
|
## 2.0.29(2022-03-13)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复`u--text`组件设置`decoration`属性未生效的问题
|
||||||
|
2. 修复`u-datetime-picker`使用`formatter`后返回值不正确
|
||||||
|
3. 修复`u-datetime-picker` `intercept` 可能为undefined
|
||||||
|
4. 修复已设置单位 uni..config.unit = 'rpx'时,线型指示器 `transform` 的位置翻倍,导致指示器超出宽度
|
||||||
|
5. 修复mixin中bem方法生成的类名在支付宝和字节小程序中失效
|
||||||
|
6. 修复默认值传值为空的时候,打开`u-datetime-picker`报错,不能选中第一列时间的bug
|
||||||
|
7. 修复`u-datetime-picker`使用`formatter`后返回值不正确
|
||||||
|
8. 修复`u-image`组件`loading`无效果的问题
|
||||||
|
9. 修复`config.unit`属性设为`rpx`时,导航栏占用高度不足导致塌陷的问题
|
||||||
|
10. 修复`u-datetime-picker`组件`itemHeight`无效问题
|
||||||
|
11. 其他修复
|
||||||
|
## 2.0.28(2022-02-22)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. search组件新增searchIconSize属性
|
||||||
|
2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56
|
||||||
|
3. 修复text value.js 判断日期出format错误问题
|
||||||
|
4. priceFormat格式化金额出现精度错误
|
||||||
|
5. priceFormat在部分情况下出现精度损失问题
|
||||||
|
6. 优化表单rules提示
|
||||||
|
7. 修复avatar组件src为空时,展示状态不对
|
||||||
|
8. 其他修复
|
||||||
|
## 2.0.27(2022-01-28)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1.样式修复
|
||||||
|
## 2.0.26(2022-01-28)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1.样式修复
|
||||||
|
## 2.0.25(2022-01-27)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复text组件mode=price时,可能会导致精度错误的问题
|
||||||
|
2. 添加$u.setConfig()方法,可设置uView内置的config, props, zIndex, color属性,详见:[修改uView内置配置方案](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
|
||||||
|
3. 优化form组件在errorType=toast时,如果输入错误页面会有抖动的问题
|
||||||
|
4. 修复$u.addUnit()对配置默认单位可能无效的问题
|
||||||
|
## 2.0.24(2022-01-25)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复swiper在current指定非0时缩放有误
|
||||||
|
2. 修复u-icon添加stop属性的时候报错
|
||||||
|
3. 优化遗留的通过正则判断rpx单位的问题
|
||||||
|
4. 优化Layout布局 vue使用gutter时,会超出固定区域
|
||||||
|
5. 优化search组件高度单位问题(rpx -> px)
|
||||||
|
6. 修复u-image slot 加载和错误的图片失去了高度
|
||||||
|
7. 修复u-index-list中footer插槽与header插槽存在性判断错误
|
||||||
|
8. 修复部分机型下u-popup关闭时会闪烁
|
||||||
|
9. 修复u-image在nvue-app下失去宽高
|
||||||
|
10. 修复u-popup运行报错
|
||||||
|
11. 修复u-tooltip报错
|
||||||
|
12. 修复box-sizing在app下的警告
|
||||||
|
13. 修复u-navbar在小程序中报运行时错误
|
||||||
|
14. 其他修复
|
||||||
|
## 2.0.23(2022-01-24)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复image组件在hx3.3.9的nvue下可能会显示异常的问题
|
||||||
|
2. 修复col组件gutter参数带rpx单位处理不正确的问题
|
||||||
|
3. 修复text组件单行时无法显示省略号的问题
|
||||||
|
4. navbar添加titleStyle参数
|
||||||
|
5. 升级到hx3.3.9可消除nvue下控制台样式警告的问题
|
||||||
|
## 2.0.22(2022-01-19)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. $u.page()方法优化,避免在特殊场景可能报错的问题
|
||||||
|
2. picker组件添加immediateChange参数
|
||||||
|
3. 新增$u.pages()方法
|
||||||
|
## 2.0.21(2022-01-19)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 优化:form组件在用户设置rules的时候提示用户model必传
|
||||||
|
2. 优化遗留的通过正则判断rpx单位的问题
|
||||||
|
3. 修复微信小程序环境中tabbar组件开启safeAreaInsetBottom属性后,placeholder高度填充不正确
|
||||||
|
4. 修复swiper在current指定非0时缩放有误
|
||||||
|
5. 修复u-icon添加stop属性的时候报错
|
||||||
|
6. 修复upload组件在accept=all的时候没有作用
|
||||||
|
7. 修复在text组件mode为phone时call属性无效的问题
|
||||||
|
8. 处理u-form clearValidate方法
|
||||||
|
9. 其他修复
|
||||||
|
## 2.0.20(2022-01-14)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复calendar默认会选择一个日期,如果直接点确定的话,无法取到值的问题
|
||||||
|
2. 修复Slider缺少disabled props 还有注释
|
||||||
|
3. 修复u-notice-bar点击事件无法拿到index索引值的问题
|
||||||
|
4. 修复u-collapse-item在vue文件下,app端自定义插槽不生效的问题
|
||||||
|
5. 优化头像为空时显示默认头像
|
||||||
|
6. 修复图片地址赋值后判断加载状态为完成问题
|
||||||
|
7. 修复日历滚动到默认日期月份区域
|
||||||
|
8. search组件暴露点击左边icon事件
|
||||||
|
9. 修复u-form clearValidate方法不生效
|
||||||
|
10. upload h5端增加返回文件参数(文件的name参数)
|
||||||
|
11. 处理upload选择文件后url为blob类型无法预览的问题
|
||||||
|
12. u-code-input 修复输入框没有往左移出一半屏幕
|
||||||
|
13. 修复Upload上传 disabled为true时,控制台报hoverClass类型错误
|
||||||
|
14. 临时处理ios app下grid点击坍塌问题
|
||||||
|
15. 其他修复
|
||||||
|
## 2.0.19(2021-12-29)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 优化微信小程序包体积可在微信中预览,请升级HbuilderX3.3.4,同时在“运行->运行到小程序模拟器”中勾选“运行时是否压缩代码”
|
||||||
|
2. 优化微信小程序setData性能,处理某些方法如$u.route()无法在模板中使用的问题
|
||||||
|
3. navbar添加autoBack参数
|
||||||
|
4. 允许avatar组件的事件冒泡
|
||||||
|
5. 修复cell组件报错问题
|
||||||
|
6. 其他修复
|
||||||
|
## 2.0.18(2021-12-28)
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复app端编译报错问题
|
||||||
|
2. 重新处理微信小程序端setData过大的性能问题
|
||||||
|
3. 修复边框问题
|
||||||
|
4. 修复最大最小月份不大于0则没有数据出现的问题
|
||||||
|
5. 修复SwipeAction微信小程序端无法上下滑动问题
|
||||||
|
6. 修复input的placeholder在小程序端默认显示为true问题
|
||||||
|
7. 修复divider组件click事件无效问题
|
||||||
|
8. 修复u-code-input maxlength 属性值为 String 类型时显示异常
|
||||||
|
9. 修复当 grid只有 1到2时 在小程序端algin设置无效的问题
|
||||||
|
10. 处理form-item的label为top时,取消错误提示的左边距
|
||||||
|
11. 其他修复
|
||||||
|
## 2.0.17(2021-12-26)
|
||||||
|
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 解决HBuilderX3.3.3.20211225版本导致的样式问题
|
||||||
|
2. calendar日历添加monthNum参数
|
||||||
|
3. navbar添加center slot
|
||||||
|
## 2.0.16(2021-12-25)
|
||||||
|
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 解决微信小程序setData性能问题
|
||||||
|
2. 修复count-down组件change事件不触发问题
|
||||||
|
## 2.0.15(2021-12-21)
|
||||||
|
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复Cell单元格titleWidth无效
|
||||||
|
2. 修复cheakbox组件ischecked不更新
|
||||||
|
3. 修复keyboard是否显示"."按键默认值问题
|
||||||
|
4. 修复number-keyboard是否显示键盘的"."符号问题
|
||||||
|
5. 修复Input输入框 readonly无效
|
||||||
|
6. 修复u-avatar 导致打包app、H5时候报错问题
|
||||||
|
7. 修复Upload上传deletable无效
|
||||||
|
8. 修复upload当设置maxSize时无效的问题
|
||||||
|
9. 修复tabs lineWidth传入带单位的字符串的时候偏移量计算错误问题
|
||||||
|
10. 修复rate组件在有padding的view内,显示的星星位置和可触摸区域不匹配,无法正常选中星星
|
||||||
|
## 2.0.13(2021-12-14)
|
||||||
|
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复配置默认单位为rpx可能会导致自定义导航栏高度异常的问题
|
||||||
|
## 2.0.12(2021-12-14)
|
||||||
|
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复tabs组件在vue环境下划线消失的问题
|
||||||
|
2. 修复upload组件在安卓小程序无法选择视频的问题
|
||||||
|
3. 添加uni.$u.config.unit配置,用于配置参数默认单位,详见:[默认单位配置](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
|
||||||
|
4. 修复textarea组件在没绑定v-model时,字符统计不生效问题
|
||||||
|
5. 修复nvue下控制是否出现滚动条失效问题
|
||||||
|
## 2.0.11(2021-12-13)
|
||||||
|
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. text组件align参数无效的问题
|
||||||
|
2. subsection组件添加keyName参数
|
||||||
|
3. upload组件无法判断[Object file]类型的问题
|
||||||
|
4. 处理notify层级过低问题
|
||||||
|
5. codeInput组件添加disabledDot参数
|
||||||
|
6. 处理actionSheet组件round参数无效的问题
|
||||||
|
7. calendar组件添加round参数用于控制圆角值
|
||||||
|
8. 处理swipeAction组件在vue环境下默认被打开的问题
|
||||||
|
9. button组件的throttleTime节流参数无效的问题
|
||||||
|
10. 解决u-notify手动关闭方法close()无效的问题
|
||||||
|
11. input组件readonly不生效问题
|
||||||
|
12. tag组件type参数为info不生效问题
|
||||||
|
## 2.0.10(2021-12-08)
|
||||||
|
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复button sendMessagePath属性不生效
|
||||||
|
2. 修复DatetimePicker选择器title无效
|
||||||
|
3. 修复u-toast设置loading=true不生效
|
||||||
|
4. 修复u-text金额模式传0报错
|
||||||
|
5. 修复u-toast组件的icon属性配置不生效
|
||||||
|
6. button的icon在特殊场景下的颜色优化
|
||||||
|
7. IndexList优化,增加#
|
||||||
|
## 2.0.9(2021-12-01)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 优化swiper的height支持100%值(仅vue有效),修复嵌入视频时click事件无法触发的问题
|
||||||
|
2. 优化tabs组件对list值为空的判断,或者动态变化list时重新计算相关尺寸的问题
|
||||||
|
3. 优化datetime-picker组件逻辑,让其后续打开的默认值为上一次的选中值,需要通过v-model绑定值才有效
|
||||||
|
4. 修复upload内嵌在其他组件中,选择图片可能不会换行的问题
|
||||||
|
## 2.0.8(2021-12-01)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复toast的position参数无效问题
|
||||||
|
2. 处理input在ios nvue上无法获得焦点的问题
|
||||||
|
3. avatar-group组件添加extraValue参数,让剩余展示数量可手动控制
|
||||||
|
4. tabs组件添加keyName参数用于配置从对象中读取的键名
|
||||||
|
5. 处理text组件名字脱敏默认配置无效的问题
|
||||||
|
6. 处理picker组件item文本太长换行问题
|
||||||
|
## 2.0.7(2021-11-30)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 修复radio和checkbox动态改变v-model无效的问题。
|
||||||
|
2. 优化form规则validator在微信小程序用法
|
||||||
|
3. 修复backtop组件mode参数在微信小程序无效的问题
|
||||||
|
4. 处理Album的previewFullImage属性无效的问题
|
||||||
|
5. 处理u-datetime-picker组件mode='time'在选择改变时间时,控制台报错的问题
|
||||||
|
## 2.0.6(2021-11-27)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. 处理tag组件在vue下边框无效的问题。
|
||||||
|
2. 处理popup组件圆角参数可能无效的问题。
|
||||||
|
3. 处理tabs组件lineColor参数可能无效的问题。
|
||||||
|
4. propgress组件在值很小时,显示异常的问题。
|
||||||
|
## 2.0.5(2021-11-25)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. calendar在vue下显示异常问题。
|
||||||
|
2. form组件labelPosition和errorType参数无效的问题
|
||||||
|
3. input组件inputAlign无效的问题
|
||||||
|
4. 其他一些修复
|
||||||
|
## 2.0.4(2021-11-23)
|
||||||
|
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
0. input组件缺失@confirm事件,以及subfix和prefix无效问题
|
||||||
|
1. component.scss文件样式在vue下干扰全局布局问题
|
||||||
|
2. 修复subsection在vue环境下表现异常的问题
|
||||||
|
3. tag组件的bgColor等参数无效的问题
|
||||||
|
4. upload组件不换行的问题
|
||||||
|
5. 其他的一些修复处理
|
||||||
|
## 2.0.3(2021-11-16)
|
||||||
|
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. uView2.0已实现全面兼容nvue
|
||||||
|
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
|
||||||
|
3. 目前uView2.0为公测阶段,相关细节可能会有变动
|
||||||
|
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
|
||||||
|
5. 处理modal的confirm回调事件拼写错误问题
|
||||||
|
6. 处理input组件@input事件参数错误问题
|
||||||
|
7. 其他一些修复
|
||||||
|
## 2.0.2(2021-11-16)
|
||||||
|
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. uView2.0已实现全面兼容nvue
|
||||||
|
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
|
||||||
|
3. 目前uView2.0为公测阶段,相关细节可能会有变动
|
||||||
|
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
|
||||||
|
5. 修复input组件formatter参数缺失问题
|
||||||
|
6. 优化loading-icon组件的scss写法问题,防止不兼容新版本scss
|
||||||
|
## 2.0.0(2020-11-15)
|
||||||
|
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
|
||||||
|
|
||||||
|
# uView2.0重磅发布,利剑出鞘,一统江湖
|
||||||
|
|
||||||
|
1. uView2.0已实现全面兼容nvue
|
||||||
|
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
|
||||||
|
3. 目前uView2.0为公测阶段,相关细节可能会有变动
|
||||||
|
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
|
||||||
|
5. 修复input组件formatter参数缺失问题
|
||||||
|
|
||||||
|
|
||||||
78
node_modules/uview-ui/components/u--form/u--form.vue
generated
vendored
Normal file
78
node_modules/uview-ui/components/u--form/u--form.vue
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<uvForm
|
||||||
|
ref="uForm"
|
||||||
|
:model="model"
|
||||||
|
:rules="rules"
|
||||||
|
:errorType="errorType"
|
||||||
|
:borderBottom="borderBottom"
|
||||||
|
:labelPosition="labelPosition"
|
||||||
|
:labelWidth="labelWidth"
|
||||||
|
:labelAlign="labelAlign"
|
||||||
|
:labelStyle="labelStyle"
|
||||||
|
:customStyle="customStyle"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</uvForm>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件
|
||||||
|
* 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
|
||||||
|
*/
|
||||||
|
import uvForm from '../u-form/u-form.vue';
|
||||||
|
import props from '../u-form/props.js'
|
||||||
|
export default {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
name: 'u-form',
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
name: 'u--form',
|
||||||
|
// #endif
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
components: {
|
||||||
|
uvForm
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.children = []
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
|
||||||
|
setRules(rules) {
|
||||||
|
this.$refs.uForm.setRules(rules)
|
||||||
|
},
|
||||||
|
validate() {
|
||||||
|
/**
|
||||||
|
* 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form
|
||||||
|
* 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的
|
||||||
|
* 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children
|
||||||
|
*/
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.setMpData()
|
||||||
|
// #endif
|
||||||
|
return this.$refs.uForm.validate()
|
||||||
|
},
|
||||||
|
validateField(value, callback) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.setMpData()
|
||||||
|
// #endif
|
||||||
|
return this.$refs.uForm.validateField(value, callback)
|
||||||
|
},
|
||||||
|
resetFields() {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.setMpData()
|
||||||
|
// #endif
|
||||||
|
return this.$refs.uForm.resetFields()
|
||||||
|
},
|
||||||
|
clearValidate(props) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.setMpData()
|
||||||
|
// #endif
|
||||||
|
return this.$refs.uForm.clearValidate(props)
|
||||||
|
},
|
||||||
|
setMpData() {
|
||||||
|
this.$refs.uForm.children = this.children
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
47
node_modules/uview-ui/components/u--image/u--image.vue
generated
vendored
Normal file
47
node_modules/uview-ui/components/u--image/u--image.vue
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<uvImage
|
||||||
|
:src="src"
|
||||||
|
:mode="mode"
|
||||||
|
:width="width"
|
||||||
|
:height="height"
|
||||||
|
:shape="shape"
|
||||||
|
:radius="radius"
|
||||||
|
:lazyLoad="lazyLoad"
|
||||||
|
:showMenuByLongpress="showMenuByLongpress"
|
||||||
|
:loadingIcon="loadingIcon"
|
||||||
|
:errorIcon="errorIcon"
|
||||||
|
:showLoading="showLoading"
|
||||||
|
:showError="showError"
|
||||||
|
:fade="fade"
|
||||||
|
:webp="webp"
|
||||||
|
:duration="duration"
|
||||||
|
:bgColor="bgColor"
|
||||||
|
:customStyle="customStyle"
|
||||||
|
@click="$emit('click')"
|
||||||
|
@error="$emit('error')"
|
||||||
|
@load="$emit('load')"
|
||||||
|
>
|
||||||
|
<template v-slot:loading>
|
||||||
|
<slot name="loading"></slot>
|
||||||
|
</template>
|
||||||
|
<template v-slot:error>
|
||||||
|
<slot name="error"></slot>
|
||||||
|
</template>
|
||||||
|
</uvImage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件
|
||||||
|
* 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
|
||||||
|
*/
|
||||||
|
import uvImage from '../u-image/u-image.vue';
|
||||||
|
import props from '../u-image/props.js';
|
||||||
|
export default {
|
||||||
|
name: 'u--image',
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
components: {
|
||||||
|
uvImage
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
72
node_modules/uview-ui/components/u--input/u--input.vue
generated
vendored
Normal file
72
node_modules/uview-ui/components/u--input/u--input.vue
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<uvInput
|
||||||
|
:value="value"
|
||||||
|
:type="type"
|
||||||
|
:fixed="fixed"
|
||||||
|
:disabled="disabled"
|
||||||
|
:disabledColor="disabledColor"
|
||||||
|
:clearable="clearable"
|
||||||
|
:password="password"
|
||||||
|
:maxlength="maxlength"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:placeholderClass="placeholderClass"
|
||||||
|
:placeholderStyle="placeholderStyle"
|
||||||
|
:showWordLimit="showWordLimit"
|
||||||
|
:confirmType="confirmType"
|
||||||
|
:confirmHold="confirmHold"
|
||||||
|
:holdKeyboard="holdKeyboard"
|
||||||
|
:focus="focus"
|
||||||
|
:autoBlur="autoBlur"
|
||||||
|
:disableDefaultPadding="disableDefaultPadding"
|
||||||
|
:cursor="cursor"
|
||||||
|
:cursorSpacing="cursorSpacing"
|
||||||
|
:selectionStart="selectionStart"
|
||||||
|
:selectionEnd="selectionEnd"
|
||||||
|
:adjustPosition="adjustPosition"
|
||||||
|
:inputAlign="inputAlign"
|
||||||
|
:fontSize="fontSize"
|
||||||
|
:color="color"
|
||||||
|
:prefixIcon="prefixIcon"
|
||||||
|
:suffixIcon="suffixIcon"
|
||||||
|
:suffixIconStyle="suffixIconStyle"
|
||||||
|
:prefixIconStyle="prefixIconStyle"
|
||||||
|
:border="border"
|
||||||
|
:readonly="readonly"
|
||||||
|
:shape="shape"
|
||||||
|
:customStyle="customStyle"
|
||||||
|
:formatter="formatter"
|
||||||
|
@focus="$emit('focus')"
|
||||||
|
@blur="$emit('blur')"
|
||||||
|
@keyboardheightchange="$emit('keyboardheightchange')"
|
||||||
|
@change="e => $emit('change', e)"
|
||||||
|
@input="e => $emit('input', e)"
|
||||||
|
@confirm="e => $emit('confirm', e)"
|
||||||
|
@clear="$emit('clear')"
|
||||||
|
@click="$emit('click')"
|
||||||
|
>
|
||||||
|
<!-- #ifdef MP -->
|
||||||
|
<slot name="prefix"></slot>
|
||||||
|
<slot name="suffix"></slot>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP -->
|
||||||
|
<slot name="prefix" slot="prefix"></slot>
|
||||||
|
<slot name="suffix" slot="suffix"></slot>
|
||||||
|
<!-- #endif -->
|
||||||
|
</uvInput>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件
|
||||||
|
* 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
|
||||||
|
*/
|
||||||
|
import uvInput from '../u-input/u-input.vue';
|
||||||
|
import props from '../u-input/props.js'
|
||||||
|
export default {
|
||||||
|
name: 'u--input',
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
components: {
|
||||||
|
uvInput
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
44
node_modules/uview-ui/components/u--text/u--text.vue
generated
vendored
Normal file
44
node_modules/uview-ui/components/u--text/u--text.vue
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<uvText
|
||||||
|
:type="type"
|
||||||
|
:show="show"
|
||||||
|
:text="text"
|
||||||
|
:prefixIcon="prefixIcon"
|
||||||
|
:suffixIcon="suffixIcon"
|
||||||
|
:mode="mode"
|
||||||
|
:href="href"
|
||||||
|
:format="format"
|
||||||
|
:call="call"
|
||||||
|
:openType="openType"
|
||||||
|
:bold="bold"
|
||||||
|
:block="block"
|
||||||
|
:lines="lines"
|
||||||
|
:color="color"
|
||||||
|
:decoration="decoration"
|
||||||
|
:size="size"
|
||||||
|
:iconStyle="iconStyle"
|
||||||
|
:margin="margin"
|
||||||
|
:lineHeight="lineHeight"
|
||||||
|
:align="align"
|
||||||
|
:wordWrap="wordWrap"
|
||||||
|
:customStyle="customStyle"
|
||||||
|
@click="$emit('click')"
|
||||||
|
></uvText>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件
|
||||||
|
* 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转
|
||||||
|
* 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
|
||||||
|
*/
|
||||||
|
import uvText from "../u-text/u-text.vue";
|
||||||
|
import props from "../u-text/props.js";
|
||||||
|
export default {
|
||||||
|
name: "u--text",
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
components: {
|
||||||
|
uvText,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
47
node_modules/uview-ui/components/u--textarea/u--textarea.vue
generated
vendored
Normal file
47
node_modules/uview-ui/components/u--textarea/u--textarea.vue
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<uvTextarea
|
||||||
|
:value="value"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:height="height"
|
||||||
|
:confirmType="confirmType"
|
||||||
|
:disabled="disabled"
|
||||||
|
:count="count"
|
||||||
|
:focus="focus"
|
||||||
|
:autoHeight="autoHeight"
|
||||||
|
:fixed="fixed"
|
||||||
|
:cursorSpacing="cursorSpacing"
|
||||||
|
:cursor="cursor"
|
||||||
|
:showConfirmBar="showConfirmBar"
|
||||||
|
:selectionStart="selectionStart"
|
||||||
|
:selectionEnd="selectionEnd"
|
||||||
|
:adjustPosition="adjustPosition"
|
||||||
|
:disableDefaultPadding="disableDefaultPadding"
|
||||||
|
:holdKeyboard="holdKeyboard"
|
||||||
|
:maxlength="maxlength"
|
||||||
|
:border="border"
|
||||||
|
:customStyle="customStyle"
|
||||||
|
:formatter="formatter"
|
||||||
|
@focus="e => $emit('focus')"
|
||||||
|
@blur="e => $emit('blur')"
|
||||||
|
@linechange="e => $emit('linechange', e)"
|
||||||
|
@confirm="e => $emit('confirm')"
|
||||||
|
@input="e => $emit('input', e)"
|
||||||
|
@keyboardheightchange="e => $emit('keyboardheightchange')"
|
||||||
|
></uvTextarea>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件
|
||||||
|
* 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
|
||||||
|
*/
|
||||||
|
import uvTextarea from '../u-textarea/u-textarea.vue';
|
||||||
|
import props from '../u-textarea/props.js'
|
||||||
|
export default {
|
||||||
|
name: 'u--textarea',
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
components: {
|
||||||
|
uvTextarea
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
54
node_modules/uview-ui/components/u-action-sheet/props.js
generated
vendored
Normal file
54
node_modules/uview-ui/components/u-action-sheet/props.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 操作菜单是否展示 (默认false)
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.actionSheet.show
|
||||||
|
},
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.actionSheet.title
|
||||||
|
},
|
||||||
|
// 选项上方的描述信息
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.actionSheet.description
|
||||||
|
},
|
||||||
|
// 数据
|
||||||
|
actions: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.actionSheet.actions
|
||||||
|
},
|
||||||
|
// 取消按钮的文字,不为空时显示按钮
|
||||||
|
cancelText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.actionSheet.cancelText
|
||||||
|
},
|
||||||
|
// 点击某个菜单项时是否关闭弹窗
|
||||||
|
closeOnClickAction: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.actionSheet.closeOnClickAction
|
||||||
|
},
|
||||||
|
// 处理底部安全区(默认true)
|
||||||
|
safeAreaInsetBottom: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.actionSheet.safeAreaInsetBottom
|
||||||
|
},
|
||||||
|
// 小程序的打开方式
|
||||||
|
openType: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.actionSheet.openType
|
||||||
|
},
|
||||||
|
// 点击遮罩是否允许关闭 (默认true)
|
||||||
|
closeOnClickOverlay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.actionSheet.closeOnClickOverlay
|
||||||
|
},
|
||||||
|
// 圆角值
|
||||||
|
round: {
|
||||||
|
type: [Boolean, String, Number],
|
||||||
|
default: uni.$u.props.actionSheet.round
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
278
node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
generated
vendored
Normal file
278
node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<u-popup
|
||||||
|
:show="show"
|
||||||
|
mode="bottom"
|
||||||
|
@close="closeHandler"
|
||||||
|
:safeAreaInsetBottom="safeAreaInsetBottom"
|
||||||
|
:round="round"
|
||||||
|
>
|
||||||
|
<view class="u-action-sheet">
|
||||||
|
<view
|
||||||
|
class="u-action-sheet__header"
|
||||||
|
v-if="title"
|
||||||
|
>
|
||||||
|
<text class="u-action-sheet__header__title u-line-1">{{title}}</text>
|
||||||
|
<view
|
||||||
|
class="u-action-sheet__header__icon-wrap"
|
||||||
|
@tap.stop="cancel"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
name="close"
|
||||||
|
size="17"
|
||||||
|
color="#c8c9cc"
|
||||||
|
bold
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text
|
||||||
|
class="u-action-sheet__description"
|
||||||
|
:style="[{
|
||||||
|
marginTop: `${title && description ? 0 : '18px'}`
|
||||||
|
}]"
|
||||||
|
v-if="description"
|
||||||
|
>{{description}}</text>
|
||||||
|
<slot>
|
||||||
|
<u-line v-if="description"></u-line>
|
||||||
|
<view class="u-action-sheet__item-wrap">
|
||||||
|
<template v-for="(item, index) in actions">
|
||||||
|
<!-- #ifdef MP -->
|
||||||
|
<button
|
||||||
|
:key="index"
|
||||||
|
class="u-reset-button"
|
||||||
|
:openType="item.openType"
|
||||||
|
@getuserinfo="onGetUserInfo"
|
||||||
|
@contact="onContact"
|
||||||
|
@getphonenumber="onGetPhoneNumber"
|
||||||
|
@error="onError"
|
||||||
|
@launchapp="onLaunchApp"
|
||||||
|
@opensetting="onOpenSetting"
|
||||||
|
:lang="lang"
|
||||||
|
:session-from="sessionFrom"
|
||||||
|
:send-message-title="sendMessageTitle"
|
||||||
|
:send-message-path="sendMessagePath"
|
||||||
|
:send-message-img="sendMessageImg"
|
||||||
|
:show-message-card="showMessageCard"
|
||||||
|
:app-parameter="appParameter"
|
||||||
|
@tap="selectHandler(index)"
|
||||||
|
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
|
||||||
|
>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view
|
||||||
|
class="u-action-sheet__item-wrap__item"
|
||||||
|
@tap.stop="selectHandler(index)"
|
||||||
|
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
|
||||||
|
:hover-stay-time="150"
|
||||||
|
>
|
||||||
|
<template v-if="!item.loading">
|
||||||
|
<text
|
||||||
|
class="u-action-sheet__item-wrap__item__name"
|
||||||
|
:style="[itemStyle(index)]"
|
||||||
|
>{{ item.name }}</text>
|
||||||
|
<text
|
||||||
|
v-if="item.subname"
|
||||||
|
class="u-action-sheet__item-wrap__item__subname"
|
||||||
|
>{{ item.subname }}</text>
|
||||||
|
</template>
|
||||||
|
<u-loading-icon
|
||||||
|
v-else
|
||||||
|
custom-class="van-action-sheet__loading"
|
||||||
|
size="18"
|
||||||
|
mode="circle"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef MP -->
|
||||||
|
</button>
|
||||||
|
<!-- #endif -->
|
||||||
|
<u-line v-if="index !== actions.length - 1"></u-line>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
<u-gap
|
||||||
|
bgColor="#eaeaec"
|
||||||
|
height="6"
|
||||||
|
v-if="cancelText"
|
||||||
|
></u-gap>
|
||||||
|
<view hover-class="u-action-sheet--hover">
|
||||||
|
<text
|
||||||
|
@touchmove.stop.prevent
|
||||||
|
:hover-stay-time="150"
|
||||||
|
v-if="cancelText"
|
||||||
|
class="u-action-sheet__cancel-text"
|
||||||
|
@tap="cancel"
|
||||||
|
>{{cancelText}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import openType from '../../libs/mixin/openType'
|
||||||
|
import button from '../../libs/mixin/button'
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* ActionSheet 操作菜单
|
||||||
|
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
|
||||||
|
* @tutorial https://www.uviewui.com/components/actionSheet.html
|
||||||
|
*
|
||||||
|
* @property {Boolean} show 操作菜单是否展示 (默认 false )
|
||||||
|
* @property {String} title 操作菜单标题
|
||||||
|
* @property {String} description 选项上方的描述信息
|
||||||
|
* @property {Array<Object>} actions 按钮的文字数组,见官方文档示例
|
||||||
|
* @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
|
||||||
|
* @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true )
|
||||||
|
* @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true )
|
||||||
|
* @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
|
||||||
|
* @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
|
||||||
|
* @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
|
||||||
|
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
|
||||||
|
* @property {String} sessionFrom 会话来源,openType="contact"时有效
|
||||||
|
* @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
|
||||||
|
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
|
||||||
|
* @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
|
||||||
|
* @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
|
||||||
|
* @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
|
||||||
|
*
|
||||||
|
* @event {Function} select 点击ActionSheet列表项时触发
|
||||||
|
* @event {Function} close 点击取消按钮时触发
|
||||||
|
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
|
||||||
|
* @event {Function} contact 客服消息回调,openType="contact"时有效
|
||||||
|
* @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效
|
||||||
|
* @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效
|
||||||
|
* @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效
|
||||||
|
* @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效
|
||||||
|
* @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-action-sheet",
|
||||||
|
// 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
|
||||||
|
mixins: [openType, button, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 操作项目的样式
|
||||||
|
itemStyle() {
|
||||||
|
return (index) => {
|
||||||
|
let style = {};
|
||||||
|
if (this.actions[index].color) style.color = this.actions[index].color
|
||||||
|
if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize)
|
||||||
|
// 选项被禁用的样式
|
||||||
|
if (this.actions[index].disabled) style.color = '#c0c4cc'
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeHandler() {
|
||||||
|
// 允许点击遮罩关闭时,才发出close事件
|
||||||
|
if(this.closeOnClickOverlay) {
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 点击取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.$emit('close')
|
||||||
|
},
|
||||||
|
selectHandler(index) {
|
||||||
|
const item = this.actions[index]
|
||||||
|
if (item && !item.disabled && !item.loading) {
|
||||||
|
this.$emit('select', item)
|
||||||
|
if (this.closeOnClickAction) {
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
$u-action-sheet-reset-button-width:100% !default;
|
||||||
|
$u-action-sheet-title-font-size: 16px !default;
|
||||||
|
$u-action-sheet-title-padding: 12px 30px !default;
|
||||||
|
$u-action-sheet-title-color: $u-main-color !default;
|
||||||
|
$u-action-sheet-header-icon-wrap-right:15px !default;
|
||||||
|
$u-action-sheet-header-icon-wrap-top:15px !default;
|
||||||
|
$u-action-sheet-description-font-size:13px !default;
|
||||||
|
$u-action-sheet-description-color:14px !default;
|
||||||
|
$u-action-sheet-description-margin: 18px 15px !default;
|
||||||
|
$u-action-sheet-item-wrap-item-padding:15px !default;
|
||||||
|
$u-action-sheet-item-wrap-name-font-size:16px !default;
|
||||||
|
$u-action-sheet-item-wrap-subname-font-size:13px !default;
|
||||||
|
$u-action-sheet-item-wrap-subname-color: #c0c4cc !default;
|
||||||
|
$u-action-sheet-item-wrap-subname-margin-top:10px !default;
|
||||||
|
$u-action-sheet-cancel-text-font-size:16px !default;
|
||||||
|
$u-action-sheet-cancel-text-color:$u-content-color !default;
|
||||||
|
$u-action-sheet-cancel-text-font-size:15px !default;
|
||||||
|
$u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
|
||||||
|
|
||||||
|
.u-reset-button {
|
||||||
|
width: $u-action-sheet-reset-button-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-action-sheet {
|
||||||
|
text-align: center;
|
||||||
|
&__header {
|
||||||
|
position: relative;
|
||||||
|
padding: $u-action-sheet-title-padding;
|
||||||
|
&__title {
|
||||||
|
font-size: $u-action-sheet-title-font-size;
|
||||||
|
color: $u-action-sheet-title-color;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon-wrap {
|
||||||
|
position: absolute;
|
||||||
|
right: $u-action-sheet-header-icon-wrap-right;
|
||||||
|
top: $u-action-sheet-header-icon-wrap-top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
font-size: $u-action-sheet-description-font-size;
|
||||||
|
color: $u-tips-color;
|
||||||
|
margin: $u-action-sheet-description-margin;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item-wrap {
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
padding: $u-action-sheet-item-wrap-item-padding;
|
||||||
|
@include flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
font-size: $u-action-sheet-item-wrap-name-font-size;
|
||||||
|
color: $u-main-color;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subname {
|
||||||
|
font-size: $u-action-sheet-item-wrap-subname-font-size;
|
||||||
|
color: $u-action-sheet-item-wrap-subname-color;
|
||||||
|
margin-top: $u-action-sheet-item-wrap-subname-margin-top;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cancel-text {
|
||||||
|
font-size: $u-action-sheet-cancel-text-font-size;
|
||||||
|
color: $u-action-sheet-cancel-text-color;
|
||||||
|
text-align: center;
|
||||||
|
padding: $u-action-sheet-cancel-text-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--hover {
|
||||||
|
background-color: $u-action-sheet-cancel-text-hover-background-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
59
node_modules/uview-ui/components/u-album/props.js
generated
vendored
Normal file
59
node_modules/uview-ui/components/u-album/props.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 图片地址,Array<String>|Array<Object>形式
|
||||||
|
urls: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.album.urls
|
||||||
|
},
|
||||||
|
// 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||||
|
keyName: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.album.keyName
|
||||||
|
},
|
||||||
|
// 单图时,图片长边的长度
|
||||||
|
singleSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.album.singleSize
|
||||||
|
},
|
||||||
|
// 多图时,图片边长
|
||||||
|
multipleSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.album.multipleSize
|
||||||
|
},
|
||||||
|
// 多图时,图片水平和垂直之间的间隔
|
||||||
|
space: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.album.space
|
||||||
|
},
|
||||||
|
// 单图时,图片缩放裁剪的模式
|
||||||
|
singleMode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.album.singleMode
|
||||||
|
},
|
||||||
|
// 多图时,图片缩放裁剪的模式
|
||||||
|
multipleMode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.album.multipleMode
|
||||||
|
},
|
||||||
|
// 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.album.maxCount
|
||||||
|
},
|
||||||
|
// 是否可以预览图片
|
||||||
|
previewFullImage: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.album.previewFullImage
|
||||||
|
},
|
||||||
|
// 每行展示图片数量,如设置,singleSize和multipleSize将会无效
|
||||||
|
rowCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.album.rowCount
|
||||||
|
},
|
||||||
|
// 超出maxCount时是否显示查看更多的提示
|
||||||
|
showMore: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.album.showMore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
259
node_modules/uview-ui/components/u-album/u-album.vue
generated
vendored
Normal file
259
node_modules/uview-ui/components/u-album/u-album.vue
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-album">
|
||||||
|
<view
|
||||||
|
class="u-album__row"
|
||||||
|
ref="u-album__row"
|
||||||
|
v-for="(arr, index) in showUrls"
|
||||||
|
:forComputedUse="albumWidth"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-album__row__wrapper"
|
||||||
|
v-for="(item, index1) in arr"
|
||||||
|
:key="index1"
|
||||||
|
:style="[imageStyle(index + 1, index1 + 1)]"
|
||||||
|
@tap="previewFullImage ? onPreviewTap(getSrc(item)) : ''"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="getSrc(item)"
|
||||||
|
:mode="
|
||||||
|
urls.length === 1
|
||||||
|
? imageHeight > 0
|
||||||
|
? singleMode
|
||||||
|
: 'widthFix'
|
||||||
|
: multipleMode
|
||||||
|
"
|
||||||
|
:style="[
|
||||||
|
{
|
||||||
|
width: imageWidth,
|
||||||
|
height: imageHeight
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
></image>
|
||||||
|
<view
|
||||||
|
v-if="
|
||||||
|
showMore &&
|
||||||
|
urls.length > rowCount * showUrls.length &&
|
||||||
|
index === showUrls.length - 1 &&
|
||||||
|
index1 === showUrls[showUrls.length - 1].length - 1
|
||||||
|
"
|
||||||
|
class="u-album__row__wrapper__text"
|
||||||
|
>
|
||||||
|
<u--text
|
||||||
|
:text="`+${urls.length - maxCount}`"
|
||||||
|
color="#fff"
|
||||||
|
:size="multipleSize * 0.3"
|
||||||
|
align="center"
|
||||||
|
customStyle="justify-content: center"
|
||||||
|
></u--text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js'
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 由于weex为阿里的KPI业绩考核的产物,所以不支持百分比单位,这里需要通过dom查询组件的宽度
|
||||||
|
const dom = uni.requireNativePlugin('dom')
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Album 相册
|
||||||
|
* @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码
|
||||||
|
* @tutorial https://www.uviewui.com/components/album.html
|
||||||
|
*
|
||||||
|
* @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式
|
||||||
|
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||||
|
* @property {String | Number} singleSize 单图时,图片长边的长度 (默认 180 )
|
||||||
|
* @property {String | Number} multipleSize 多图时,图片边长 (默认 70 )
|
||||||
|
* @property {String | Number} space 多图时,图片水平和垂直之间的间隔 (默认 6 )
|
||||||
|
* @property {String} singleMode 单图时,图片缩放裁剪的模式 (默认 'scaleToFill' )
|
||||||
|
* @property {String} multipleMode 多图时,图片缩放裁剪的模式 (默认 'aspectFill' )
|
||||||
|
* @property {String | Number} maxCount 取消按钮的提示文字 (默认 9 )
|
||||||
|
* @property {Boolean} previewFullImage 是否可以预览图片 (默认 true )
|
||||||
|
* @property {String | Number} rowCount 每行展示图片数量,如设置,singleSize和multipleSize将会无效 (默认 3 )
|
||||||
|
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
|
||||||
|
*
|
||||||
|
* @event {Function} albumWidth 某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送 (回调参数 width )
|
||||||
|
* @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-album',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 单图的宽度
|
||||||
|
singleWidth: 0,
|
||||||
|
// 单图的高度
|
||||||
|
singleHeight: 0,
|
||||||
|
// 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比
|
||||||
|
singlePercent: 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
urls: {
|
||||||
|
immediate: true,
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal.length === 1) {
|
||||||
|
this.getImageRect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
imageStyle() {
|
||||||
|
return (index1, index2) => {
|
||||||
|
const { space, rowCount, multipleSize, urls } = this,
|
||||||
|
{ addUnit, addStyle } = uni.$u,
|
||||||
|
rowLen = this.showUrls.length,
|
||||||
|
allLen = this.urls.length
|
||||||
|
const style = {
|
||||||
|
marginRight: addUnit(space),
|
||||||
|
marginBottom: addUnit(space)
|
||||||
|
}
|
||||||
|
// 如果为最后一行,则每个图片都无需下边框
|
||||||
|
if (index1 === rowLen) style.marginBottom = 0
|
||||||
|
// 每行的最右边一张和总长度的最后一张无需右边框
|
||||||
|
if (
|
||||||
|
index2 === rowCount ||
|
||||||
|
(index1 === rowLen &&
|
||||||
|
index2 === this.showUrls[index1 - 1].length)
|
||||||
|
)
|
||||||
|
style.marginRight = 0
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 将数组划分为二维数组
|
||||||
|
showUrls() {
|
||||||
|
const arr = []
|
||||||
|
this.urls.map((item, index) => {
|
||||||
|
// 限制最大展示数量
|
||||||
|
if (index + 1 <= this.maxCount) {
|
||||||
|
// 计算该元素为第几个素组内
|
||||||
|
const itemIndex = Math.floor(index / this.rowCount)
|
||||||
|
// 判断对应的索引是否存在
|
||||||
|
if (!arr[itemIndex]) {
|
||||||
|
arr[itemIndex] = []
|
||||||
|
}
|
||||||
|
arr[itemIndex].push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
},
|
||||||
|
imageWidth() {
|
||||||
|
return uni.$u.addUnit(
|
||||||
|
this.urls.length === 1 ? this.singleWidth : this.multipleSize
|
||||||
|
)
|
||||||
|
},
|
||||||
|
imageHeight() {
|
||||||
|
return uni.$u.addUnit(
|
||||||
|
this.urls.length === 1 ? this.singleHeight : this.multipleSize
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
|
||||||
|
// 因为用户在某些特殊的情况下,需要让文字与相册的宽度相等,所以这里事件的形式对外发送
|
||||||
|
albumWidth() {
|
||||||
|
let width = 0
|
||||||
|
if (this.urls.length === 1) {
|
||||||
|
width = this.singleWidth
|
||||||
|
} else {
|
||||||
|
width =
|
||||||
|
this.showUrls[0].length * this.multipleSize +
|
||||||
|
this.space * (this.showUrls[0].length - 1)
|
||||||
|
}
|
||||||
|
this.$emit('albumWidth', width)
|
||||||
|
return width
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 预览图片
|
||||||
|
onPreviewTap(url) {
|
||||||
|
const urls = this.urls.map((item) => {
|
||||||
|
return this.getSrc(item)
|
||||||
|
})
|
||||||
|
uni.previewImage({
|
||||||
|
current: url,
|
||||||
|
urls
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取图片的路径
|
||||||
|
getSrc(item) {
|
||||||
|
return uni.$u.test.object(item)
|
||||||
|
? (this.keyName && item[this.keyName]) || item.src
|
||||||
|
: item
|
||||||
|
},
|
||||||
|
// 单图时,获取图片的尺寸
|
||||||
|
// 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸
|
||||||
|
// 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent)
|
||||||
|
getImageRect() {
|
||||||
|
const src = this.getSrc(this.urls[0])
|
||||||
|
uni.getImageInfo({
|
||||||
|
src,
|
||||||
|
success: (res) => {
|
||||||
|
// 判断图片横向还是竖向展示方式
|
||||||
|
const isHorizotal = res.width >= res.height
|
||||||
|
this.singleWidth = isHorizotal
|
||||||
|
? this.singleSize
|
||||||
|
: (res.width / res.height) * this.singleSize
|
||||||
|
this.singleHeight = !isHorizotal
|
||||||
|
? this.singleSize
|
||||||
|
: (res.height / res.width) * this.singleWidth
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
this.getComponentWidth()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取组件的宽度
|
||||||
|
async getComponentWidth() {
|
||||||
|
// 延时一定时间,以获取dom尺寸
|
||||||
|
await uni.$u.sleep(30)
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.$uGetRect('.u-album__row').then((size) => {
|
||||||
|
this.singleWidth = size.width * this.singlePercent
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 这里ref="u-album__row"所在的标签为通过for循环出来,导致this.$refs['u-album__row']是一个数组
|
||||||
|
const ref = this.$refs['u-album__row'][0]
|
||||||
|
ref &&
|
||||||
|
dom.getComponentRect(ref, (res) => {
|
||||||
|
this.singleWidth = res.size.width * this.singlePercent
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../libs/css/components.scss';
|
||||||
|
|
||||||
|
.u-album {
|
||||||
|
@include flex(column);
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
@include flex(row);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
@include flex(row);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
44
node_modules/uview-ui/components/u-alert/props.js
generated
vendored
Normal file
44
node_modules/uview-ui/components/u-alert/props.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 显示文字
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.alert.title
|
||||||
|
},
|
||||||
|
// 主题,success/warning/info/error
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.alert.type
|
||||||
|
},
|
||||||
|
// 辅助性文字
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.alert.description
|
||||||
|
},
|
||||||
|
// 是否可关闭
|
||||||
|
closable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.alert.closable
|
||||||
|
},
|
||||||
|
// 是否显示图标
|
||||||
|
showIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.alert.showIcon
|
||||||
|
},
|
||||||
|
// 浅或深色调,light-浅色,dark-深色
|
||||||
|
effect: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.alert.effect
|
||||||
|
},
|
||||||
|
// 文字是否居中
|
||||||
|
center: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.alert.center
|
||||||
|
},
|
||||||
|
// 字体大小
|
||||||
|
fontSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.alert.fontSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
243
node_modules/uview-ui/components/u-alert/u-alert.vue
generated
vendored
Normal file
243
node_modules/uview-ui/components/u-alert/u-alert.vue
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
<template>
|
||||||
|
<u-transition
|
||||||
|
mode="fade"
|
||||||
|
:show="show"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-alert"
|
||||||
|
:class="[`u-alert--${type}--${effect}`]"
|
||||||
|
@tap.stop="clickHandler"
|
||||||
|
:style="[$u.addStyle(customStyle)]"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-alert__icon"
|
||||||
|
v-if="showIcon"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
:name="iconName"
|
||||||
|
size="18"
|
||||||
|
:color="iconColor"
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="u-alert__content"
|
||||||
|
:style="[{
|
||||||
|
paddingRight: closable ? '20px' : 0
|
||||||
|
}]"
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
class="u-alert__content__title"
|
||||||
|
v-if="title"
|
||||||
|
:style="[{
|
||||||
|
fontSize: $u.addUnit(fontSize),
|
||||||
|
textAlign: center ? 'center' : 'left'
|
||||||
|
}]"
|
||||||
|
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
|
||||||
|
>{{ title }}</text>
|
||||||
|
<text
|
||||||
|
class="u-alert__content__desc"
|
||||||
|
v-if="description"
|
||||||
|
:style="[{
|
||||||
|
fontSize: $u.addUnit(fontSize),
|
||||||
|
textAlign: center ? 'center' : 'left'
|
||||||
|
}]"
|
||||||
|
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
|
||||||
|
>{{ description }}</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="u-alert__close"
|
||||||
|
v-if="closable"
|
||||||
|
@tap.stop="closeHandler"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
name="close"
|
||||||
|
:color="iconColor"
|
||||||
|
size="15"
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* Alert 警告提示
|
||||||
|
* @description 警告提示,展现需要关注的信息。
|
||||||
|
* @tutorial https://www.uviewui.com/components/alertTips.html
|
||||||
|
*
|
||||||
|
* @property {String} title 显示的文字
|
||||||
|
* @property {String} type 使用预设的颜色 (默认 'warning' )
|
||||||
|
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
|
||||||
|
* @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
|
||||||
|
* @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
|
||||||
|
* @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
|
||||||
|
* @property {Boolean} center 文字是否居中 (默认 false )
|
||||||
|
* @property {String | Number} fontSize 字体大小 (默认 14 )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
* @event {Function} click 点击组件时触发
|
||||||
|
* @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-alert',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iconColor() {
|
||||||
|
return this.effect === 'light' ? this.type : '#fff'
|
||||||
|
},
|
||||||
|
// 不同主题对应不同的图标
|
||||||
|
iconName() {
|
||||||
|
switch (this.type) {
|
||||||
|
case 'success':
|
||||||
|
return 'checkmark-circle-fill';
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
return 'close-circle-fill';
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
return 'error-circle-fill';
|
||||||
|
break;
|
||||||
|
case 'info':
|
||||||
|
return 'info-circle-fill';
|
||||||
|
break;
|
||||||
|
case 'primary':
|
||||||
|
return 'more-circle-fill';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 'error-circle-fill';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击内容
|
||||||
|
clickHandler() {
|
||||||
|
this.$emit('click')
|
||||||
|
},
|
||||||
|
// 点击关闭按钮
|
||||||
|
closeHandler() {
|
||||||
|
this.show = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-alert {
|
||||||
|
position: relative;
|
||||||
|
background-color: $u-primary;
|
||||||
|
padding: 8px 10px;
|
||||||
|
@include flex(row);
|
||||||
|
align-items: center;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
|
||||||
|
&--primary--dark {
|
||||||
|
background-color: $u-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary--light {
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error--dark {
|
||||||
|
background-color: $u-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error--light {
|
||||||
|
background-color: #FEF0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success--dark {
|
||||||
|
background-color: $u-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success--light {
|
||||||
|
background-color: #f5fff0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning--dark {
|
||||||
|
background-color: $u-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning--light {
|
||||||
|
background-color: #FDF6EC;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info--dark {
|
||||||
|
background-color: $u-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info--light {
|
||||||
|
background-color: #f4f4f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
@include flex(column);
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
color: $u-main-color;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__desc {
|
||||||
|
color: $u-main-color;
|
||||||
|
font-size: 14px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title--dark,
|
||||||
|
&__desc--dark {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--primary--light,
|
||||||
|
&__text--primary--light {
|
||||||
|
color: $u-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--success--light,
|
||||||
|
&__text--success--light {
|
||||||
|
color: $u-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--warning--light,
|
||||||
|
&__text--warning--light {
|
||||||
|
color: $u-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--error--light,
|
||||||
|
&__text--error--light {
|
||||||
|
color: $u-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--info--light,
|
||||||
|
&__text--info--light {
|
||||||
|
color: $u-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__close {
|
||||||
|
position: absolute;
|
||||||
|
top: 11px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
52
node_modules/uview-ui/components/u-avatar-group/props.js
generated
vendored
Normal file
52
node_modules/uview-ui/components/u-avatar-group/props.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 头像图片组
|
||||||
|
urls: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.avatarGroup.urls
|
||||||
|
},
|
||||||
|
// 最多展示的头像数量
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.avatarGroup.maxCount
|
||||||
|
},
|
||||||
|
// 头像形状
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatarGroup.shape
|
||||||
|
},
|
||||||
|
// 图片裁剪模式
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatarGroup.mode
|
||||||
|
},
|
||||||
|
// 超出maxCount时是否显示查看更多的提示
|
||||||
|
showMore: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.avatarGroup.showMore
|
||||||
|
},
|
||||||
|
// 头像大小
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.avatarGroup.size
|
||||||
|
},
|
||||||
|
// 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||||
|
keyName: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatarGroup.keyName
|
||||||
|
},
|
||||||
|
// 头像之间的遮挡比例
|
||||||
|
gap: {
|
||||||
|
type: [String, Number],
|
||||||
|
validator(value) {
|
||||||
|
return value >= 0 && value <= 1
|
||||||
|
},
|
||||||
|
default: uni.$u.props.avatarGroup.gap
|
||||||
|
},
|
||||||
|
// 需额外显示的值
|
||||||
|
extraValue: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: uni.$u.props.avatarGroup.extraValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
node_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue
generated
vendored
Normal file
103
node_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-avatar-group">
|
||||||
|
<view
|
||||||
|
class="u-avatar-group__item"
|
||||||
|
v-for="(item, index) in showUrl"
|
||||||
|
:key="index"
|
||||||
|
:style="{
|
||||||
|
marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<u-avatar
|
||||||
|
:size="size"
|
||||||
|
:shape="shape"
|
||||||
|
:mode="mode"
|
||||||
|
:src="$u.test.object(item) ? keyName && item[keyName] || item.url : item"
|
||||||
|
></u-avatar>
|
||||||
|
<view
|
||||||
|
class="u-avatar-group__item__show-more"
|
||||||
|
v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
|
||||||
|
@tap="clickHandler"
|
||||||
|
>
|
||||||
|
<u--text
|
||||||
|
color="#ffffff"
|
||||||
|
:size="size * 0.4"
|
||||||
|
:text="`+${extraValue || urls.length - showUrl.length}`"
|
||||||
|
align="center"
|
||||||
|
customStyle="justify-content: center"
|
||||||
|
></u--text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* AvatarGroup 头像组
|
||||||
|
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
|
||||||
|
* @tutorial https://www.uviewui.com/components/avatar.html
|
||||||
|
*
|
||||||
|
* @property {Array} urls 头像图片组 (默认 [] )
|
||||||
|
* @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
|
||||||
|
* @property {String} shape 头像形状( 'circle' (默认) | 'square' )
|
||||||
|
* @property {String} mode 图片裁剪模式(默认 'scaleToFill' )
|
||||||
|
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
|
||||||
|
* @property {String | Number} size 头像大小 (默认 40 )
|
||||||
|
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||||
|
* @property {String | Number} gap 头像之间的遮挡比例(0.4代表遮挡40%) (默认 0.5 )
|
||||||
|
* @property {String | Number} extraValue 需额外显示的值
|
||||||
|
* @event {Function} showMore 头像组更多点击
|
||||||
|
* @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-avatar-group',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showUrl() {
|
||||||
|
return this.urls.slice(0, this.maxCount)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clickHandler() {
|
||||||
|
this.$emit('showMore')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-avatar-group {
|
||||||
|
@include flex;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
margin-left: -10px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&--no-indent {
|
||||||
|
// 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__show-more {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
@include flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
78
node_modules/uview-ui/components/u-avatar/props.js
generated
vendored
Normal file
78
node_modules/uview-ui/components/u-avatar/props.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 头像图片路径(不能为相对路径)
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.src
|
||||||
|
},
|
||||||
|
// 头像形状,circle-圆形,square-方形
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.shape
|
||||||
|
},
|
||||||
|
// 头像尺寸
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.avatar.size
|
||||||
|
},
|
||||||
|
// 裁剪模式
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.mode
|
||||||
|
},
|
||||||
|
// 显示的文字
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.text
|
||||||
|
},
|
||||||
|
// 背景色
|
||||||
|
bgColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.bgColor
|
||||||
|
},
|
||||||
|
// 文字颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.color
|
||||||
|
},
|
||||||
|
// 文字大小
|
||||||
|
fontSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.avatar.fontSize
|
||||||
|
},
|
||||||
|
// 显示的图标
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.icon
|
||||||
|
},
|
||||||
|
// 显示小程序头像,只对百度,微信,QQ小程序有效
|
||||||
|
mpAvatar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.avatar.mpAvatar
|
||||||
|
},
|
||||||
|
// 是否使用随机背景色
|
||||||
|
randomBgColor: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.avatar.randomBgColor
|
||||||
|
},
|
||||||
|
// 加载失败的默认头像(组件有内置默认图片)
|
||||||
|
defaultUrl: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.defaultUrl
|
||||||
|
},
|
||||||
|
// 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
|
||||||
|
colorIndex: {
|
||||||
|
type: [String, Number],
|
||||||
|
// 校验参数规则,索引在0-19之间
|
||||||
|
validator(n) {
|
||||||
|
return uni.$u.test.range(n, [0, 19]) || n === ''
|
||||||
|
},
|
||||||
|
default: uni.$u.props.avatar.colorIndex
|
||||||
|
},
|
||||||
|
// 组件标识符
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.avatar.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
172
node_modules/uview-ui/components/u-avatar/u-avatar.vue
generated
vendored
Normal file
172
node_modules/uview-ui/components/u-avatar/u-avatar.vue
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="u-avatar"
|
||||||
|
:class="[`u-avatar--${shape}`]"
|
||||||
|
:style="[{
|
||||||
|
backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : $u.random(0, 19)] : bgColor) : 'transparent',
|
||||||
|
width: $u.addUnit(size),
|
||||||
|
height: $u.addUnit(size),
|
||||||
|
}, $u.addStyle(customStyle)]"
|
||||||
|
@tap="clickHandler"
|
||||||
|
>
|
||||||
|
<slot>
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
|
||||||
|
<open-data
|
||||||
|
v-if="mpAvatar && allowMp"
|
||||||
|
type="userAvatarUrl"
|
||||||
|
:style="[{
|
||||||
|
width: $u.addUnit(size),
|
||||||
|
height: $u.addUnit(size)
|
||||||
|
}]"
|
||||||
|
/>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU -->
|
||||||
|
<template v-if="mpAvatar && allowMp"></template>
|
||||||
|
<!-- #endif -->
|
||||||
|
<u-icon
|
||||||
|
v-else-if="icon"
|
||||||
|
:name="icon"
|
||||||
|
:size="fontSize"
|
||||||
|
:color="color"
|
||||||
|
></u-icon>
|
||||||
|
<u--text
|
||||||
|
v-else-if="text"
|
||||||
|
:text="text"
|
||||||
|
:size="fontSize"
|
||||||
|
:color="color"
|
||||||
|
align="center"
|
||||||
|
customStyle="justify-content: center"
|
||||||
|
></u--text>
|
||||||
|
<image
|
||||||
|
class="u-avatar__image"
|
||||||
|
v-else
|
||||||
|
:class="[`u-avatar__image--${shape}`]"
|
||||||
|
:src="avatarUrl || defaultUrl"
|
||||||
|
:mode="mode"
|
||||||
|
@error="errorHandler"
|
||||||
|
:style="[{
|
||||||
|
width: $u.addUnit(size),
|
||||||
|
height: $u.addUnit(size)
|
||||||
|
}]"
|
||||||
|
></image>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
const base64Avatar =
|
||||||
|
"data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
|
||||||
|
/**
|
||||||
|
* Avatar 头像
|
||||||
|
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
|
||||||
|
* @tutorial https://www.uviewui.com/components/avatar.html
|
||||||
|
*
|
||||||
|
* @property {String} src 头像路径,如加载失败,将会显示默认头像(不能为相对路径)
|
||||||
|
* @property {String} shape 头像形状 ( circle (默认) | square)
|
||||||
|
* @property {String | Number} size 头像尺寸,可以为指定字符串(large, default, mini),或者数值 (默认 40 )
|
||||||
|
* @property {String} mode 头像图片的裁剪类型,与uni的image组件的mode参数一致,如效果达不到需求,可尝试传widthFix值 (默认 'scaleToFill' )
|
||||||
|
* @property {String} text 用文字替代图片,级别优先于src
|
||||||
|
* @property {String} bgColor 背景颜色,一般显示文字时用 (默认 '#c0c4cc' )
|
||||||
|
* @property {String} color 文字颜色 (默认 '#ffffff' )
|
||||||
|
* @property {String | Number} fontSize 文字大小 (默认 18 )
|
||||||
|
* @property {String} icon 显示的图标
|
||||||
|
* @property {Boolean} mpAvatar 显示小程序头像,只对百度,微信,QQ小程序有效 (默认 false )
|
||||||
|
* @property {Boolean} randomBgColor 是否使用随机背景色 (默认 false )
|
||||||
|
* @property {String} defaultUrl 加载失败的默认头像(组件有内置默认图片)
|
||||||
|
* @property {String | Number} colorIndex 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
|
||||||
|
* @property {String} name 组件标识符 (默认 'level' )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @event {Function} click 点击组件时触发 index: 用户传递的标识符
|
||||||
|
* @example <u-avatar :src="src" mode="square"></u-avatar>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-avatar',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 如果配置randomBgColor参数为true,在图标或者文字的模式下,会随机从中取出一个颜色值当做背景色
|
||||||
|
colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2',
|
||||||
|
'#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee',
|
||||||
|
'#73d1f1',
|
||||||
|
'#80a7dc'
|
||||||
|
],
|
||||||
|
avatarUrl: this.src,
|
||||||
|
allowMp: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听头像src的变化,赋值给内部的avatarUrl变量,因为图片加载失败时,需要修改图片的src为默认值
|
||||||
|
// 而组件内部不能直接修改props的值,所以需要一个中间变量
|
||||||
|
src: {
|
||||||
|
immediate: true,
|
||||||
|
handler(newVal) {
|
||||||
|
this.avatarUrl = newVal
|
||||||
|
// 如果没有传src,则主动触发error事件,用于显示默认的头像,否则src为''空字符等的时候,会无内容展示
|
||||||
|
if(!newVal) {
|
||||||
|
this.errorHandler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
imageStyle() {
|
||||||
|
const style = {}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
// 目前只有这几个小程序平台具有open-data标签
|
||||||
|
// 其他平台可以通过uni.getUserInfo类似接口获取信息,但是需要弹窗授权(首次),不合符组件逻辑
|
||||||
|
// 故目前自动获取小程序头像只支持这几个平台
|
||||||
|
// #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU
|
||||||
|
this.allowMp = true
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
|
||||||
|
isImg() {
|
||||||
|
return this.src.indexOf('/') !== -1
|
||||||
|
},
|
||||||
|
// 图片加载时失败时触发
|
||||||
|
errorHandler() {
|
||||||
|
this.avatarUrl = this.defaultUrl || base64Avatar
|
||||||
|
},
|
||||||
|
clickHandler() {
|
||||||
|
this.$emit('click', this.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-avatar {
|
||||||
|
@include flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&--circle {
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--square {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
&--circle {
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--square {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
54
node_modules/uview-ui/components/u-back-top/props.js
generated
vendored
Normal file
54
node_modules/uview-ui/components/u-back-top/props.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 返回顶部的形状,circle-圆形,square-方形
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.backtop.mode
|
||||||
|
},
|
||||||
|
// 自定义图标
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.backtop.icon
|
||||||
|
},
|
||||||
|
// 提示文字
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.backtop.text
|
||||||
|
},
|
||||||
|
// 返回顶部滚动时间
|
||||||
|
duration: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.duration
|
||||||
|
},
|
||||||
|
// 滚动距离
|
||||||
|
scrollTop: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.scrollTop
|
||||||
|
},
|
||||||
|
// 距离顶部多少距离显示,单位px
|
||||||
|
top: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.top
|
||||||
|
},
|
||||||
|
// 返回顶部按钮到底部的距离,单位px
|
||||||
|
bottom: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.bottom
|
||||||
|
},
|
||||||
|
// 返回顶部按钮到右边的距离,单位px
|
||||||
|
right: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.right
|
||||||
|
},
|
||||||
|
// 层级
|
||||||
|
zIndex: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.backtop.zIndex
|
||||||
|
},
|
||||||
|
// 图标的样式,对象形式
|
||||||
|
iconStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: uni.$u.props.backtop.iconStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
node_modules/uview-ui/components/u-back-top/u-back-top.vue
generated
vendored
Normal file
129
node_modules/uview-ui/components/u-back-top/u-back-top.vue
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<u-transition
|
||||||
|
mode="fade"
|
||||||
|
:customStyle="backTopStyle"
|
||||||
|
:show="show"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-back-top"
|
||||||
|
:style="[contentStyle]"
|
||||||
|
v-if="!$slots.default && !$slots.$default"
|
||||||
|
@click="backToTop"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
:name="icon"
|
||||||
|
:custom-style="iconStyle"
|
||||||
|
></u-icon>
|
||||||
|
<text
|
||||||
|
v-if="text"
|
||||||
|
class="u-back-top__text"
|
||||||
|
>{{text}}</text>
|
||||||
|
</view>
|
||||||
|
<slot v-else />
|
||||||
|
</u-transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const dom = weex.requireModule('dom')
|
||||||
|
// #endif
|
||||||
|
/**
|
||||||
|
* backTop 返回顶部
|
||||||
|
* @description 本组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
|
||||||
|
* @tutorial https://uviewui.com/components/backTop.html
|
||||||
|
*
|
||||||
|
* @property {String} mode 返回顶部的形状,circle-圆形,square-方形 (默认 'circle' )
|
||||||
|
* @property {String} icon 自定义图标 (默认 'arrow-upward' ) 见官方文档示例
|
||||||
|
* @property {String} text 提示文字
|
||||||
|
* @property {String | Number} duration 返回顶部滚动时间 (默认 100)
|
||||||
|
* @property {String | Number} scrollTop 滚动距离 (默认 0 )
|
||||||
|
* @property {String | Number} top 距离顶部多少距离显示,单位px (默认 400 )
|
||||||
|
* @property {String | Number} bottom 返回顶部按钮到底部的距离,单位px (默认 100 )
|
||||||
|
* @property {String | Number} right 返回顶部按钮到右边的距离,单位px (默认 20 )
|
||||||
|
* @property {String | Number} zIndex 层级 (默认 9 )
|
||||||
|
* @property {Object<Object>} iconStyle 图标的样式,对象形式 (默认 {color: '#909399',fontSize: '19px'})
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @example <u-back-top :scrollTop="scrollTop"></u-back-top>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-back-top',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
computed: {
|
||||||
|
backTopStyle() {
|
||||||
|
// 动画组件样式
|
||||||
|
const style = {
|
||||||
|
bottom: uni.$u.addUnit(this.bottom),
|
||||||
|
right: uni.$u.addUnit(this.right),
|
||||||
|
width: '40px',
|
||||||
|
height: '40px',
|
||||||
|
position: 'fixed',
|
||||||
|
zIndex: 10,
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
},
|
||||||
|
show() {
|
||||||
|
return uni.$u.getPx(this.scrollTop) > uni.$u.getPx(this.top)
|
||||||
|
},
|
||||||
|
contentStyle() {
|
||||||
|
const style = {}
|
||||||
|
let radius = 0
|
||||||
|
// 是否圆形
|
||||||
|
if(this.mode === 'circle') {
|
||||||
|
radius = '100px'
|
||||||
|
} else {
|
||||||
|
radius = '4px'
|
||||||
|
}
|
||||||
|
// 为了兼容安卓nvue,只能这么分开写
|
||||||
|
style.borderTopLeftRadius = radius
|
||||||
|
style.borderTopRightRadius = radius
|
||||||
|
style.borderBottomLeftRadius = radius
|
||||||
|
style.borderBottomRightRadius = radius
|
||||||
|
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
backToTop() {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if (!this.$parent.$refs['u-back-top']) {
|
||||||
|
uni.$u.error(`nvue页面需要给页面最外层元素设置"ref='u-back-top'`)
|
||||||
|
}
|
||||||
|
dom.scrollToElement(this.$parent.$refs['u-back-top'], {
|
||||||
|
offset: 0
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: 0,
|
||||||
|
duration: this.duration
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
this.$emit('click')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../libs/css/components.scss';
|
||||||
|
$u-back-top-flex:1 !default;
|
||||||
|
$u-back-top-height:100% !default;
|
||||||
|
$u-back-top-background-color:#E1E1E1 !default;
|
||||||
|
$u-back-top-tips-font-size:12px !default;
|
||||||
|
.u-back-top {
|
||||||
|
@include flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex:$u-back-top-flex;
|
||||||
|
height: $u-back-top-height;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: $u-back-top-background-color;
|
||||||
|
|
||||||
|
&__tips {
|
||||||
|
font-size:$u-back-top-tips-font-size;
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
72
node_modules/uview-ui/components/u-badge/props.js
generated
vendored
Normal file
72
node_modules/uview-ui/components/u-badge/props.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 是否显示圆点
|
||||||
|
isDot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.badge.isDot
|
||||||
|
},
|
||||||
|
// 显示的内容
|
||||||
|
value: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: uni.$u.props.badge.value
|
||||||
|
},
|
||||||
|
// 是否显示
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.badge.show
|
||||||
|
},
|
||||||
|
// 最大值,超过最大值会显示 '{max}+'
|
||||||
|
max: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: uni.$u.props.badge.max
|
||||||
|
},
|
||||||
|
// 主题类型,error|warning|success|primary
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.badge.type
|
||||||
|
},
|
||||||
|
// 当数值为 0 时,是否展示 Badge
|
||||||
|
showZero: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.badge.showZero
|
||||||
|
},
|
||||||
|
// 背景颜色,优先级比type高,如设置,type参数会失效
|
||||||
|
bgColor: {
|
||||||
|
type: [String, null],
|
||||||
|
default: uni.$u.props.badge.bgColor
|
||||||
|
},
|
||||||
|
// 字体颜色
|
||||||
|
color: {
|
||||||
|
type: [String, null],
|
||||||
|
default: uni.$u.props.badge.color
|
||||||
|
},
|
||||||
|
// 徽标形状,circle-四角均为圆角,horn-左下角为直角
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.badge.shape
|
||||||
|
},
|
||||||
|
// 设置数字的显示方式,overflow|ellipsis|limit
|
||||||
|
// overflow会根据max字段判断,超出显示`${max}+`
|
||||||
|
// ellipsis会根据max判断,超出显示`${max}...`
|
||||||
|
// limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
|
||||||
|
numberType: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.badge.numberType
|
||||||
|
},
|
||||||
|
// 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
|
||||||
|
offset: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.badge.offset
|
||||||
|
},
|
||||||
|
// 是否反转背景和字体颜色
|
||||||
|
inverted: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.badge.inverted
|
||||||
|
},
|
||||||
|
// 是否绝对定位
|
||||||
|
absolute: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.badge.absolute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
171
node_modules/uview-ui/components/u-badge/u-badge.vue
generated
vendored
Normal file
171
node_modules/uview-ui/components/u-badge/u-badge.vue
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<text
|
||||||
|
v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
|
||||||
|
:class="[isDot ? 'u-badge--dot' : 'u-badge--not-dot', inverted && 'u-badge--inverted', shape === 'horn' && 'u-badge--horn', `u-badge--${type}${inverted ? '--inverted' : ''}`]"
|
||||||
|
:style="[$u.addStyle(customStyle), badgeStyle]"
|
||||||
|
class="u-badge"
|
||||||
|
>{{ isDot ? '' :showValue }}</text>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* badge 徽标数
|
||||||
|
* @description 该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
|
||||||
|
* @tutorial https://uviewui.com/components/badge.html
|
||||||
|
*
|
||||||
|
* @property {Boolean} isDot 是否显示圆点 (默认 false )
|
||||||
|
* @property {String | Number} value 显示的内容
|
||||||
|
* @property {Boolean} show 是否显示 (默认 true )
|
||||||
|
* @property {String | Number} max 最大值,超过最大值会显示 '{max}+' (默认999)
|
||||||
|
* @property {String} type 主题类型,error|warning|success|primary (默认 'error' )
|
||||||
|
* @property {Boolean} showZero 当数值为 0 时,是否展示 Badge (默认 false )
|
||||||
|
* @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效
|
||||||
|
* @property {String} color 字体颜色 (默认 '#ffffff' )
|
||||||
|
* @property {String} shape 徽标形状,circle-四角均为圆角,horn-左下角为直角 (默认 'circle' )
|
||||||
|
* @property {String} numberType 设置数字的显示方式,overflow|ellipsis|limit (默认 'overflow' )
|
||||||
|
* @property {Array}} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
|
||||||
|
* @property {Boolean} inverted 是否反转背景和字体颜色(默认 false )
|
||||||
|
* @property {Boolean} absolute 是否绝对定位(默认 false )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
* @example <u-badge :type="type" :count="count"></u-badge>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-badge',
|
||||||
|
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
|
||||||
|
computed: {
|
||||||
|
// 是否将badge中心与父组件右上角重合
|
||||||
|
boxStyle() {
|
||||||
|
let style = {};
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
// 整个组件的样式
|
||||||
|
badgeStyle() {
|
||||||
|
const style = {}
|
||||||
|
if(this.color) {
|
||||||
|
style.color = this.color
|
||||||
|
}
|
||||||
|
if (this.bgColor && !this.inverted) {
|
||||||
|
style.backgroundColor = this.bgColor
|
||||||
|
}
|
||||||
|
if (this.absolute) {
|
||||||
|
style.position = 'absolute'
|
||||||
|
// 如果有设置offset参数
|
||||||
|
if(this.offset.length) {
|
||||||
|
// top和right分为为offset的第一个和第二个值,如果没有第二个值,则right等于top
|
||||||
|
const top = this.offset[0]
|
||||||
|
const right = this.offset[1] || top
|
||||||
|
style.top = uni.$u.addUnit(top)
|
||||||
|
style.right = uni.$u.addUnit(right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
},
|
||||||
|
showValue() {
|
||||||
|
switch (this.numberType) {
|
||||||
|
case "overflow":
|
||||||
|
return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
|
||||||
|
break;
|
||||||
|
case "ellipsis":
|
||||||
|
return Number(this.value) > Number(this.max) ? "..." : this.value
|
||||||
|
break;
|
||||||
|
case "limit":
|
||||||
|
return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
|
||||||
|
Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
|
||||||
|
1e3 * 100) / 100 + "k" : this.value
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return Number(this.value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
$u-badge-primary: $u-primary !default;
|
||||||
|
$u-badge-error: $u-error !default;
|
||||||
|
$u-badge-success: $u-success !default;
|
||||||
|
$u-badge-info: $u-info !default;
|
||||||
|
$u-badge-warning: $u-warning !default;
|
||||||
|
$u-badge-dot-radius: 100px !default;
|
||||||
|
$u-badge-dot-size: 8px !default;
|
||||||
|
$u-badge-dot-right: 4px !default;
|
||||||
|
$u-badge-dot-top: 0 !default;
|
||||||
|
$u-badge-text-font-size: 11px !default;
|
||||||
|
$u-badge-text-right: 10px !default;
|
||||||
|
$u-badge-text-padding: 2px 5px !default;
|
||||||
|
$u-badge-text-align: center !default;
|
||||||
|
$u-badge-text-color: #FFFFFF !default;
|
||||||
|
|
||||||
|
.u-badge {
|
||||||
|
border-top-right-radius: $u-badge-dot-radius;
|
||||||
|
border-top-left-radius: $u-badge-dot-radius;
|
||||||
|
border-bottom-left-radius: $u-badge-dot-radius;
|
||||||
|
border-bottom-right-radius: $u-badge-dot-radius;
|
||||||
|
@include flex;
|
||||||
|
line-height: $u-badge-text-font-size;
|
||||||
|
text-align: $u-badge-text-align;
|
||||||
|
font-size: $u-badge-text-font-size;
|
||||||
|
color: $u-badge-text-color;
|
||||||
|
|
||||||
|
&--dot {
|
||||||
|
height: $u-badge-dot-size;
|
||||||
|
width: $u-badge-dot-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inverted {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--not-dot {
|
||||||
|
padding: $u-badge-text-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--horn {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
background-color: $u-badge-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary--inverted {
|
||||||
|
color: $u-badge-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background-color: $u-badge-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error--inverted {
|
||||||
|
color: $u-badge-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background-color: $u-badge-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success--inverted {
|
||||||
|
color: $u-badge-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
background-color: $u-badge-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info--inverted {
|
||||||
|
color: $u-badge-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
background-color: $u-badge-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning--inverted {
|
||||||
|
color: $u-badge-warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
46
node_modules/uview-ui/components/u-button/nvue.scss
generated
vendored
Normal file
46
node_modules/uview-ui/components/u-button/nvue.scss
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
$u-button-active-opacity:0.75 !default;
|
||||||
|
$u-button-loading-text-margin-left:4px !default;
|
||||||
|
$u-button-text-color: #FFFFFF !default;
|
||||||
|
$u-button-text-plain-error-color:$u-error !default;
|
||||||
|
$u-button-text-plain-warning-color:$u-warning !default;
|
||||||
|
$u-button-text-plain-success-color:$u-success !default;
|
||||||
|
$u-button-text-plain-info-color:$u-info !default;
|
||||||
|
$u-button-text-plain-primary-color:$u-primary !default;
|
||||||
|
.u-button {
|
||||||
|
&--active {
|
||||||
|
opacity: $u-button-active-opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--active--plain {
|
||||||
|
background-color: rgb(217, 217, 217);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__loading-text {
|
||||||
|
margin-left:$u-button-loading-text-margin-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text,
|
||||||
|
&__loading-text {
|
||||||
|
color:$u-button-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--plain--error {
|
||||||
|
color:$u-button-text-plain-error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--plain--warning {
|
||||||
|
color:$u-button-text-plain-warning-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--plain--success{
|
||||||
|
color:$u-button-text-plain-success-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--plain--info {
|
||||||
|
color:$u-button-text-plain-info-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text--plain--primary {
|
||||||
|
color:$u-button-text-plain-primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
161
node_modules/uview-ui/components/u-button/props.js
generated
vendored
Normal file
161
node_modules/uview-ui/components/u-button/props.js
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* @Author : LQ
|
||||||
|
* @Description :
|
||||||
|
* @version : 1.0
|
||||||
|
* @Date : 2021-08-16 10:04:04
|
||||||
|
* @LastAuthor : LQ
|
||||||
|
* @lastTime : 2021-08-16 10:04:24
|
||||||
|
* @FilePath : /u-view2.0/uview-ui/components/u-button/props.js
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 是否细边框
|
||||||
|
hairline: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.hairline
|
||||||
|
},
|
||||||
|
// 按钮的预置样式,info,primary,error,warning,success
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.type
|
||||||
|
},
|
||||||
|
// 按钮尺寸,large,normal,small,mini
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.size
|
||||||
|
},
|
||||||
|
// 按钮形状,circle(两边为半圆),square(带圆角)
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.shape
|
||||||
|
},
|
||||||
|
// 按钮是否镂空
|
||||||
|
plain: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.plain
|
||||||
|
},
|
||||||
|
// 是否禁止状态
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.disabled
|
||||||
|
},
|
||||||
|
// 是否加载中
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.loading
|
||||||
|
},
|
||||||
|
// 加载中提示文字
|
||||||
|
loadingText: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.loadingText
|
||||||
|
},
|
||||||
|
// 加载状态图标类型
|
||||||
|
loadingMode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.loadingMode
|
||||||
|
},
|
||||||
|
// 加载图标大小
|
||||||
|
loadingSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.loadingSize
|
||||||
|
},
|
||||||
|
// 开放能力,具体请看uniapp稳定关于button组件部分说明
|
||||||
|
// https://uniapp.dcloud.io/component/button
|
||||||
|
openType: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.openType
|
||||||
|
},
|
||||||
|
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
|
||||||
|
// 取值为submit(提交表单),reset(重置表单)
|
||||||
|
formType: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.formType
|
||||||
|
},
|
||||||
|
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
|
||||||
|
// 只微信小程序、QQ小程序有效
|
||||||
|
appParameter: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.appParameter
|
||||||
|
},
|
||||||
|
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
|
||||||
|
hoverStopPropagation: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.hoverStopPropagation
|
||||||
|
},
|
||||||
|
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
|
||||||
|
lang: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.lang
|
||||||
|
},
|
||||||
|
// 会话来源,open-type="contact"时有效。只微信小程序有效
|
||||||
|
sessionFrom: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.sessionFrom
|
||||||
|
},
|
||||||
|
// 会话内消息卡片标题,open-type="contact"时有效
|
||||||
|
// 默认当前标题,只微信小程序有效
|
||||||
|
sendMessageTitle: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.sendMessageTitle
|
||||||
|
},
|
||||||
|
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
|
||||||
|
// 默认当前分享路径,只微信小程序有效
|
||||||
|
sendMessagePath: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.sendMessagePath
|
||||||
|
},
|
||||||
|
// 会话内消息卡片图片,open-type="contact"时有效
|
||||||
|
// 默认当前页面截图,只微信小程序有效
|
||||||
|
sendMessageImg: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.sendMessageImg
|
||||||
|
},
|
||||||
|
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
|
||||||
|
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效
|
||||||
|
showMessageCard: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.button.showMessageCard
|
||||||
|
},
|
||||||
|
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
|
||||||
|
dataName: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.dataName
|
||||||
|
},
|
||||||
|
// 节流,一定时间内只能触发一次
|
||||||
|
throttleTime: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.throttleTime
|
||||||
|
},
|
||||||
|
// 按住后多久出现点击态,单位毫秒
|
||||||
|
hoverStartTime: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.hoverStartTime
|
||||||
|
},
|
||||||
|
// 手指松开后点击态保留时间,单位毫秒
|
||||||
|
hoverStayTime: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.hoverStayTime
|
||||||
|
},
|
||||||
|
// 按钮文字,之所以通过props传入,是因为slot传入的话
|
||||||
|
// nvue中无法控制文字的样式
|
||||||
|
text: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.button.text
|
||||||
|
},
|
||||||
|
// 按钮图标
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.icon
|
||||||
|
},
|
||||||
|
// 按钮图标
|
||||||
|
iconColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.icon
|
||||||
|
},
|
||||||
|
// 按钮颜色,支持传入linear-gradient渐变色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.button.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
490
node_modules/uview-ui/components/u-button/u-button.vue
generated
vendored
Normal file
490
node_modules/uview-ui/components/u-button/u-button.vue
generated
vendored
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<button
|
||||||
|
:hover-start-time="Number(hoverStartTime)"
|
||||||
|
:hover-stay-time="Number(hoverStayTime)"
|
||||||
|
:form-type="formType"
|
||||||
|
:open-type="openType"
|
||||||
|
:app-parameter="appParameter"
|
||||||
|
:hover-stop-propagation="hoverStopPropagation"
|
||||||
|
:send-message-title="sendMessageTitle"
|
||||||
|
:send-message-path="sendMessagePath"
|
||||||
|
:lang="lang"
|
||||||
|
:data-name="dataName"
|
||||||
|
:session-from="sessionFrom"
|
||||||
|
:send-message-img="sendMessageImg"
|
||||||
|
:show-message-card="showMessageCard"
|
||||||
|
@getphonenumber="getphonenumber"
|
||||||
|
@getuserinfo="getuserinfo"
|
||||||
|
@error="error"
|
||||||
|
@opensetting="opensetting"
|
||||||
|
@launchapp="launchapp"
|
||||||
|
:hover-class="!disabled && !loading ? 'u-button--active' : ''"
|
||||||
|
class="u-button u-reset-button"
|
||||||
|
:style="[baseColor, $u.addStyle(customStyle)]"
|
||||||
|
@tap="clickHandler"
|
||||||
|
:class="bemClass"
|
||||||
|
>
|
||||||
|
<template v-if="loading">
|
||||||
|
<u-loading-icon
|
||||||
|
:mode="loadingMode"
|
||||||
|
:size="textSize * 1.15"
|
||||||
|
:color="loadingColor"
|
||||||
|
></u-loading-icon>
|
||||||
|
<text
|
||||||
|
class="u-button__loading-text"
|
||||||
|
:style="[{ fontSize: textSize + 'px' }]"
|
||||||
|
>{{ loadingText || text }}</text
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<u-icon
|
||||||
|
v-if="icon"
|
||||||
|
:name="icon"
|
||||||
|
:color="iconColorCom"
|
||||||
|
:size="textSize * 1.35"
|
||||||
|
:customStyle="{ marginRight: '2px' }"
|
||||||
|
></u-icon>
|
||||||
|
<slot>
|
||||||
|
<text
|
||||||
|
class="u-button__text"
|
||||||
|
:style="[{ fontSize: textSize + 'px' }]"
|
||||||
|
>{{ text }}</text
|
||||||
|
>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<view
|
||||||
|
:hover-start-time="Number(hoverStartTime)"
|
||||||
|
:hover-stay-time="Number(hoverStayTime)"
|
||||||
|
class="u-button"
|
||||||
|
:hover-class="
|
||||||
|
!disabled && !loading && !color && (plain || type === 'info')
|
||||||
|
? 'u-button--active--plain'
|
||||||
|
: !disabled && !loading && !plain
|
||||||
|
? 'u-button--active'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
@tap="clickHandler"
|
||||||
|
:class="bemClass"
|
||||||
|
:style="[baseColor, $u.addStyle(customStyle)]"
|
||||||
|
>
|
||||||
|
<template v-if="loading">
|
||||||
|
<u-loading-icon
|
||||||
|
:mode="loadingMode"
|
||||||
|
:size="textSize * 1.15"
|
||||||
|
:color="loadingColor"
|
||||||
|
></u-loading-icon>
|
||||||
|
<text
|
||||||
|
class="u-button__loading-text"
|
||||||
|
:style="[nvueTextStyle]"
|
||||||
|
:class="[plain && `u-button__text--plain--${type}`]"
|
||||||
|
>{{ loadingText || text }}</text
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<u-icon
|
||||||
|
v-if="icon"
|
||||||
|
:name="icon"
|
||||||
|
:color="iconColorCom"
|
||||||
|
:size="textSize * 1.35"
|
||||||
|
></u-icon>
|
||||||
|
<text
|
||||||
|
class="u-button__text"
|
||||||
|
:style="[
|
||||||
|
{
|
||||||
|
marginLeft: icon ? '2px' : 0,
|
||||||
|
},
|
||||||
|
nvueTextStyle,
|
||||||
|
]"
|
||||||
|
:class="[plain && `u-button__text--plain--${type}`]"
|
||||||
|
>{{ text }}</text
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import button from "../../libs/mixin/button.js";
|
||||||
|
import openType from "../../libs/mixin/openType.js";
|
||||||
|
import props from "./props.js";
|
||||||
|
/**
|
||||||
|
* button 按钮
|
||||||
|
* @description Button 按钮
|
||||||
|
* @tutorial https://www.uviewui.com/components/button.html
|
||||||
|
*
|
||||||
|
* @property {Boolean} hairline 是否显示按钮的细边框 (默认 true )
|
||||||
|
* @property {String} type 按钮的预置样式,info,primary,error,warning,success (默认 'info' )
|
||||||
|
* @property {String} size 按钮尺寸,large,normal,mini (默认 normal)
|
||||||
|
* @property {String} shape 按钮形状,circle(两边为半圆),square(带圆角) (默认 'square' )
|
||||||
|
* @property {Boolean} plain 按钮是否镂空,背景色透明 (默认 false)
|
||||||
|
* @property {Boolean} disabled 是否禁用 (默认 false)
|
||||||
|
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台,在 ios 上为雪花,Android上为圆圈) (默认 false)
|
||||||
|
* @property {String | Number} loadingText 加载中提示文字
|
||||||
|
* @property {String} loadingMode 加载状态图标类型 (默认 'spinner' )
|
||||||
|
* @property {String | Number} loadingSize 加载图标大小 (默认 15 )
|
||||||
|
* @property {String} openType 开放能力,具体请看uniapp稳定关于button组件部分说明
|
||||||
|
* @property {String} formType 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
|
||||||
|
* @property {String} appParameter 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 (注:只微信小程序、QQ小程序有效)
|
||||||
|
* @property {Boolean} hoverStopPropagation 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效(默认 true )
|
||||||
|
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文(默认 en )
|
||||||
|
* @property {String} sessionFrom 会话来源,openType="contact"时有效
|
||||||
|
* @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
|
||||||
|
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
|
||||||
|
* @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
|
||||||
|
* @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效(默认false)
|
||||||
|
* @property {String} dataName 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
|
||||||
|
* @property {String | Number} throttleTime 节流,一定时间内只能触发一次 (默认 0 )
|
||||||
|
* @property {String | Number} hoverStartTime 按住后多久出现点击态,单位毫秒 (默认 0 )
|
||||||
|
* @property {String | Number} hoverStayTime 手指松开后点击态保留时间,单位毫秒 (默认 200 )
|
||||||
|
* @property {String | Number} text 按钮文字,之所以通过props传入,是因为slot传入的话(注:nvue中无法控制文字的样式)
|
||||||
|
* @property {String} icon 按钮图标
|
||||||
|
* @property {String} iconColor 按钮图标颜色
|
||||||
|
* @property {String} color 按钮颜色,支持传入linear-gradient渐变色
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @event {Function} click 非禁止并且非加载中,才能点击
|
||||||
|
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
|
||||||
|
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo
|
||||||
|
* @event {Function} error 当使用开放能力时,发生错误的回调
|
||||||
|
* @event {Function} opensetting 在打开授权设置页并关闭后回调
|
||||||
|
* @event {Function} launchapp 打开 APP 成功的回调
|
||||||
|
* @example <u-button>月落</u-button>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-button",
|
||||||
|
// #ifdef MP
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, button, openType, props],
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
// #endif
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 生成bem风格的类名
|
||||||
|
bemClass() {
|
||||||
|
// this.bem为一个computed变量,在mixin中
|
||||||
|
if (!this.color) {
|
||||||
|
return this.bem(
|
||||||
|
"button",
|
||||||
|
["type", "shape", "size"],
|
||||||
|
["disabled", "plain", "hairline"]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 由于nvue的原因,在有color参数时,不需要传入type,否则会生成type相关的类型,影响最终的样式
|
||||||
|
return this.bem(
|
||||||
|
"button",
|
||||||
|
["shape", "size"],
|
||||||
|
["disabled", "plain", "hairline"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadingColor() {
|
||||||
|
if (this.plain) {
|
||||||
|
// 如果有设置color值,则用color值,否则使用type主题颜色
|
||||||
|
return this.color
|
||||||
|
? this.color
|
||||||
|
: uni.$u.config.color[`u-${this.type}`];
|
||||||
|
}
|
||||||
|
if (this.type === "info") {
|
||||||
|
return "#c9c9c9";
|
||||||
|
}
|
||||||
|
return "rgb(200, 200, 200)";
|
||||||
|
},
|
||||||
|
iconColorCom() {
|
||||||
|
// 如果是镂空状态,设置了color就用color值,否则使用主题颜色,
|
||||||
|
// u-icon的color能接受一个主题颜色的值
|
||||||
|
if (this.iconColor) return this.iconColor;
|
||||||
|
if (this.plain) {
|
||||||
|
return this.color ? this.color : this.type;
|
||||||
|
} else {
|
||||||
|
return this.type === "info" ? "#000000" : "#ffffff";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
baseColor() {
|
||||||
|
let style = {};
|
||||||
|
if (this.color) {
|
||||||
|
// 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
|
||||||
|
style.color = this.plain ? this.color : "white";
|
||||||
|
if (!this.plain) {
|
||||||
|
// 非镂空,背景色使用自定义的颜色
|
||||||
|
style["background-color"] = this.color;
|
||||||
|
}
|
||||||
|
if (this.color.indexOf("gradient") !== -1) {
|
||||||
|
// 如果自定义的颜色为渐变色,不显示边框,以及通过backgroundImage设置渐变色
|
||||||
|
// weex文档说明可以写borderWidth的形式,为什么这里需要分开写?
|
||||||
|
// 因为weex是阿里巴巴为了部门业绩考核而做的你懂的东西,所以需要这么写才有效
|
||||||
|
style.borderTopWidth = 0;
|
||||||
|
style.borderRightWidth = 0;
|
||||||
|
style.borderBottomWidth = 0;
|
||||||
|
style.borderLeftWidth = 0;
|
||||||
|
if (!this.plain) {
|
||||||
|
style.backgroundImage = this.color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非渐变色,则设置边框相关的属性
|
||||||
|
style.borderColor = this.color;
|
||||||
|
style.borderWidth = "1px";
|
||||||
|
style.borderStyle = "solid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
// nvue版本按钮的字体不会继承父组件的颜色,需要对每一个text组件进行单独的设置
|
||||||
|
nvueTextStyle() {
|
||||||
|
let style = {};
|
||||||
|
// 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
|
||||||
|
if (this.type === "info") {
|
||||||
|
style.color = "#323233";
|
||||||
|
}
|
||||||
|
if (this.color) {
|
||||||
|
style.color = this.plain ? this.color : "white";
|
||||||
|
}
|
||||||
|
style.fontSize = this.textSize + "px";
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
// 字体大小
|
||||||
|
textSize() {
|
||||||
|
let fontSize = 14,
|
||||||
|
{ size } = this;
|
||||||
|
if (size === "large") fontSize = 16;
|
||||||
|
if (size === "normal") fontSize = 14;
|
||||||
|
if (size === "small") fontSize = 12;
|
||||||
|
if (size === "mini") fontSize = 10;
|
||||||
|
return fontSize;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clickHandler() {
|
||||||
|
// 非禁止并且非加载中,才能点击
|
||||||
|
if (!this.disabled && !this.loading) {
|
||||||
|
// 进行节流控制,每this.throttle毫秒内,只在开始处执行
|
||||||
|
uni.$u.throttle(() => {
|
||||||
|
this.$emit("click");
|
||||||
|
}, this.throttleTime);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 下面为对接uniapp官方按钮开放能力事件回调的对接
|
||||||
|
getphonenumber(res) {
|
||||||
|
this.$emit("getphonenumber", res);
|
||||||
|
},
|
||||||
|
getuserinfo(res) {
|
||||||
|
this.$emit("getuserinfo", res);
|
||||||
|
},
|
||||||
|
error(res) {
|
||||||
|
this.$emit("error", res);
|
||||||
|
},
|
||||||
|
opensetting(res) {
|
||||||
|
this.$emit("opensetting", res);
|
||||||
|
},
|
||||||
|
launchapp(res) {
|
||||||
|
this.$emit("launchapp", res);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
@import "./vue.scss";
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
@import "./nvue.scss";
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
$u-button-u-button-height: 40px !default;
|
||||||
|
$u-button-text-font-size: 15px !default;
|
||||||
|
$u-button-loading-text-font-size: 15px !default;
|
||||||
|
$u-button-loading-text-margin-left: 4px !default;
|
||||||
|
$u-button-large-width: 100% !default;
|
||||||
|
$u-button-large-height: 50px !default;
|
||||||
|
$u-button-normal-padding: 0 12px !default;
|
||||||
|
$u-button-large-padding: 0 15px !default;
|
||||||
|
$u-button-normal-font-size: 14px !default;
|
||||||
|
$u-button-small-min-width: 60px !default;
|
||||||
|
$u-button-small-height: 30px !default;
|
||||||
|
$u-button-small-padding: 0px 8px !default;
|
||||||
|
$u-button-mini-padding: 0px 8px !default;
|
||||||
|
$u-button-small-font-size: 12px !default;
|
||||||
|
$u-button-mini-height: 22px !default;
|
||||||
|
$u-button-mini-font-size: 10px !default;
|
||||||
|
$u-button-mini-min-width: 50px !default;
|
||||||
|
$u-button-disabled-opacity: 0.5 !default;
|
||||||
|
$u-button-info-color: #323233 !default;
|
||||||
|
$u-button-info-background-color: #fff !default;
|
||||||
|
$u-button-info-border-color: #ebedf0 !default;
|
||||||
|
$u-button-info-border-width: 1px !default;
|
||||||
|
$u-button-info-border-style: solid !default;
|
||||||
|
$u-button-success-color: #fff !default;
|
||||||
|
$u-button-success-background-color: $u-success !default;
|
||||||
|
$u-button-success-border-color: $u-button-success-background-color !default;
|
||||||
|
$u-button-success-border-width: 1px !default;
|
||||||
|
$u-button-success-border-style: solid !default;
|
||||||
|
$u-button-primary-color: #fff !default;
|
||||||
|
$u-button-primary-background-color: $u-primary !default;
|
||||||
|
$u-button-primary-border-color: $u-button-primary-background-color !default;
|
||||||
|
$u-button-primary-border-width: 1px !default;
|
||||||
|
$u-button-primary-border-style: solid !default;
|
||||||
|
$u-button-error-color: #fff !default;
|
||||||
|
$u-button-error-background-color: $u-error !default;
|
||||||
|
$u-button-error-border-color: $u-button-error-background-color !default;
|
||||||
|
$u-button-error-border-width: 1px !default;
|
||||||
|
$u-button-error-border-style: solid !default;
|
||||||
|
$u-button-warning-color: #fff !default;
|
||||||
|
$u-button-warning-background-color: $u-warning !default;
|
||||||
|
$u-button-warning-border-color: $u-button-warning-background-color !default;
|
||||||
|
$u-button-warning-border-width: 1px !default;
|
||||||
|
$u-button-warning-border-style: solid !default;
|
||||||
|
$u-button-block-width: 100% !default;
|
||||||
|
$u-button-circle-border-top-right-radius: 100px !default;
|
||||||
|
$u-button-circle-border-top-left-radius: 100px !default;
|
||||||
|
$u-button-circle-border-bottom-left-radius: 100px !default;
|
||||||
|
$u-button-circle-border-bottom-right-radius: 100px !default;
|
||||||
|
$u-button-square-border-top-right-radius: 3px !default;
|
||||||
|
$u-button-square-border-top-left-radius: 3px !default;
|
||||||
|
$u-button-square-border-bottom-left-radius: 3px !default;
|
||||||
|
$u-button-square-border-bottom-right-radius: 3px !default;
|
||||||
|
$u-button-icon-min-width: 1em !default;
|
||||||
|
$u-button-plain-background-color: #fff !default;
|
||||||
|
$u-button-hairline-border-width: 0.5px !default;
|
||||||
|
|
||||||
|
.u-button {
|
||||||
|
height: $u-button-u-button-height;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
@include flex;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: $u-button-text-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__loading-text {
|
||||||
|
font-size: $u-button-loading-text-font-size;
|
||||||
|
margin-left: $u-button-loading-text-margin-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: $u-button-large-width;
|
||||||
|
/* #endif */
|
||||||
|
height: $u-button-large-height;
|
||||||
|
padding: $u-button-large-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--normal {
|
||||||
|
padding: $u-button-normal-padding;
|
||||||
|
font-size: $u-button-normal-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--small {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
min-width: $u-button-small-min-width;
|
||||||
|
/* #endif */
|
||||||
|
height: $u-button-small-height;
|
||||||
|
padding: $u-button-small-padding;
|
||||||
|
font-size: $u-button-small-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--mini {
|
||||||
|
height: $u-button-mini-height;
|
||||||
|
font-size: $u-button-mini-font-size;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
min-width: $u-button-mini-min-width;
|
||||||
|
/* #endif */
|
||||||
|
padding: $u-button-mini-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
opacity: $u-button-disabled-opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
color: $u-button-info-color;
|
||||||
|
background-color: $u-button-info-background-color;
|
||||||
|
border-color: $u-button-info-border-color;
|
||||||
|
border-width: $u-button-info-border-width;
|
||||||
|
border-style: $u-button-info-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
color: $u-button-success-color;
|
||||||
|
background-color: $u-button-success-background-color;
|
||||||
|
border-color: $u-button-success-border-color;
|
||||||
|
border-width: $u-button-success-border-width;
|
||||||
|
border-style: $u-button-success-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
color: $u-button-primary-color;
|
||||||
|
background-color: $u-button-primary-background-color;
|
||||||
|
border-color: $u-button-primary-border-color;
|
||||||
|
border-width: $u-button-primary-border-width;
|
||||||
|
border-style: $u-button-primary-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
color: $u-button-error-color;
|
||||||
|
background-color: $u-button-error-background-color;
|
||||||
|
border-color: $u-button-error-border-color;
|
||||||
|
border-width: $u-button-error-border-width;
|
||||||
|
border-style: $u-button-error-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
color: $u-button-warning-color;
|
||||||
|
background-color: $u-button-warning-background-color;
|
||||||
|
border-color: $u-button-warning-border-color;
|
||||||
|
border-width: $u-button-warning-border-width;
|
||||||
|
border-style: $u-button-warning-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--block {
|
||||||
|
@include flex;
|
||||||
|
width: $u-button-block-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--circle {
|
||||||
|
border-top-right-radius: $u-button-circle-border-top-right-radius;
|
||||||
|
border-top-left-radius: $u-button-circle-border-top-left-radius;
|
||||||
|
border-bottom-left-radius: $u-button-circle-border-bottom-left-radius;
|
||||||
|
border-bottom-right-radius: $u-button-circle-border-bottom-right-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--square {
|
||||||
|
border-bottom-left-radius: $u-button-square-border-top-right-radius;
|
||||||
|
border-bottom-right-radius: $u-button-square-border-top-left-radius;
|
||||||
|
border-top-left-radius: $u-button-square-border-bottom-left-radius;
|
||||||
|
border-top-right-radius: $u-button-square-border-bottom-right-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
min-width: $u-button-icon-min-width;
|
||||||
|
line-height: inherit !important;
|
||||||
|
vertical-align: top;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
background-color: $u-button-plain-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--hairline {
|
||||||
|
border-width: $u-button-hairline-border-width !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
80
node_modules/uview-ui/components/u-button/vue.scss
generated
vendored
Normal file
80
node_modules/uview-ui/components/u-button/vue.scss
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// nvue下hover-class无效
|
||||||
|
$u-button-before-top:50% !default;
|
||||||
|
$u-button-before-left:50% !default;
|
||||||
|
$u-button-before-width:100% !default;
|
||||||
|
$u-button-before-height:100% !default;
|
||||||
|
$u-button-before-transform:translate(-50%, -50%) !default;
|
||||||
|
$u-button-before-opacity:0 !default;
|
||||||
|
$u-button-before-background-color:#000 !default;
|
||||||
|
$u-button-before-border-color:#000 !default;
|
||||||
|
$u-button-active-before-opacity:.15 !default;
|
||||||
|
$u-button-icon-margin-left:4px !default;
|
||||||
|
$u-button-plain-u-button-info-color:$u-info;
|
||||||
|
$u-button-plain-u-button-success-color:$u-success;
|
||||||
|
$u-button-plain-u-button-error-color:$u-error;
|
||||||
|
$u-button-plain-u-button-warning-color:$u-error;
|
||||||
|
|
||||||
|
.u-button {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
top:$u-button-before-top;
|
||||||
|
left:$u-button-before-left;
|
||||||
|
width:$u-button-before-width;
|
||||||
|
height:$u-button-before-height;
|
||||||
|
border: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
transform:$u-button-before-transform;
|
||||||
|
opacity:$u-button-before-opacity;
|
||||||
|
content: " ";
|
||||||
|
background-color:$u-button-before-background-color;
|
||||||
|
border-color:$u-button-before-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
&:before {
|
||||||
|
opacity: .15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon+&__text:not(:empty),
|
||||||
|
&__loading-text {
|
||||||
|
margin-left:$u-button-icon-margin-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
&.u-button--primary {
|
||||||
|
color: $u-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
&.u-button--info {
|
||||||
|
color:$u-button-plain-u-button-info-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
&.u-button--success {
|
||||||
|
color:$u-button-plain-u-button-success-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
&.u-button--error {
|
||||||
|
color:$u-button-plain-u-button-error-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--plain {
|
||||||
|
&.u-button--warning {
|
||||||
|
color:$u-button-plain-u-button-warning-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
node_modules/uview-ui/components/u-calendar/header.vue
generated
vendored
Normal file
99
node_modules/uview-ui/components/u-calendar/header.vue
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-calendar-header u-border-bottom">
|
||||||
|
<text
|
||||||
|
class="u-calendar-header__title"
|
||||||
|
v-if="showTitle"
|
||||||
|
>{{ title }}</text>
|
||||||
|
<text
|
||||||
|
class="u-calendar-header__subtitle"
|
||||||
|
v-if="showSubtitle"
|
||||||
|
>{{ subtitle }}</text>
|
||||||
|
<view class="u-calendar-header__weekdays">
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">一</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">二</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">三</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">四</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">五</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">六</text>
|
||||||
|
<text class="u-calendar-header__weekdays__weekday">日</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'u-calendar-header',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin],
|
||||||
|
props: {
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 副标题
|
||||||
|
subtitle: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 是否显示标题
|
||||||
|
showTitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 是否显示副标题
|
||||||
|
showSubtitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
name() {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-calendar-header {
|
||||||
|
padding-bottom: 4px;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: $u-main-color;
|
||||||
|
text-align: center;
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: $u-main-color;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 40px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__weekdays {
|
||||||
|
@include flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&__weekday {
|
||||||
|
font-size: 13px;
|
||||||
|
color: $u-main-color;
|
||||||
|
line-height: 30px;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
579
node_modules/uview-ui/components/u-calendar/month.vue
generated
vendored
Normal file
579
node_modules/uview-ui/components/u-calendar/month.vue
generated
vendored
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-calendar-month-wrapper" ref="u-calendar-month-wrapper">
|
||||||
|
<view v-for="(item, index) in months" :key="index" :class="[`u-calendar-month-${index}`]"
|
||||||
|
:ref="`u-calendar-month-${index}`" :id="`month-${index}`">
|
||||||
|
<text v-if="index !== 0" class="u-calendar-month__title">{{ item.year }}年{{ item.month }}月</text>
|
||||||
|
<view class="u-calendar-month__days">
|
||||||
|
<view v-if="showMark" class="u-calendar-month__days__month-mark-wrapper">
|
||||||
|
<text class="u-calendar-month__days__month-mark-wrapper__text">{{ item.month }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="u-calendar-month__days__day" v-for="(item1, index1) in item.date" :key="index1"
|
||||||
|
:style="[dayStyle(index, index1, item1)]" @tap="clickHandler(index, index1, item1)"
|
||||||
|
:class="[item1.selected && 'u-calendar-month__days__day__select--selected']">
|
||||||
|
<view class="u-calendar-month__days__day__select" :style="[daySelectStyle(index, index1, item1)]">
|
||||||
|
<text class="u-calendar-month__days__day__select__info"
|
||||||
|
:class="[item1.disabled && 'u-calendar-month__days__day__select__info--disabled']"
|
||||||
|
:style="[textStyle(item1)]">{{ item1.day }}</text>
|
||||||
|
<text v-if="getBottomInfo(index, index1, item1)"
|
||||||
|
class="u-calendar-month__days__day__select__buttom-info"
|
||||||
|
:class="[item1.disabled && 'u-calendar-month__days__day__select__buttom-info--disabled']"
|
||||||
|
:style="[textStyle(item1)]">{{ getBottomInfo(index, index1, item1) }}</text>
|
||||||
|
<text v-if="item1.dot" class="u-calendar-month__days__day__select__dot"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 由于nvue不支持百分比单位,需要查询宽度来计算每个日期的宽度
|
||||||
|
const dom = uni.requireNativePlugin('dom')
|
||||||
|
// #endif
|
||||||
|
import dayjs from '../../libs/util/dayjs.js';
|
||||||
|
export default {
|
||||||
|
name: 'u-calendar-month',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin],
|
||||||
|
props: {
|
||||||
|
// 是否显示月份背景色
|
||||||
|
showMark: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 主题色,对底部按钮和选中日期有效
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#3c9cff'
|
||||||
|
},
|
||||||
|
// 月份数据
|
||||||
|
months: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
// 日期选择类型
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'single'
|
||||||
|
},
|
||||||
|
// 日期行高
|
||||||
|
rowHeight: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 58
|
||||||
|
},
|
||||||
|
// mode=multiple时,最多可选多少个日期
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: Infinity
|
||||||
|
},
|
||||||
|
// mode=range时,第一个日期底部的提示文字
|
||||||
|
startText: {
|
||||||
|
type: String,
|
||||||
|
default: '开始'
|
||||||
|
},
|
||||||
|
// mode=range时,最后一个日期底部的提示文字
|
||||||
|
endText: {
|
||||||
|
type: String,
|
||||||
|
default: '结束'
|
||||||
|
},
|
||||||
|
// 默认选中的日期,mode为multiple或range是必须为数组格式
|
||||||
|
defaultDate: {
|
||||||
|
type: [Array, String, Date],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// 最小的可选日期
|
||||||
|
minDate: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
// 最大可选日期
|
||||||
|
maxDate: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
// 如果没有设置maxDate,则往后推多少个月
|
||||||
|
maxMonth: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 2
|
||||||
|
},
|
||||||
|
// 是否为只读状态,只读状态下禁止选择日期
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.readonly
|
||||||
|
},
|
||||||
|
// 日期区间最多可选天数,默认无限制,mode = range时有效
|
||||||
|
maxRange: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: Infinity
|
||||||
|
},
|
||||||
|
// 范围选择超过最多可选天数时的提示文案,mode = range时有效
|
||||||
|
rangePrompt: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
|
||||||
|
showRangePrompt: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 是否允许日期范围的起止时间为同一天,mode = range时有效
|
||||||
|
allowSameDay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 每个日期的宽度
|
||||||
|
width: 0,
|
||||||
|
// 当前选中的日期item
|
||||||
|
item: {},
|
||||||
|
selected: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectedChange: {
|
||||||
|
immediate: true,
|
||||||
|
handler(n) {
|
||||||
|
this.setDefaultDate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 多个条件的变化,会引起选中日期的变化,这里统一管理监听
|
||||||
|
selectedChange() {
|
||||||
|
return [this.minDate, this.maxDate, this.defaultDate]
|
||||||
|
},
|
||||||
|
dayStyle(index1, index2, item) {
|
||||||
|
return (index1, index2, item) => {
|
||||||
|
const style = {}
|
||||||
|
let week = item.week
|
||||||
|
// 不进行四舍五入的形式保留2位小数
|
||||||
|
const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1))
|
||||||
|
// 得出每个日期的宽度
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
style.width = uni.$u.addUnit(dayWidth)
|
||||||
|
// #endif
|
||||||
|
style.height = uni.$u.addUnit(this.rowHeight)
|
||||||
|
if (index2 === 0) {
|
||||||
|
// 获取当前为星期几,如果为0,则为星期天,减一为每月第一天时,需要向左偏移的item个数
|
||||||
|
week = (week === 0 ? 7 : week) - 1
|
||||||
|
style.marginLeft = uni.$u.addUnit(week * dayWidth)
|
||||||
|
}
|
||||||
|
if (this.mode === 'range') {
|
||||||
|
// 之所以需要这么写,是因为DCloud公司的iOS客户端的开发者能力有限导致的bug
|
||||||
|
style.paddingLeft = 0
|
||||||
|
style.paddingRight = 0
|
||||||
|
style.paddingBottom = 0
|
||||||
|
style.paddingTop = 0
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
daySelectStyle() {
|
||||||
|
return (index1, index2, item) => {
|
||||||
|
let date = dayjs(item.date).format("YYYY-MM-DD"),
|
||||||
|
style = {}
|
||||||
|
// 判断date是否在selected数组中,因为月份可能会需要补0,所以使用dateSame判断,而不用数组的includes判断
|
||||||
|
if (this.selected.some(item => this.dateSame(item, date))) {
|
||||||
|
style.backgroundColor = this.color
|
||||||
|
}
|
||||||
|
if (this.mode === 'single') {
|
||||||
|
if (date === this.selected[0]) {
|
||||||
|
// 因为需要对nvue的兼容,只能这么写,无法缩写,也无法通过类名控制等等
|
||||||
|
style.borderTopLeftRadius = '3px'
|
||||||
|
style.borderBottomLeftRadius = '3px'
|
||||||
|
style.borderTopRightRadius = '3px'
|
||||||
|
style.borderBottomRightRadius = '3px'
|
||||||
|
}
|
||||||
|
} else if (this.mode === 'range') {
|
||||||
|
if (this.selected.length >= 2) {
|
||||||
|
const len = this.selected.length - 1
|
||||||
|
// 第一个日期设置左上角和左下角的圆角
|
||||||
|
if (this.dateSame(date, this.selected[0])) {
|
||||||
|
style.borderTopLeftRadius = '3px'
|
||||||
|
style.borderBottomLeftRadius = '3px'
|
||||||
|
}
|
||||||
|
// 最后一个日期设置右上角和右下角的圆角
|
||||||
|
if (this.dateSame(date, this.selected[len])) {
|
||||||
|
style.borderTopRightRadius = '3px'
|
||||||
|
style.borderBottomRightRadius = '3px'
|
||||||
|
}
|
||||||
|
// 处于第一和最后一个之间的日期,背景色设置为浅色,通过将对应颜色进行等分,再取其尾部的颜色值
|
||||||
|
if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
|
||||||
|
.selected[len]))) {
|
||||||
|
style.backgroundColor = uni.$u.colorGradient(this.color, '#ffffff', 100)[90]
|
||||||
|
// 增加一个透明度,让范围区间的背景色也能看到底部的mark水印字符
|
||||||
|
style.opacity = 0.7
|
||||||
|
}
|
||||||
|
} else if (this.selected.length === 1) {
|
||||||
|
// 之所以需要这么写,是因为DCloud公司的iOS客户端的开发者能力有限导致的bug
|
||||||
|
// 进行还原操作,否则在nvue的iOS,uni-app有bug,会导致诡异的表现
|
||||||
|
style.borderTopLeftRadius = '3px'
|
||||||
|
style.borderBottomLeftRadius = '3px'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.selected.some(item => this.dateSame(item, date))) {
|
||||||
|
style.borderTopLeftRadius = '3px'
|
||||||
|
style.borderBottomLeftRadius = '3px'
|
||||||
|
style.borderTopRightRadius = '3px'
|
||||||
|
style.borderBottomRightRadius = '3px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 某个日期是否被选中
|
||||||
|
textStyle() {
|
||||||
|
return (item) => {
|
||||||
|
const date = dayjs(item.date).format("YYYY-MM-DD"),
|
||||||
|
style = {}
|
||||||
|
// 选中的日期,提示文字设置白色
|
||||||
|
if (this.selected.some(item => this.dateSame(item, date))) {
|
||||||
|
style.color = '#ffffff'
|
||||||
|
}
|
||||||
|
if (this.mode === 'range') {
|
||||||
|
const len = this.selected.length - 1
|
||||||
|
// 如果是范围选择模式,第一个和最后一个之间的日期,文字颜色设置为高亮的主题色
|
||||||
|
if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
|
||||||
|
.selected[len]))) {
|
||||||
|
style.color = this.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取底部的提示文字
|
||||||
|
getBottomInfo() {
|
||||||
|
return (index1, index2, item) => {
|
||||||
|
const date = dayjs(item.date).format("YYYY-MM-DD")
|
||||||
|
const bottomInfo = item.bottomInfo
|
||||||
|
// 当为日期范围模式时,且选择的日期个数大于0时
|
||||||
|
if (this.mode === 'range' && this.selected.length > 0) {
|
||||||
|
if (this.selected.length === 1) {
|
||||||
|
// 选择了一个日期时,如果当前日期为数组中的第一个日期,则显示底部文字为“开始”
|
||||||
|
if (this.dateSame(date, this.selected[0])) return this.startText
|
||||||
|
else return bottomInfo
|
||||||
|
} else {
|
||||||
|
const len = this.selected.length - 1
|
||||||
|
// 如果数组中的日期大于2个时,第一个和最后一个显示为开始和结束日期
|
||||||
|
if (this.dateSame(date, this.selected[0]) && this.dateSame(date, this.selected[1]) &&
|
||||||
|
len === 1) {
|
||||||
|
// 如果长度为2,且第一个等于第二个日期,则提示语放在同一个item中
|
||||||
|
return `${this.startText}/${this.endText}`
|
||||||
|
} else if (this.dateSame(date, this.selected[0])) {
|
||||||
|
return this.startText
|
||||||
|
} else if (this.dateSame(date, this.selected[len])) {
|
||||||
|
return this.endText
|
||||||
|
} else {
|
||||||
|
return bottomInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return bottomInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
// 初始化默认选中
|
||||||
|
this.$emit('monthSelected', this.selected)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 这里需要另一个延时,因为获取宽度后,会进行月份数据渲染,只有渲染完成之后,才有真正的高度
|
||||||
|
// 因为nvue下,$nextTick并不是100%可靠的
|
||||||
|
uni.$u.sleep(10).then(() => {
|
||||||
|
this.getWrapperWidth()
|
||||||
|
this.getMonthRect()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 判断两个日期是否相等
|
||||||
|
dateSame(date1, date2) {
|
||||||
|
return dayjs(date1).isSame(dayjs(date2))
|
||||||
|
},
|
||||||
|
// 获取月份数据区域的宽度,因为nvue不支持百分比,所以无法通过css设置每个日期item的宽度
|
||||||
|
getWrapperWidth() {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
dom.getComponentRect(this.$refs['u-calendar-month-wrapper'], res => {
|
||||||
|
this.width = res.size.width
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.$uGetRect('.u-calendar-month-wrapper').then(size => {
|
||||||
|
this.width = size.width
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
getMonthRect() {
|
||||||
|
// 获取每个月份数据的尺寸,用于父组件在scroll-view滚动事件中,监听当前滚动到了第几个月份
|
||||||
|
const promiseAllArr = this.months.map((item, index) => this.getMonthRectByPromise(
|
||||||
|
`u-calendar-month-${index}`))
|
||||||
|
// 一次性返回
|
||||||
|
Promise.all(promiseAllArr).then(
|
||||||
|
sizes => {
|
||||||
|
let height = 1
|
||||||
|
const topArr = []
|
||||||
|
for (let i = 0; i < this.months.length; i++) {
|
||||||
|
// 添加到months数组中,供scroll-view滚动事件中,判断当前滚动到哪个月份
|
||||||
|
topArr[i] = height
|
||||||
|
height += sizes[i].height
|
||||||
|
}
|
||||||
|
// 由于微信下,无法通过this.months[i].top的形式(引用类型)去修改父组件的month的top值,所以使用事件形式对外发出
|
||||||
|
this.$emit('updateMonthTop', topArr)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取每个月份区域的尺寸
|
||||||
|
getMonthRectByPromise(el) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
// $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://www.uviewui.com/js/getRect.html
|
||||||
|
// 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.$uGetRect(`.${el}`).then(size => {
|
||||||
|
resolve(size)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// nvue下,使用dom模块查询元素高度
|
||||||
|
// 返回一个promise,让调用此方法的主体能使用then回调
|
||||||
|
return new Promise(resolve => {
|
||||||
|
dom.getComponentRect(this.$refs[el][0], res => {
|
||||||
|
resolve(res.size)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// 点击某一个日期
|
||||||
|
clickHandler(index1, index2, item) {
|
||||||
|
if (this.readonly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.item = item
|
||||||
|
const date = dayjs(item.date).format("YYYY-MM-DD")
|
||||||
|
if (item.disabled) return
|
||||||
|
// 对上一次选择的日期数组进行深度克隆
|
||||||
|
let selected = uni.$u.deepClone(this.selected)
|
||||||
|
if (this.mode === 'single') {
|
||||||
|
// 单选情况下,让数组中的元素为当前点击的日期
|
||||||
|
selected = [date]
|
||||||
|
} else if (this.mode === 'multiple') {
|
||||||
|
if (selected.some(item => this.dateSame(item, date))) {
|
||||||
|
// 如果点击的日期已在数组中,则进行移除操作,也就是达到反选的效果
|
||||||
|
const itemIndex = selected.findIndex(item => item === date)
|
||||||
|
selected.splice(itemIndex, 1)
|
||||||
|
} else {
|
||||||
|
// 如果点击的日期不在数组中,且已有的长度小于总可选长度时,则添加到数组中去
|
||||||
|
if (selected.length < this.maxCount) selected.push(date)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 选择区间形式
|
||||||
|
if (selected.length === 0 || selected.length >= 2) {
|
||||||
|
// 如果原来就为0或者大于2的长度,则当前点击的日期,就是开始日期
|
||||||
|
selected = [date]
|
||||||
|
} else if (selected.length === 1) {
|
||||||
|
// 如果已经选择了开始日期
|
||||||
|
const existsDate = selected[0]
|
||||||
|
// 如果当前选择的日期小于上一次选择的日期,则当前的日期定为开始日期
|
||||||
|
if (dayjs(date).isBefore(existsDate)) {
|
||||||
|
selected = [date]
|
||||||
|
} else if (dayjs(date).isAfter(existsDate)) {
|
||||||
|
// 当前日期减去最大可选的日期天数,如果大于起始时间,则进行提示
|
||||||
|
if(dayjs(dayjs(date).subtract(this.maxRange, 'day')).isAfter(dayjs(selected[0])) && this.showRangePrompt) {
|
||||||
|
if(this.rangePrompt) {
|
||||||
|
uni.$u.toast(this.rangePrompt)
|
||||||
|
} else {
|
||||||
|
uni.$u.toast(`选择天数不能超过 ${this.maxRange} 天`)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 如果当前日期大于已有日期,将当前的添加到数组尾部
|
||||||
|
selected.push(date)
|
||||||
|
const startDate = selected[0]
|
||||||
|
const endDate = selected[1]
|
||||||
|
const arr = []
|
||||||
|
let i = 0
|
||||||
|
do {
|
||||||
|
// 将开始和结束日期之间的日期添加到数组中
|
||||||
|
arr.push(dayjs(startDate).add(i, 'day').format("YYYY-MM-DD"))
|
||||||
|
i++
|
||||||
|
// 累加的日期小于结束日期时,继续下一次的循环
|
||||||
|
} while (dayjs(startDate).add(i, 'day').isBefore(dayjs(endDate)))
|
||||||
|
// 为了一次性修改数组,避免computed中多次触发,这里才用arr变量一次性赋值的方式,同时将最后一个日期添加近来
|
||||||
|
arr.push(endDate)
|
||||||
|
selected = arr
|
||||||
|
} else {
|
||||||
|
// 选择区间时,只有一个日期的情况下,且不允许选择起止为同一天的话,不允许选择自己
|
||||||
|
if (selected[0] === date && !this.allowSameDay) return
|
||||||
|
selected.push(date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setSelected(selected)
|
||||||
|
},
|
||||||
|
// 设置默认日期
|
||||||
|
setDefaultDate() {
|
||||||
|
if (!this.defaultDate) {
|
||||||
|
// 如果没有设置默认日期,则将当天日期设置为默认选中的日期
|
||||||
|
const selected = [dayjs().format("YYYY-MM-DD")]
|
||||||
|
return this.setSelected(selected, false)
|
||||||
|
}
|
||||||
|
let defaultDate = []
|
||||||
|
const minDate = this.minDate || dayjs().format("YYYY-MM-DD")
|
||||||
|
const maxDate = this.maxDate || dayjs(minDate).add(this.maxMonth - 1, 'month').format("YYYY-MM-DD")
|
||||||
|
if (this.mode === 'single') {
|
||||||
|
// 单选模式,可以是字符串或数组,Date对象等
|
||||||
|
if (!uni.$u.test.array(this.defaultDate)) {
|
||||||
|
defaultDate = [dayjs(this.defaultDate).format("YYYY-MM-DD")]
|
||||||
|
} else {
|
||||||
|
defaultDate = [this.defaultDate[0]]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果为非数组,则不执行
|
||||||
|
if (!uni.$u.test.array(this.defaultDate)) return
|
||||||
|
defaultDate = this.defaultDate
|
||||||
|
}
|
||||||
|
// 过滤用户传递的默认数组,取出只在可允许最大值与最小值之间的元素
|
||||||
|
defaultDate = defaultDate.filter(item => {
|
||||||
|
return dayjs(item).isAfter(dayjs(minDate).subtract(1, 'day')) && dayjs(item).isBefore(dayjs(
|
||||||
|
maxDate).add(1, 'day'))
|
||||||
|
})
|
||||||
|
this.setSelected(defaultDate, false)
|
||||||
|
},
|
||||||
|
setSelected(selected, event = true) {
|
||||||
|
this.selected = selected
|
||||||
|
event && this.$emit('monthSelected', this.selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-calendar-month-wrapper {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-calendar-month {
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 42px;
|
||||||
|
height: 42px;
|
||||||
|
color: $u-main-color;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__days {
|
||||||
|
position: relative;
|
||||||
|
@include flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&__month-mark-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 155px;
|
||||||
|
color: rgba(231, 232, 234, 0.83);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__day {
|
||||||
|
@include flex;
|
||||||
|
padding: 2px;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
// vue下使用css进行宽度计算,因为某些安卓机会无法进行js获取父元素宽度进行计算得出,会有偏移
|
||||||
|
width: calc(100% / 7);
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&__select {
|
||||||
|
flex: 1;
|
||||||
|
@include flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: $u-error;
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__buttom-info {
|
||||||
|
color: $u-content-color;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
&--selected {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: #cacbcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
&--selected {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: #cacbcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--selected {
|
||||||
|
background-color: $u-primary;
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--range-selected {
|
||||||
|
opacity: 0.3;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--range-start-selected {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--range-end-selected {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
node_modules/uview-ui/components/u-calendar/props.js
generated
vendored
Normal file
144
node_modules/uview-ui/components/u-calendar/props.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 日历顶部标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.title
|
||||||
|
},
|
||||||
|
// 是否显示标题
|
||||||
|
showTitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showTitle
|
||||||
|
},
|
||||||
|
// 是否显示副标题
|
||||||
|
showSubtitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showSubtitle
|
||||||
|
},
|
||||||
|
// 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.mode
|
||||||
|
},
|
||||||
|
// mode=range时,第一个日期底部的提示文字
|
||||||
|
startText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.startText
|
||||||
|
},
|
||||||
|
// mode=range时,最后一个日期底部的提示文字
|
||||||
|
endText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.endText
|
||||||
|
},
|
||||||
|
// 自定义列表
|
||||||
|
customList: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.calendar.customList
|
||||||
|
},
|
||||||
|
// 主题色,对底部按钮和选中日期有效
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.color
|
||||||
|
},
|
||||||
|
// 最小的可选日期
|
||||||
|
minDate: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.calendar.minDate
|
||||||
|
},
|
||||||
|
// 最大可选日期
|
||||||
|
maxDate: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.calendar.maxDate
|
||||||
|
},
|
||||||
|
// 默认选中的日期,mode为multiple或range是必须为数组格式
|
||||||
|
defaultDate: {
|
||||||
|
type: [Array, String, Date, null],
|
||||||
|
default: uni.$u.props.calendar.defaultDate
|
||||||
|
},
|
||||||
|
// mode=multiple时,最多可选多少个日期
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.calendar.maxCount
|
||||||
|
},
|
||||||
|
// 日期行高
|
||||||
|
rowHeight: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.calendar.rowHeight
|
||||||
|
},
|
||||||
|
// 日期格式化函数
|
||||||
|
formatter: {
|
||||||
|
type: [Function, null],
|
||||||
|
default: uni.$u.props.calendar.formatter
|
||||||
|
},
|
||||||
|
// 是否显示农历
|
||||||
|
showLunar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showLunar
|
||||||
|
},
|
||||||
|
// 是否显示月份背景色
|
||||||
|
showMark: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showMark
|
||||||
|
},
|
||||||
|
// 确定按钮的文字
|
||||||
|
confirmText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.confirmText
|
||||||
|
},
|
||||||
|
// 确认按钮处于禁用状态时的文字
|
||||||
|
confirmDisabledText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.confirmDisabledText
|
||||||
|
},
|
||||||
|
// 是否显示日历弹窗
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.show
|
||||||
|
},
|
||||||
|
// 是否允许点击遮罩关闭日历
|
||||||
|
closeOnClickOverlay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.closeOnClickOverlay
|
||||||
|
},
|
||||||
|
// 是否为只读状态,只读状态下禁止选择日期
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.readonly
|
||||||
|
},
|
||||||
|
// 是否展示确认按钮
|
||||||
|
showConfirm: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showConfirm
|
||||||
|
},
|
||||||
|
// 日期区间最多可选天数,默认无限制,mode = range时有效
|
||||||
|
maxRange: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: uni.$u.props.calendar.maxRange
|
||||||
|
},
|
||||||
|
// 范围选择超过最多可选天数时的提示文案,mode = range时有效
|
||||||
|
rangePrompt: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.calendar.rangePrompt
|
||||||
|
},
|
||||||
|
// 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
|
||||||
|
showRangePrompt: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.showRangePrompt
|
||||||
|
},
|
||||||
|
// 是否允许日期范围的起止时间为同一天,mode = range时有效
|
||||||
|
allowSameDay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.calendar.allowSameDay
|
||||||
|
},
|
||||||
|
// 圆角值
|
||||||
|
round: {
|
||||||
|
type: [Boolean, String, Number],
|
||||||
|
default: uni.$u.props.calendar.round
|
||||||
|
},
|
||||||
|
// 最多展示月份数量
|
||||||
|
monthNum: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
383
node_modules/uview-ui/components/u-calendar/u-calendar.vue
generated
vendored
Normal file
383
node_modules/uview-ui/components/u-calendar/u-calendar.vue
generated
vendored
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
<template>
|
||||||
|
<u-popup
|
||||||
|
:show="show"
|
||||||
|
mode="bottom"
|
||||||
|
closeable
|
||||||
|
@close="close"
|
||||||
|
:round="round"
|
||||||
|
:closeOnClickOverlay="closeOnClickOverlay"
|
||||||
|
>
|
||||||
|
<view class="u-calendar">
|
||||||
|
<uHeader
|
||||||
|
:title="title"
|
||||||
|
:subtitle="subtitle"
|
||||||
|
:showSubtitle="showSubtitle"
|
||||||
|
:showTitle="showTitle"
|
||||||
|
></uHeader>
|
||||||
|
<scroll-view
|
||||||
|
:style="{
|
||||||
|
height: $u.addUnit(listHeight)
|
||||||
|
}"
|
||||||
|
scroll-y
|
||||||
|
@scroll="onScroll"
|
||||||
|
:scroll-top="scrollTop"
|
||||||
|
:scrollIntoView="scrollIntoView"
|
||||||
|
>
|
||||||
|
<uMonth
|
||||||
|
:color="color"
|
||||||
|
:rowHeight="rowHeight"
|
||||||
|
:showMark="showMark"
|
||||||
|
:months="months"
|
||||||
|
:mode="mode"
|
||||||
|
:maxCount="maxCount"
|
||||||
|
:startText="startText"
|
||||||
|
:endText="endText"
|
||||||
|
:defaultDate="defaultDate"
|
||||||
|
:minDate="innerMinDate"
|
||||||
|
:maxDate="innerMaxDate"
|
||||||
|
:maxMonth="monthNum"
|
||||||
|
:readonly="readonly"
|
||||||
|
:maxRange="maxRange"
|
||||||
|
:rangePrompt="rangePrompt"
|
||||||
|
:showRangePrompt="showRangePrompt"
|
||||||
|
:allowSameDay="allowSameDay"
|
||||||
|
ref="month"
|
||||||
|
@monthSelected="monthSelected"
|
||||||
|
@updateMonthTop="updateMonthTop"
|
||||||
|
></uMonth>
|
||||||
|
</scroll-view>
|
||||||
|
<slot name="footer" v-if="showConfirm">
|
||||||
|
<view class="u-calendar__confirm">
|
||||||
|
<u-button
|
||||||
|
shape="circle"
|
||||||
|
:text="
|
||||||
|
buttonDisabled ? confirmDisabledText : confirmText
|
||||||
|
"
|
||||||
|
:color="color"
|
||||||
|
@click="confirm"
|
||||||
|
:disabled="buttonDisabled"
|
||||||
|
></u-button>
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import uHeader from './header.vue'
|
||||||
|
import uMonth from './month.vue'
|
||||||
|
import props from './props.js'
|
||||||
|
import util from './util.js'
|
||||||
|
import dayjs from '../../libs/util/dayjs.js'
|
||||||
|
import Calendar from '../../libs/util/calendar.js'
|
||||||
|
/**
|
||||||
|
* Calendar 日历
|
||||||
|
* @description 此组件用于单个选择日期,范围选择日期等,日历被包裹在底部弹起的容器中.
|
||||||
|
* @tutorial https://www.uviewui.com/components/calendar.html
|
||||||
|
*
|
||||||
|
* @property {String} title 标题内容 (默认 日期选择 )
|
||||||
|
* @property {Boolean} showTitle 是否显示标题 (默认 true )
|
||||||
|
* @property {Boolean} showSubtitle 是否显示副标题 (默认 true )
|
||||||
|
* @property {String} mode 日期类型选择 single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 ( 默认 'single' )
|
||||||
|
* @property {String} startText mode=range时,第一个日期底部的提示文字 (默认 '开始' )
|
||||||
|
* @property {String} endText mode=range时,最后一个日期底部的提示文字 (默认 '结束' )
|
||||||
|
* @property {Array} customList 自定义列表
|
||||||
|
* @property {String} color 主题色,对底部按钮和选中日期有效 (默认 ‘#3c9cff' )
|
||||||
|
* @property {String | Number} minDate 最小的可选日期 (默认 0 )
|
||||||
|
* @property {String | Number} maxDate 最大可选日期 (默认 0 )
|
||||||
|
* @property {Array | String| Date} defaultDate 默认选中的日期,mode为multiple或range是必须为数组格式
|
||||||
|
* @property {String | Number} maxCount mode=multiple时,最多可选多少个日期 (默认 Number.MAX_SAFE_INTEGER )
|
||||||
|
* @property {String | Number} rowHeight 日期行高 (默认 56 )
|
||||||
|
* @property {Function} formatter 日期格式化函数
|
||||||
|
* @property {Boolean} showLunar 是否显示农历 (默认 false )
|
||||||
|
* @property {Boolean} showMark 是否显示月份背景色 (默认 true )
|
||||||
|
* @property {String} confirmText 确定按钮的文字 (默认 '确定' )
|
||||||
|
* @property {String} confirmDisabledText 确认按钮处于禁用状态时的文字 (默认 '确定' )
|
||||||
|
* @property {Boolean} show 是否显示日历弹窗 (默认 false )
|
||||||
|
* @property {Boolean} closeOnClickOverlay 是否允许点击遮罩关闭日历 (默认 false )
|
||||||
|
* @property {Boolean} readonly 是否为只读状态,只读状态下禁止选择日期 (默认 false )
|
||||||
|
* @property {String | Number} maxRange 日期区间最多可选天数,默认无限制,mode = range时有效
|
||||||
|
* @property {String} rangePrompt 范围选择超过最多可选天数时的提示文案,mode = range时有效
|
||||||
|
* @property {Boolean} showRangePrompt 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 (默认 true )
|
||||||
|
* @property {Boolean} allowSameDay 是否允许日期范围的起止时间为同一天,mode = range时有效 (默认 false )
|
||||||
|
* @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
|
||||||
|
* @property {Number|String} monthNum 最多展示的月份数量 (默认 3 )
|
||||||
|
*
|
||||||
|
* @event {Function()} confirm 点击确定按钮时触发 选择日期相关的返回参数
|
||||||
|
* @event {Function()} close 日历关闭时触发 可定义页面关闭时的回调事件
|
||||||
|
* @example <u-calendar :defaultDate="defaultDateMultiple" :show="show" mode="multiple" @confirm="confirm">
|
||||||
|
</u-calendar>
|
||||||
|
* */
|
||||||
|
export default {
|
||||||
|
name: 'u-calendar',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
components: {
|
||||||
|
uHeader,
|
||||||
|
uMonth
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 需要显示的月份的数组
|
||||||
|
months: [],
|
||||||
|
// 在月份滚动区域中,当前视图中月份的index索引
|
||||||
|
monthIndex: 0,
|
||||||
|
// 月份滚动区域的高度
|
||||||
|
listHeight: 0,
|
||||||
|
// month组件中选择的日期数组
|
||||||
|
selected: [],
|
||||||
|
scrollIntoView: '',
|
||||||
|
scrollTop:0,
|
||||||
|
// 过滤处理方法
|
||||||
|
innerFormatter: (value) => value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectedChange: {
|
||||||
|
immediate: true,
|
||||||
|
handler(n) {
|
||||||
|
this.setMonth()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 打开弹窗时,设置月份数据
|
||||||
|
show: {
|
||||||
|
immediate: true,
|
||||||
|
handler(n) {
|
||||||
|
this.setMonth()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 由于maxDate和minDate可以为字符串(2021-10-10),或者数值(时间戳),但是dayjs如果接受字符串形式的时间戳会有问题,这里进行处理
|
||||||
|
innerMaxDate() {
|
||||||
|
return uni.$u.test.number(this.maxDate)
|
||||||
|
? Number(this.maxDate)
|
||||||
|
: this.maxDate
|
||||||
|
},
|
||||||
|
innerMinDate() {
|
||||||
|
return uni.$u.test.number(this.minDate)
|
||||||
|
? Number(this.minDate)
|
||||||
|
: this.minDate
|
||||||
|
},
|
||||||
|
// 多个条件的变化,会引起选中日期的变化,这里统一管理监听
|
||||||
|
selectedChange() {
|
||||||
|
return [this.innerMinDate, this.innerMaxDate, this.defaultDate]
|
||||||
|
},
|
||||||
|
subtitle() {
|
||||||
|
// 初始化时,this.months为空数组,所以需要特别判断处理
|
||||||
|
if (this.months.length) {
|
||||||
|
return `${this.months[this.monthIndex].year}年${
|
||||||
|
this.months[this.monthIndex].month
|
||||||
|
}月`
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonDisabled() {
|
||||||
|
// 如果为range类型,且选择的日期个数不足1个时,让底部的按钮出于disabled状态
|
||||||
|
if (this.mode === 'range') {
|
||||||
|
if (this.selected.length <= 1) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.start = Date.now()
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
|
||||||
|
setFormatter(e) {
|
||||||
|
this.innerFormatter = e
|
||||||
|
},
|
||||||
|
// month组件内部选择日期后,通过事件通知给父组件
|
||||||
|
monthSelected(e) {
|
||||||
|
this.selected = e
|
||||||
|
if (!this.showConfirm) {
|
||||||
|
// 在不需要确认按钮的情况下,如果为单选,或者范围多选且已选长度大于2,则直接进行返还
|
||||||
|
if (
|
||||||
|
this.mode === 'multiple' ||
|
||||||
|
this.mode === 'single' ||
|
||||||
|
(this.mode === 'range' && this.selected.length >= 2)
|
||||||
|
) {
|
||||||
|
this.$emit('confirm', this.selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
// 校验maxDate,不能小于当前时间
|
||||||
|
if (
|
||||||
|
this.innerMaxDate &&
|
||||||
|
new Date(this.innerMaxDate).getTime() <= Date.now()
|
||||||
|
) {
|
||||||
|
return uni.$u.error('maxDate不能小于当前时间')
|
||||||
|
}
|
||||||
|
// 滚动区域的高度
|
||||||
|
this.listHeight = this.rowHeight * 5 + 30
|
||||||
|
this.setMonth()
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.$emit('close')
|
||||||
|
},
|
||||||
|
// 点击确定按钮
|
||||||
|
confirm() {
|
||||||
|
if (!this.buttonDisabled) {
|
||||||
|
this.$emit('confirm', this.selected)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获得两个日期之间的月份数
|
||||||
|
getMonths(minDate, maxDate) {
|
||||||
|
const minYear = dayjs(minDate).year()
|
||||||
|
const minMonth = dayjs(minDate).month() + 1
|
||||||
|
const maxYear = dayjs(maxDate).year()
|
||||||
|
const maxMonth = dayjs(maxDate).month() + 1
|
||||||
|
return (maxYear - minYear) * 12 + (maxMonth - minMonth) + 1
|
||||||
|
},
|
||||||
|
// 设置月份数据
|
||||||
|
setMonth() {
|
||||||
|
// 最小日期的毫秒数
|
||||||
|
const minDate = this.innerMinDate || dayjs().valueOf()
|
||||||
|
// 如果没有指定最大日期,则往后推3个月
|
||||||
|
const maxDate =
|
||||||
|
this.innerMaxDate ||
|
||||||
|
dayjs(minDate)
|
||||||
|
.add(this.monthNum - 1, 'month')
|
||||||
|
.valueOf()
|
||||||
|
// 最大最小月份之间的共有多少个月份,
|
||||||
|
const months = uni.$u.range(
|
||||||
|
1,
|
||||||
|
this.monthNum,
|
||||||
|
this.getMonths(minDate, maxDate)
|
||||||
|
)
|
||||||
|
// 先清空数组
|
||||||
|
this.months = []
|
||||||
|
for (let i = 0; i < months; i++) {
|
||||||
|
this.months.push({
|
||||||
|
date: new Array(
|
||||||
|
dayjs(minDate).add(i, 'month').daysInMonth()
|
||||||
|
)
|
||||||
|
.fill(1)
|
||||||
|
.map((item, index) => {
|
||||||
|
// 日期,取值1-31
|
||||||
|
let day = index + 1
|
||||||
|
// 星期,0-6,0为周日
|
||||||
|
const week = dayjs(minDate)
|
||||||
|
.add(i, 'month')
|
||||||
|
.date(day)
|
||||||
|
.day()
|
||||||
|
const date = dayjs(minDate)
|
||||||
|
.add(i, 'month')
|
||||||
|
.date(day)
|
||||||
|
.format('YYYY-MM-DD')
|
||||||
|
let bottomInfo = ''
|
||||||
|
if (this.showLunar) {
|
||||||
|
// 将日期转为农历格式
|
||||||
|
const lunar = Calendar.solar2lunar(
|
||||||
|
dayjs(date).year(),
|
||||||
|
dayjs(date).month() + 1,
|
||||||
|
dayjs(date).date()
|
||||||
|
)
|
||||||
|
bottomInfo = lunar.IDayCn
|
||||||
|
}
|
||||||
|
let config = {
|
||||||
|
day,
|
||||||
|
week,
|
||||||
|
// 小于最小允许的日期,或者大于最大的日期,则设置为disabled状态
|
||||||
|
disabled:
|
||||||
|
dayjs(date).isBefore(
|
||||||
|
dayjs(minDate).format('YYYY-MM-DD')
|
||||||
|
) ||
|
||||||
|
dayjs(date).isAfter(
|
||||||
|
dayjs(maxDate).format('YYYY-MM-DD')
|
||||||
|
),
|
||||||
|
// 返回一个日期对象,供外部的formatter获取当前日期的年月日等信息,进行加工处理
|
||||||
|
date: new Date(date),
|
||||||
|
bottomInfo,
|
||||||
|
dot: false,
|
||||||
|
month:
|
||||||
|
dayjs(minDate).add(i, 'month').month() + 1
|
||||||
|
}
|
||||||
|
const formatter =
|
||||||
|
this.formatter || this.innerFormatter
|
||||||
|
return formatter(config)
|
||||||
|
}),
|
||||||
|
// 当前所属的月份
|
||||||
|
month: dayjs(minDate).add(i, 'month').month() + 1,
|
||||||
|
// 当前年份
|
||||||
|
year: dayjs(minDate).add(i, 'month').year()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
// 滚动到默认设置的月份
|
||||||
|
scrollIntoDefaultMonth(selected) {
|
||||||
|
// 查询默认日期在可选列表的下标
|
||||||
|
const _index = this.months.findIndex(({
|
||||||
|
year,
|
||||||
|
month
|
||||||
|
}) => {
|
||||||
|
month = uni.$u.padZero(month)
|
||||||
|
return `${year}-${month}` === selected
|
||||||
|
})
|
||||||
|
if (_index !== -1) {
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollIntoView = `month-${_index}`
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.scrollTop = this.months[_index].top || 0;
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// scroll-view滚动监听
|
||||||
|
onScroll(event) {
|
||||||
|
// 不允许小于0的滚动值,如果scroll-view到顶了,继续下拉,会出现负数值
|
||||||
|
const scrollTop = Math.max(0, event.detail.scrollTop)
|
||||||
|
// 将当前滚动条数值,除以滚动区域的高度,可以得出当前滚动到了哪一个月份的索引
|
||||||
|
for (let i = 0; i < this.months.length; i++) {
|
||||||
|
if (scrollTop >= (this.months[i].top || this.listHeight)) {
|
||||||
|
this.monthIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 更新月份的top值
|
||||||
|
updateMonthTop(topArr = []) {
|
||||||
|
// 设置对应月份的top值,用于onScroll方法更新月份
|
||||||
|
topArr.map((item, index) => {
|
||||||
|
this.months[index].top = item
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取默认日期的下标
|
||||||
|
if (!this.defaultDate) {
|
||||||
|
// 如果没有设置默认日期,则将当天日期设置为默认选中的日期
|
||||||
|
const selected = dayjs().format("YYYY-MM")
|
||||||
|
this.scrollIntoDefaultMonth(selected)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let selected = dayjs().format("YYYY-MM");
|
||||||
|
// 单选模式,可以是字符串或数组,Date对象等
|
||||||
|
if (!uni.$u.test.array(this.defaultDate)) {
|
||||||
|
selected = dayjs(this.defaultDate).format("YYYY-MM")
|
||||||
|
} else {
|
||||||
|
selected = dayjs(this.defaultDate[0]).format("YYYY-MM");
|
||||||
|
}
|
||||||
|
this.scrollIntoDefaultMonth(selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../libs/css/components.scss';
|
||||||
|
|
||||||
|
.u-calendar {
|
||||||
|
&__confirm {
|
||||||
|
padding: 7px 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
85
node_modules/uview-ui/components/u-calendar/util.js
generated
vendored
Normal file
85
node_modules/uview-ui/components/u-calendar/util.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
// 设置月份数据
|
||||||
|
setMonth() {
|
||||||
|
// 月初是周几
|
||||||
|
const day = dayjs(this.date).date(1).day()
|
||||||
|
const start = day == 0 ? 6 : day - 1
|
||||||
|
|
||||||
|
// 本月天数
|
||||||
|
const days = dayjs(this.date).endOf('month').format('D')
|
||||||
|
|
||||||
|
// 上个月天数
|
||||||
|
const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
|
||||||
|
|
||||||
|
// 日期数据
|
||||||
|
const arr = []
|
||||||
|
// 清空表格
|
||||||
|
this.month = []
|
||||||
|
|
||||||
|
// 添加上月数据
|
||||||
|
arr.push(
|
||||||
|
...new Array(start).fill(1).map((e, i) => {
|
||||||
|
const day = prevDays - start + i + 1
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: day,
|
||||||
|
disabled: true,
|
||||||
|
date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 添加本月数据
|
||||||
|
arr.push(
|
||||||
|
...new Array(days - 0).fill(1).map((e, i) => {
|
||||||
|
const day = i + 1
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: day,
|
||||||
|
date: dayjs(this.date).date(day).format('YYYY-MM-DD')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 添加下个月
|
||||||
|
arr.push(
|
||||||
|
...new Array(42 - days - start).fill(1).map((e, i) => {
|
||||||
|
const day = i + 1
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: day,
|
||||||
|
disabled: true,
|
||||||
|
date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 分割数组
|
||||||
|
for (let n = 0; n < arr.length; n += 7) {
|
||||||
|
this.month.push(
|
||||||
|
arr.slice(n, n + 7).map((e, i) => {
|
||||||
|
e.index = i + n
|
||||||
|
|
||||||
|
// 自定义信息
|
||||||
|
const custom = this.customList.find((c) => c.date == e.date)
|
||||||
|
|
||||||
|
// 农历
|
||||||
|
if (this.lunar) {
|
||||||
|
const {
|
||||||
|
IDayCn,
|
||||||
|
IMonthCn
|
||||||
|
} = this.getLunar(e.date)
|
||||||
|
e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
...custom
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
node_modules/uview-ui/components/u-car-keyboard/props.js
generated
vendored
Normal file
14
node_modules/uview-ui/components/u-car-keyboard/props.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 是否打乱键盘按键的顺序
|
||||||
|
random: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 输入一个中文后,是否自动切换到英文
|
||||||
|
autoChange: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
311
node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue
generated
vendored
Normal file
311
node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="u-keyboard"
|
||||||
|
@touchmove.stop.prevent="noop"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-for="(group, i) in abc ? engKeyBoardList : areaList"
|
||||||
|
:key="i"
|
||||||
|
class="u-keyboard__button"
|
||||||
|
:index="i"
|
||||||
|
:class="[i + 1 === 4 && 'u-keyboard__button--center']"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-if="i === 3"
|
||||||
|
class="u-keyboard__button__inner-wrapper"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-keyboard__button__inner-wrapper__left"
|
||||||
|
hover-class="u-hover-class"
|
||||||
|
:hover-stay-time="200"
|
||||||
|
@tap="changeCarInputMode"
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
class="u-keyboard__button__inner-wrapper__left__lang"
|
||||||
|
:class="[!abc && 'u-keyboard__button__inner-wrapper__left__lang--active']"
|
||||||
|
>中</text>
|
||||||
|
<text class="u-keyboard__button__inner-wrapper__left__line">/</text>
|
||||||
|
<text
|
||||||
|
class="u-keyboard__button__inner-wrapper__left__lang"
|
||||||
|
:class="[abc && 'u-keyboard__button__inner-wrapper__left__lang--active']"
|
||||||
|
>英</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="u-keyboard__button__inner-wrapper"
|
||||||
|
v-for="(item, j) in group"
|
||||||
|
:key="j"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-keyboard__button__inner-wrapper__inner"
|
||||||
|
:hover-stay-time="200"
|
||||||
|
@tap="carInputClick(i, j)"
|
||||||
|
hover-class="u-hover-class"
|
||||||
|
>
|
||||||
|
<text class="u-keyboard__button__inner-wrapper__inner__text">{{ item }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="i === 3"
|
||||||
|
@touchstart="backspaceClick"
|
||||||
|
@touchend="clearTimer"
|
||||||
|
class="u-keyboard__button__inner-wrapper"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-keyboard__button__inner-wrapper__right"
|
||||||
|
hover-class="u-hover-class"
|
||||||
|
:hover-stay-time="200"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
size="28"
|
||||||
|
name="backspace"
|
||||||
|
color="#303133"
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* keyboard 键盘组件
|
||||||
|
* @description 此为uView自定义的键盘面板,内含了数字键盘,车牌号键,身份证号键盘3种模式,都有可以打乱按键顺序的选项。
|
||||||
|
* @tutorial https://uviewui.com/components/keyboard.html
|
||||||
|
* @property {Boolean} random 是否打乱键盘的顺序
|
||||||
|
* @event {Function} change 点击键盘触发
|
||||||
|
* @event {Function} backspace 点击退格键触发
|
||||||
|
* @example <u-keyboard ref="uKeyboard" mode="car" v-model="show"></u-keyboard>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-keyboard",
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 车牌输入时,abc=true为输入车牌号码,bac=false为输入省份中文简称
|
||||||
|
abc: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
areaList() {
|
||||||
|
let data = [
|
||||||
|
'京',
|
||||||
|
'沪',
|
||||||
|
'粤',
|
||||||
|
'津',
|
||||||
|
'冀',
|
||||||
|
'豫',
|
||||||
|
'云',
|
||||||
|
'辽',
|
||||||
|
'黑',
|
||||||
|
'湘',
|
||||||
|
'皖',
|
||||||
|
'鲁',
|
||||||
|
'苏',
|
||||||
|
'浙',
|
||||||
|
'赣',
|
||||||
|
'鄂',
|
||||||
|
'桂',
|
||||||
|
'甘',
|
||||||
|
'晋',
|
||||||
|
'陕',
|
||||||
|
'蒙',
|
||||||
|
'吉',
|
||||||
|
'闽',
|
||||||
|
'贵',
|
||||||
|
'渝',
|
||||||
|
'川',
|
||||||
|
'青',
|
||||||
|
'琼',
|
||||||
|
'宁',
|
||||||
|
'挂',
|
||||||
|
'藏',
|
||||||
|
'港',
|
||||||
|
'澳',
|
||||||
|
'新',
|
||||||
|
'使',
|
||||||
|
'学'
|
||||||
|
];
|
||||||
|
let tmp = [];
|
||||||
|
// 打乱顺序
|
||||||
|
if (this.random) data = uni.$u.randomArray(data);
|
||||||
|
// 切割成二维数组
|
||||||
|
tmp[0] = data.slice(0, 10);
|
||||||
|
tmp[1] = data.slice(10, 20);
|
||||||
|
tmp[2] = data.slice(20, 30);
|
||||||
|
tmp[3] = data.slice(30, 36);
|
||||||
|
return tmp;
|
||||||
|
},
|
||||||
|
engKeyBoardList() {
|
||||||
|
let data = [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
0,
|
||||||
|
'Q',
|
||||||
|
'W',
|
||||||
|
'E',
|
||||||
|
'R',
|
||||||
|
'T',
|
||||||
|
'Y',
|
||||||
|
'U',
|
||||||
|
'I',
|
||||||
|
'O',
|
||||||
|
'P',
|
||||||
|
'A',
|
||||||
|
'S',
|
||||||
|
'D',
|
||||||
|
'F',
|
||||||
|
'G',
|
||||||
|
'H',
|
||||||
|
'J',
|
||||||
|
'K',
|
||||||
|
'L',
|
||||||
|
'Z',
|
||||||
|
'X',
|
||||||
|
'C',
|
||||||
|
'V',
|
||||||
|
'B',
|
||||||
|
'N',
|
||||||
|
'M'
|
||||||
|
];
|
||||||
|
let tmp = [];
|
||||||
|
if (this.random) data = uni.$u.randomArray(data);
|
||||||
|
tmp[0] = data.slice(0, 10);
|
||||||
|
tmp[1] = data.slice(10, 20);
|
||||||
|
tmp[2] = data.slice(20, 30);
|
||||||
|
tmp[3] = data.slice(30, 36);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击键盘按钮
|
||||||
|
carInputClick(i, j) {
|
||||||
|
let value = '';
|
||||||
|
// 不同模式,获取不同数组的值
|
||||||
|
if (this.abc) value = this.engKeyBoardList[i][j];
|
||||||
|
else value = this.areaList[i][j];
|
||||||
|
// 如果允许自动切换,则将中文状态切换为英文
|
||||||
|
if (!this.abc && this.autoChange) uni.$u.sleep(200).then(() => this.abc = true)
|
||||||
|
this.$emit('change', value);
|
||||||
|
},
|
||||||
|
// 修改汽车牌键盘的输入模式,中文|英文
|
||||||
|
changeCarInputMode() {
|
||||||
|
this.abc = !this.abc;
|
||||||
|
},
|
||||||
|
// 点击退格键
|
||||||
|
backspaceClick() {
|
||||||
|
this.$emit('backspace');
|
||||||
|
clearInterval(this.timer); //再次清空定时器,防止重复注册定时器
|
||||||
|
this.timer = null;
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
this.$emit('backspace');
|
||||||
|
}, 250);
|
||||||
|
},
|
||||||
|
clearTimer() {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = null;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
$u-car-keyboard-background-color: rgb(224, 228, 230) !default;
|
||||||
|
$u-car-keyboard-padding:6px 0 6px !default;
|
||||||
|
$u-car-keyboard-button-inner-width:64rpx !default;
|
||||||
|
$u-car-keyboard-button-inner-background-color:#FFFFFF !default;
|
||||||
|
$u-car-keyboard-button-height:80rpx !default;
|
||||||
|
$u-car-keyboard-button-inner-box-shadow:0 1px 0px #999992 !default;
|
||||||
|
$u-car-keyboard-button-border-radius:4px !default;
|
||||||
|
$u-car-keyboard-button-inner-margin:8rpx 5rpx !default;
|
||||||
|
$u-car-keyboard-button-text-font-size:16px !default;
|
||||||
|
$u-car-keyboard-button-text-color:$u-main-color !default;
|
||||||
|
$u-car-keyboard-center-inner-margin: 0 4rpx !default;
|
||||||
|
$u-car-keyboard-special-button-width:134rpx !default;
|
||||||
|
$u-car-keyboard-lang-font-size:16px !default;
|
||||||
|
$u-car-keyboard-lang-color:$u-main-color !default;
|
||||||
|
$u-car-keyboard-active-color:$u-primary !default;
|
||||||
|
$u-car-keyboard-line-font-size:15px !default;
|
||||||
|
$u-car-keyboard-line-color:$u-main-color !default;
|
||||||
|
$u-car-keyboard-line-margin:0 1px !default;
|
||||||
|
$u-car-keyboard-u-hover-class-background-color:#BBBCC6 !default;
|
||||||
|
|
||||||
|
.u-keyboard {
|
||||||
|
@include flex(column);
|
||||||
|
justify-content: space-around;
|
||||||
|
background-color: $u-car-keyboard-background-color;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: $u-car-keyboard-padding;
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&__inner-wrapper {
|
||||||
|
box-shadow: $u-car-keyboard-button-inner-box-shadow;
|
||||||
|
margin: $u-car-keyboard-button-inner-margin;
|
||||||
|
border-radius: $u-car-keyboard-button-border-radius;
|
||||||
|
|
||||||
|
&__inner {
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: $u-car-keyboard-button-inner-width;
|
||||||
|
background-color: $u-car-keyboard-button-inner-background-color;
|
||||||
|
height: $u-car-keyboard-button-height;
|
||||||
|
border-radius: $u-car-keyboard-button-border-radius;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: $u-car-keyboard-button-text-font-size;
|
||||||
|
color: $u-car-keyboard-button-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left,
|
||||||
|
&__right {
|
||||||
|
border-radius: $u-car-keyboard-button-border-radius;
|
||||||
|
width: $u-car-keyboard-special-button-width;
|
||||||
|
height: $u-car-keyboard-button-height;
|
||||||
|
background-color: $u-car-keyboard-u-hover-class-background-color;
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: $u-car-keyboard-button-inner-box-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left {
|
||||||
|
&__line {
|
||||||
|
font-size: $u-car-keyboard-line-font-size;
|
||||||
|
color: $u-car-keyboard-line-color;
|
||||||
|
margin: $u-car-keyboard-line-margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__lang {
|
||||||
|
font-size: $u-car-keyboard-lang-font-size;
|
||||||
|
color: $u-car-keyboard-lang-color;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
color: $u-car-keyboard-active-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-hover-class {
|
||||||
|
background-color: $u-car-keyboard-u-hover-class-background-color;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
14
node_modules/uview-ui/components/u-cell-group/props.js
generated
vendored
Normal file
14
node_modules/uview-ui/components/u-cell-group/props.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 分组标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cellGroup.title
|
||||||
|
},
|
||||||
|
// 是否显示外边框
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cellGroup.border
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
node_modules/uview-ui/components/u-cell-group/u-cell-group.vue
generated
vendored
Normal file
61
node_modules/uview-ui/components/u-cell-group/u-cell-group.vue
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<view :style="[$u.addStyle(customStyle)]" :class="[customClass]" class="u-cell-group">
|
||||||
|
<view v-if="title" class="u-cell-group__title">
|
||||||
|
<slot name="title">
|
||||||
|
<text class="u-cell-group__title__text">{{ title }}</text>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
<view class="u-cell-group__wrapper">
|
||||||
|
<u-line v-if="border"></u-line>
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* cellGroup 单元格
|
||||||
|
* @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。
|
||||||
|
* @tutorial https://uviewui.com/components/cell.html
|
||||||
|
*
|
||||||
|
* @property {String} title 分组标题
|
||||||
|
* @property {Boolean} border 是否显示外边框 (默认 true )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @event {Function} click 点击cell列表时触发
|
||||||
|
* @example <u-cell-group title="设置喜好">
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-cell-group',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
$u-cell-group-title-padding: 16px 16px 8px !default;
|
||||||
|
$u-cell-group-title-font-size: 15px !default;
|
||||||
|
$u-cell-group-title-line-height: 16px !default;
|
||||||
|
$u-cell-group-title-color: $u-main-color !default;
|
||||||
|
|
||||||
|
.u-cell-group {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
padding: $u-cell-group-title-padding;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: $u-cell-group-title-font-size;
|
||||||
|
line-height: $u-cell-group-title-line-height;
|
||||||
|
color: $u-cell-group-title-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
110
node_modules/uview-ui/components/u-cell/props.js
generated
vendored
Normal file
110
node_modules/uview-ui/components/u-cell/props.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.cell.title
|
||||||
|
},
|
||||||
|
// 标题下方的描述信息
|
||||||
|
label: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.cell.label
|
||||||
|
},
|
||||||
|
// 右侧的内容
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.cell.value
|
||||||
|
},
|
||||||
|
// 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.icon
|
||||||
|
},
|
||||||
|
// 是否禁用cell
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.disabled
|
||||||
|
},
|
||||||
|
// 是否显示下边框
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.border
|
||||||
|
},
|
||||||
|
// 内容是否垂直居中(主要是针对右侧的value部分)
|
||||||
|
center: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.center
|
||||||
|
},
|
||||||
|
// 点击后跳转的URL地址
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.url
|
||||||
|
},
|
||||||
|
// 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作
|
||||||
|
linkType: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.linkType
|
||||||
|
},
|
||||||
|
// 是否开启点击反馈(表现为点击时加上灰色背景)
|
||||||
|
clickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.clickable
|
||||||
|
},
|
||||||
|
// 是否展示右侧箭头并开启点击反馈
|
||||||
|
isLink: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.isLink
|
||||||
|
},
|
||||||
|
// 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件)
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.required
|
||||||
|
},
|
||||||
|
// 右侧的图标箭头
|
||||||
|
rightIcon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.rightIcon
|
||||||
|
},
|
||||||
|
// 右侧箭头的方向,可选值为:left,up,down
|
||||||
|
arrowDirection: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.arrowDirection
|
||||||
|
},
|
||||||
|
// 左侧图标样式
|
||||||
|
iconStyle: {
|
||||||
|
type: [Object, String],
|
||||||
|
default: () => {
|
||||||
|
return uni.$u.props.cell.iconStyle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 右侧箭头图标的样式
|
||||||
|
rightIconStyle: {
|
||||||
|
type: [Object, String],
|
||||||
|
default: () => {
|
||||||
|
return uni.$u.props.cell.rightIconStyle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 标题的样式
|
||||||
|
titleStyle: {
|
||||||
|
type: [Object, String],
|
||||||
|
default: () => {
|
||||||
|
return uni.$u.props.cell.titleStyle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 单位元的大小,可选值为large
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.cell.size
|
||||||
|
},
|
||||||
|
// 点击cell是否阻止事件传播
|
||||||
|
stop: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.cell.stop
|
||||||
|
},
|
||||||
|
// 标识符,cell被点击时返回
|
||||||
|
name: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: uni.$u.props.cell.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
229
node_modules/uview-ui/components/u-cell/u-cell.vue
generated
vendored
Normal file
229
node_modules/uview-ui/components/u-cell/u-cell.vue
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-cell" :class="[customClass]" :style="[$u.addStyle(customStyle)]"
|
||||||
|
:hover-class="(!disabled && (clickable || isLink)) ? 'u-cell--clickable' : ''" :hover-stay-time="250"
|
||||||
|
@tap="clickHandler">
|
||||||
|
<view class="u-cell__body" :class="[ center && 'u-cell--center', size === 'large' && 'u-cell__body--large']">
|
||||||
|
<view class="u-cell__body__content">
|
||||||
|
<view class="u-cell__left-icon-wrap" v-if="$slots.icon || icon">
|
||||||
|
<slot name="icon" v-if="$slots.icon">
|
||||||
|
</slot>
|
||||||
|
<u-icon v-else :name="icon" :custom-style="iconStyle" :size="size === 'large' ? 22 : 18"></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="u-cell__title">
|
||||||
|
<slot name="title">
|
||||||
|
<text v-if="title" class="u-cell__title-text" :style="[titleTextStyle]"
|
||||||
|
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text>
|
||||||
|
</slot>
|
||||||
|
<slot name="label">
|
||||||
|
<text class="u-cell__label" v-if="label"
|
||||||
|
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__label--large']">{{ label }}</text>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<slot name="value">
|
||||||
|
<text class="u-cell__value"
|
||||||
|
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__value--large']"
|
||||||
|
v-if="!$u.test.empty(value)">{{ value }}</text>
|
||||||
|
</slot>
|
||||||
|
<view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink"
|
||||||
|
:class="[`u-cell__right-icon-wrap--${arrowDirection}`]">
|
||||||
|
<slot name="right-icon" v-if="$slots['right-icon']">
|
||||||
|
</slot>
|
||||||
|
<u-icon v-else :name="rightIcon" :custom-style="rightIconStyle" :color="disabled ? '#c8c9cc' : 'info'"
|
||||||
|
:size="size === 'large' ? 18 : 16"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-line v-if="border"></u-line>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* cell 单元格
|
||||||
|
* @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。
|
||||||
|
* @tutorial https://uviewui.com/components/cell.html
|
||||||
|
* @property {String | Number} title 标题
|
||||||
|
* @property {String | Number} label 标题下方的描述信息
|
||||||
|
* @property {String | Number} value 右侧的内容
|
||||||
|
* @property {String} icon 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
|
||||||
|
* @property {Boolean} disabled 是否禁用cell
|
||||||
|
* @property {Boolean} border 是否显示下边框 (默认 true )
|
||||||
|
* @property {Boolean} center 内容是否垂直居中(主要是针对右侧的value部分) (默认 false )
|
||||||
|
* @property {String} url 点击后跳转的URL地址
|
||||||
|
* @property {String} linkType 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 (默认 'navigateTo' )
|
||||||
|
* @property {Boolean} clickable 是否开启点击反馈(表现为点击时加上灰色背景) (默认 false )
|
||||||
|
* @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 (默认 false )
|
||||||
|
* @property {Boolean} required 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) (默认 false )
|
||||||
|
* @property {String} rightIcon 右侧的图标箭头 (默认 'arrow-right')
|
||||||
|
* @property {String} arrowDirection 右侧箭头的方向,可选值为:left,up,down
|
||||||
|
* @property {Object | String} rightIconStyle 右侧箭头图标的样式
|
||||||
|
* @property {Object | String} titleStyle 标题的样式
|
||||||
|
* @property {Object | String} iconStyle 左侧图标样式
|
||||||
|
* @property {String} size 单位元的大小,可选值为 large,normal,mini
|
||||||
|
* @property {Boolean} stop 点击cell是否阻止事件传播 (默认 true )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @event {Function} click 点击cell列表时触发
|
||||||
|
* @example 该组件需要搭配cell-group组件使用,见官方文档示例
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-cell',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
computed: {
|
||||||
|
titleTextStyle() {
|
||||||
|
return uni.$u.addStyle(this.titleStyle)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击cell
|
||||||
|
clickHandler(e) {
|
||||||
|
if (this.disabled) return
|
||||||
|
this.$emit('click', {
|
||||||
|
name: this.name
|
||||||
|
})
|
||||||
|
// 如果配置了url(此props参数通过mixin引入)参数,跳转页面
|
||||||
|
this.openPage()
|
||||||
|
// 是否阻止事件传播
|
||||||
|
this.stop && this.preventEvent(e)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
$u-cell-padding: 10px 15px !default;
|
||||||
|
$u-cell-font-size: 15px !default;
|
||||||
|
$u-cell-line-height: 24px !default;
|
||||||
|
$u-cell-color: $u-main-color !default;
|
||||||
|
$u-cell-icon-size: 16px !default;
|
||||||
|
$u-cell-title-font-size: 15px !default;
|
||||||
|
$u-cell-title-line-height: 22px !default;
|
||||||
|
$u-cell-title-color: $u-main-color !default;
|
||||||
|
$u-cell-label-font-size: 12px !default;
|
||||||
|
$u-cell-label-color: $u-tips-color !default;
|
||||||
|
$u-cell-label-line-height: 18px !default;
|
||||||
|
$u-cell-value-font-size: 14px !default;
|
||||||
|
$u-cell-value-color: $u-content-color !default;
|
||||||
|
$u-cell-clickable-color: $u-bg-color !default;
|
||||||
|
$u-cell-disabled-color: #c8c9cc !default;
|
||||||
|
$u-cell-padding-top-large: 13px !default;
|
||||||
|
$u-cell-padding-bottom-large: 13px !default;
|
||||||
|
$u-cell-value-font-size-large: 15px !default;
|
||||||
|
$u-cell-label-font-size-large: 14px !default;
|
||||||
|
$u-cell-title-font-size-large: 16px !default;
|
||||||
|
$u-cell-left-icon-wrap-margin-right: 4px !default;
|
||||||
|
$u-cell-right-icon-wrap-margin-left: 4px !default;
|
||||||
|
$u-cell-title-flex:1 !default;
|
||||||
|
$u-cell-label-margin-top:5px !default;
|
||||||
|
|
||||||
|
|
||||||
|
.u-cell {
|
||||||
|
&__body {
|
||||||
|
@include flex();
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* #endif */
|
||||||
|
padding: $u-cell-padding;
|
||||||
|
font-size: $u-cell-font-size;
|
||||||
|
color: $u-cell-color;
|
||||||
|
// line-height: $u-cell-line-height;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
@include flex(row);
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
padding-top: $u-cell-padding-top-large;
|
||||||
|
padding-bottom: $u-cell-padding-bottom-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left-icon-wrap,
|
||||||
|
&__right-icon-wrap {
|
||||||
|
@include flex();
|
||||||
|
align-items: center;
|
||||||
|
// height: $u-cell-line-height;
|
||||||
|
font-size: $u-cell-icon-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left-icon-wrap {
|
||||||
|
margin-right: $u-cell-left-icon-wrap-margin-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__right-icon-wrap {
|
||||||
|
margin-left: $u-cell-right-icon-wrap-margin-left;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
|
||||||
|
&--up {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--down {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
flex: $u-cell-title-flex;
|
||||||
|
|
||||||
|
&-text {
|
||||||
|
font-size: $u-cell-title-font-size;
|
||||||
|
line-height: $u-cell-title-line-height;
|
||||||
|
color: $u-cell-title-color;
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
font-size: $u-cell-title-font-size-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
margin-top: $u-cell-label-margin-top;
|
||||||
|
font-size: $u-cell-label-font-size;
|
||||||
|
color: $u-cell-label-color;
|
||||||
|
line-height: $u-cell-label-line-height;
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
font-size: $u-cell-label-font-size-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
text-align: right;
|
||||||
|
font-size: $u-cell-value-font-size;
|
||||||
|
line-height: $u-cell-line-height;
|
||||||
|
color: $u-cell-value-color;
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
font-size: $u-cell-value-font-size-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--clickable {
|
||||||
|
background-color: $u-cell-clickable-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: $u-cell-disabled-color;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
cursor: not-allowed;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
&--center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
82
node_modules/uview-ui/components/u-checkbox-group/props.js
generated
vendored
Normal file
82
node_modules/uview-ui/components/u-checkbox-group/props.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 标识符
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.name
|
||||||
|
},
|
||||||
|
// 绑定的值
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: uni.$u.props.checkboxGroup.value
|
||||||
|
},
|
||||||
|
// 形状,circle-圆形,square-方形
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.shape
|
||||||
|
},
|
||||||
|
// 是否禁用全部checkbox
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.checkboxGroup.disabled
|
||||||
|
},
|
||||||
|
|
||||||
|
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||||
|
activeColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.activeColor
|
||||||
|
},
|
||||||
|
// 未选中的颜色
|
||||||
|
inactiveColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.inactiveColor
|
||||||
|
},
|
||||||
|
|
||||||
|
// 整个组件的尺寸,默认px
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkboxGroup.size
|
||||||
|
},
|
||||||
|
// 布局方式,row-横向,column-纵向
|
||||||
|
placement: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.placement
|
||||||
|
},
|
||||||
|
// label的字体大小,px单位
|
||||||
|
labelSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkboxGroup.labelSize
|
||||||
|
},
|
||||||
|
// label的字体颜色
|
||||||
|
labelColor: {
|
||||||
|
type: [String],
|
||||||
|
default: uni.$u.props.checkboxGroup.labelColor
|
||||||
|
},
|
||||||
|
// 是否禁止点击文本操作
|
||||||
|
labelDisabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.checkboxGroup.labelDisabled
|
||||||
|
},
|
||||||
|
// 图标颜色
|
||||||
|
iconColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.iconColor
|
||||||
|
},
|
||||||
|
// 图标的大小,单位px
|
||||||
|
iconSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkboxGroup.iconSize
|
||||||
|
},
|
||||||
|
// 勾选图标的对齐方式,left-左边,right-右边
|
||||||
|
iconPlacement: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkboxGroup.iconPlacement
|
||||||
|
},
|
||||||
|
// 竖向配列时,是否显示下划线
|
||||||
|
borderBottom: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.checkboxGroup.borderBottom
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
103
node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
generated
vendored
Normal file
103
node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="u-checkbox-group"
|
||||||
|
:class="bemClass"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* checkboxGroup 复选框组
|
||||||
|
* @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
|
||||||
|
* @tutorial https://www.uviewui.com/components/checkbox.html
|
||||||
|
* @property {String} name 标识符
|
||||||
|
* @property {Array} value 绑定的值
|
||||||
|
* @property {String} shape 形状,circle-圆形,square-方形 (默认 'square' )
|
||||||
|
* @property {Boolean} disabled 是否禁用全部checkbox (默认 false )
|
||||||
|
* @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' )
|
||||||
|
* @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' )
|
||||||
|
* @property {String | Number} size 整个组件的尺寸 单位px (默认 18 )
|
||||||
|
* @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' )
|
||||||
|
* @property {String | Number} labelSize label的字体大小,px单位 (默认 14 )
|
||||||
|
* @property {String} labelColor label的字体颜色 (默认 '#303133' )
|
||||||
|
* @property {Boolean} labelDisabled 是否禁止点击文本操作 (默认 false )
|
||||||
|
* @property {String} iconColor 图标颜色 (默认 '#ffffff' )
|
||||||
|
* @property {String | Number} iconSize 图标的大小,单位px (默认 12 )
|
||||||
|
* @property {String} iconPlacement 勾选图标的对齐方式,left-左边,right-右边 (默认 'left' )
|
||||||
|
* @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false )
|
||||||
|
* @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
|
||||||
|
* @event {Function} input 修改通过v-model绑定的值时触发,回调为一个对象
|
||||||
|
* @example <u-checkbox-group></u-checkbox-group>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-checkbox-group',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
computed: {
|
||||||
|
// 这里computed的变量,都是子组件u-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
|
||||||
|
// 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-checkbox-group)
|
||||||
|
// 拉取父组件新的变化后的参数
|
||||||
|
parentData() {
|
||||||
|
return [this.value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape,
|
||||||
|
this.iconSize, this.borderBottom, this.placement
|
||||||
|
]
|
||||||
|
},
|
||||||
|
bemClass() {
|
||||||
|
// this.bem为一个computed变量,在mixin中
|
||||||
|
return this.bem('checkbox-group', ['placement'])
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
|
||||||
|
parentData() {
|
||||||
|
if (this.children.length) {
|
||||||
|
this.children.map(child => {
|
||||||
|
// 判断子组件(u-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
|
||||||
|
typeof(child.init) === 'function' && child.init()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.children = []
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 将其他的checkbox设置为未选中的状态
|
||||||
|
unCheckedOther(childInstance) {
|
||||||
|
const values = []
|
||||||
|
this.children.map(child => {
|
||||||
|
// 将被选中的checkbox,放到数组中返回
|
||||||
|
if (child.isChecked) {
|
||||||
|
values.push(child.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 发出事件
|
||||||
|
this.$emit('change', values)
|
||||||
|
// 修改通过v-model绑定的值
|
||||||
|
this.$emit('input', values)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-checkbox-group {
|
||||||
|
|
||||||
|
&--row {
|
||||||
|
@include flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--column {
|
||||||
|
@include flex(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
69
node_modules/uview-ui/components/u-checkbox/props.js
generated
vendored
Normal file
69
node_modules/uview-ui/components/u-checkbox/props.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// checkbox的名称
|
||||||
|
name: {
|
||||||
|
type: [String, Number, Boolean],
|
||||||
|
default: uni.$u.props.checkbox.name
|
||||||
|
},
|
||||||
|
// 形状,square为方形,circle为圆型
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkbox.shape
|
||||||
|
},
|
||||||
|
// 整体的大小
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkbox.size
|
||||||
|
},
|
||||||
|
// 是否默认选中
|
||||||
|
checked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.checkbox.checked
|
||||||
|
},
|
||||||
|
// 是否禁用
|
||||||
|
disabled: {
|
||||||
|
type: [String, Boolean],
|
||||||
|
default: uni.$u.props.checkbox.disabled
|
||||||
|
},
|
||||||
|
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||||
|
activeColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkbox.activeColor
|
||||||
|
},
|
||||||
|
// 未选中的颜色
|
||||||
|
inactiveColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkbox.inactiveColor
|
||||||
|
},
|
||||||
|
// 图标的大小,单位px
|
||||||
|
iconSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkbox.iconSize
|
||||||
|
},
|
||||||
|
// 图标颜色
|
||||||
|
iconColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkbox.iconColor
|
||||||
|
},
|
||||||
|
// label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
|
||||||
|
label: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkbox.label
|
||||||
|
},
|
||||||
|
// label的字体大小,px单位
|
||||||
|
labelSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.checkbox.labelSize
|
||||||
|
},
|
||||||
|
// label的颜色
|
||||||
|
labelColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.checkbox.labelColor
|
||||||
|
},
|
||||||
|
// 是否禁止点击提示语选中复选框
|
||||||
|
labelDisabled: {
|
||||||
|
type: [String, Boolean],
|
||||||
|
default: uni.$u.props.checkbox.labelDisabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
344
node_modules/uview-ui/components/u-checkbox/u-checkbox.vue
generated
vendored
Normal file
344
node_modules/uview-ui/components/u-checkbox/u-checkbox.vue
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="u-checkbox"
|
||||||
|
:style="[checkboxStyle]"
|
||||||
|
@tap.stop="wrapperClickHandler"
|
||||||
|
:class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-checkbox__icon-wrap"
|
||||||
|
@tap.stop="iconClickHandler"
|
||||||
|
:class="iconClasses"
|
||||||
|
:style="[iconWrapStyle]"
|
||||||
|
>
|
||||||
|
<slot name="icon">
|
||||||
|
<u-icon
|
||||||
|
class="u-checkbox__icon-wrap__icon"
|
||||||
|
name="checkbox-mark"
|
||||||
|
:size="elIconSize"
|
||||||
|
:color="elIconColor"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
<text
|
||||||
|
@tap.stop="labelClickHandler"
|
||||||
|
:style="{
|
||||||
|
color: elDisabled ? elInactiveColor : elLabelColor,
|
||||||
|
fontSize: elLabelSize,
|
||||||
|
lineHeight: elLabelSize
|
||||||
|
}"
|
||||||
|
>{{label}}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* checkbox 复选框
|
||||||
|
* @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
|
||||||
|
* @tutorial https://uviewui.com/components/checkbox.html
|
||||||
|
* @property {String | Number | Boolean} name checkbox组件的标示符
|
||||||
|
* @property {String} shape 形状,square为方形,circle为圆型
|
||||||
|
* @property {String | Number} size 整体的大小
|
||||||
|
* @property {Boolean} checked 是否默认选中
|
||||||
|
* @property {String | Boolean} disabled 是否禁用
|
||||||
|
* @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||||
|
* @property {String} inactiveColor 未选中的颜色
|
||||||
|
* @property {String | Number} iconSize 图标的大小,单位px
|
||||||
|
* @property {String} iconColor 图标颜色
|
||||||
|
* @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
|
||||||
|
* @property {String} labelColor label的颜色
|
||||||
|
* @property {String | Number} labelSize label的字体大小,px单位
|
||||||
|
* @property {String | Boolean} labelDisabled 是否禁止点击提示语选中复选框
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
*
|
||||||
|
* @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
|
||||||
|
* @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-checkbox",
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isChecked: false,
|
||||||
|
// 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式
|
||||||
|
// 故只能使用如此方法
|
||||||
|
parentData: {
|
||||||
|
iconSize: 12,
|
||||||
|
labelDisabled: null,
|
||||||
|
disabled: null,
|
||||||
|
shape: 'square',
|
||||||
|
activeColor: null,
|
||||||
|
inactiveColor: null,
|
||||||
|
size: 18,
|
||||||
|
value: null,
|
||||||
|
iconColor: null,
|
||||||
|
placement: 'row',
|
||||||
|
borderBottom: false,
|
||||||
|
iconPlacement: 'left'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置
|
||||||
|
elDisabled() {
|
||||||
|
return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
|
||||||
|
},
|
||||||
|
// 是否禁用label点击
|
||||||
|
elLabelDisabled() {
|
||||||
|
return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled :
|
||||||
|
false;
|
||||||
|
},
|
||||||
|
// 组件尺寸,对应size的值,默认值为21px
|
||||||
|
elSize() {
|
||||||
|
return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21);
|
||||||
|
},
|
||||||
|
// 组件的勾选图标的尺寸,默认12px
|
||||||
|
elIconSize() {
|
||||||
|
return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12);
|
||||||
|
},
|
||||||
|
// 组件选中激活时的颜色
|
||||||
|
elActiveColor() {
|
||||||
|
return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff');
|
||||||
|
},
|
||||||
|
// 组件选未中激活时的颜色
|
||||||
|
elInactiveColor() {
|
||||||
|
return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor :
|
||||||
|
'#c8c9cc');
|
||||||
|
},
|
||||||
|
// label的颜色
|
||||||
|
elLabelColor() {
|
||||||
|
return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266')
|
||||||
|
},
|
||||||
|
// 组件的形状
|
||||||
|
elShape() {
|
||||||
|
return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle');
|
||||||
|
},
|
||||||
|
// label大小
|
||||||
|
elLabelSize() {
|
||||||
|
return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize :
|
||||||
|
'15'))
|
||||||
|
},
|
||||||
|
elIconColor() {
|
||||||
|
const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor :
|
||||||
|
'#ffffff');
|
||||||
|
// 图标的颜色
|
||||||
|
if (this.elDisabled) {
|
||||||
|
// disabled状态下,已勾选的checkbox图标改为elInactiveColor
|
||||||
|
return this.isChecked ? this.elInactiveColor : 'transparent'
|
||||||
|
} else {
|
||||||
|
return this.isChecked ? iconColor : 'transparent'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
iconClasses() {
|
||||||
|
let classes = []
|
||||||
|
// 组件的形状
|
||||||
|
classes.push('u-checkbox__icon-wrap--' + this.elShape)
|
||||||
|
if (this.elDisabled) {
|
||||||
|
classes.push('u-checkbox__icon-wrap--disabled')
|
||||||
|
}
|
||||||
|
if (this.isChecked && this.elDisabled) {
|
||||||
|
classes.push('u-checkbox__icon-wrap--disabled--checked')
|
||||||
|
}
|
||||||
|
// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
|
||||||
|
// #ifdef MP-ALIPAY || MP-TOUTIAO
|
||||||
|
classes = classes.join(' ')
|
||||||
|
// #endif
|
||||||
|
return classes
|
||||||
|
},
|
||||||
|
iconWrapStyle() {
|
||||||
|
// checkbox的整体样式
|
||||||
|
const style = {}
|
||||||
|
style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff'
|
||||||
|
style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor
|
||||||
|
style.width = uni.$u.addUnit(this.elSize)
|
||||||
|
style.height = uni.$u.addUnit(this.elSize)
|
||||||
|
// 如果是图标在右边的话,移除它的右边距
|
||||||
|
if (this.parentData.iconPlacement === 'right') {
|
||||||
|
style.marginRight = 0
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
},
|
||||||
|
checkboxStyle() {
|
||||||
|
const style = {}
|
||||||
|
if (this.parentData.borderBottom && this.parentData.placement === 'row') {
|
||||||
|
uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-checkbox-group的placement设置为column才有效')
|
||||||
|
}
|
||||||
|
// 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔
|
||||||
|
if (this.parentData.borderBottom && this.parentData.placement === 'column') {
|
||||||
|
style.paddingBottom = '8px'
|
||||||
|
}
|
||||||
|
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
|
||||||
|
this.updateParentData()
|
||||||
|
if (!this.parent) {
|
||||||
|
uni.$u.error('u-checkbox必须搭配u-checkbox-group组件使用')
|
||||||
|
}
|
||||||
|
// 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
|
||||||
|
if (this.checked) {
|
||||||
|
this.isChecked = true
|
||||||
|
} else if (uni.$u.test.array(this.parentData.value)) {
|
||||||
|
// 查找数组是是否存在this.name元素值
|
||||||
|
this.isChecked = this.parentData.value.some(item => {
|
||||||
|
return item === this.name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateParentData() {
|
||||||
|
this.getParentData('u-checkbox-group')
|
||||||
|
},
|
||||||
|
// 横向两端排列时,点击组件即可触发选中事件
|
||||||
|
wrapperClickHandler(e) {
|
||||||
|
this.parentData.iconPlacement === 'right' && this.iconClickHandler(e)
|
||||||
|
},
|
||||||
|
// 点击图标
|
||||||
|
iconClickHandler(e) {
|
||||||
|
this.preventEvent(e)
|
||||||
|
// 如果整体被禁用,不允许被点击
|
||||||
|
if (!this.elDisabled) {
|
||||||
|
this.setRadioCheckedStatus()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 点击label
|
||||||
|
labelClickHandler(e) {
|
||||||
|
this.preventEvent(e)
|
||||||
|
// 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态
|
||||||
|
if (!this.elLabelDisabled && !this.elDisabled) {
|
||||||
|
this.setRadioCheckedStatus()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emitEvent() {
|
||||||
|
this.$emit('change', this.isChecked)
|
||||||
|
// 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时
|
||||||
|
this.$nextTick(() => {
|
||||||
|
uni.$u.formValidate(this, 'change')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 改变组件选中状态
|
||||||
|
// 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-checkbox实例
|
||||||
|
// 将本组件外的其他u-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态
|
||||||
|
setRadioCheckedStatus() {
|
||||||
|
// 将本组件标记为与原来相反的状态
|
||||||
|
this.isChecked = !this.isChecked
|
||||||
|
this.emitEvent()
|
||||||
|
typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
checked(){
|
||||||
|
this.isChecked = this.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
$u-checkbox-icon-wrap-margin-right:6px !default;
|
||||||
|
$u-checkbox-icon-wrap-font-size:6px !default;
|
||||||
|
$u-checkbox-icon-wrap-border-width:1px !default;
|
||||||
|
$u-checkbox-icon-wrap-border-color:#c8c9cc !default;
|
||||||
|
$u-checkbox-icon-wrap-icon-line-height:0 !default;
|
||||||
|
$u-checkbox-icon-wrap-circle-border-radius:100% !default;
|
||||||
|
$u-checkbox-icon-wrap-square-border-radius:3px !default;
|
||||||
|
$u-checkbox-icon-wrap-checked-color:#fff !default;
|
||||||
|
$u-checkbox-icon-wrap-checked-background-color:red !default;
|
||||||
|
$u-checkbox-icon-wrap-checked-border-color:#2979ff !default;
|
||||||
|
$u-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default;
|
||||||
|
$u-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default;
|
||||||
|
$u-checkbox-label-margin-left:5px !default;
|
||||||
|
$u-checkbox-label-margin-right:12px !default;
|
||||||
|
$u-checkbox-label-color:$u-content-color !default;
|
||||||
|
$u-checkbox-label-font-size:15px !default;
|
||||||
|
$u-checkbox-label-disabled-color:#c8c9cc !default;
|
||||||
|
|
||||||
|
.u-checkbox {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
@include flex(row);
|
||||||
|
/* #endif */
|
||||||
|
overflow: hidden;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-label--left {
|
||||||
|
flex-direction: row
|
||||||
|
}
|
||||||
|
|
||||||
|
&-label--right {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: space-between
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon-wrap {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
box-sizing: border-box;
|
||||||
|
// nvue下,border-color过渡有问题
|
||||||
|
transition-property: border-color, background-color, color;
|
||||||
|
transition-duration: 0.2s;
|
||||||
|
/* #endif */
|
||||||
|
color: $u-content-color;
|
||||||
|
@include flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: $u-checkbox-icon-wrap-margin-right;
|
||||||
|
|
||||||
|
font-size: $u-checkbox-icon-wrap-font-size;
|
||||||
|
border-width: $u-checkbox-icon-wrap-border-width;
|
||||||
|
border-color: $u-checkbox-icon-wrap-border-color;
|
||||||
|
border-style: solid;
|
||||||
|
|
||||||
|
/* #ifdef MP-TOUTIAO */
|
||||||
|
// 头条小程序兼容性问题,需要设置行高为0,否则图标偏下
|
||||||
|
&__icon {
|
||||||
|
line-height: $u-checkbox-icon-wrap-icon-line-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&--circle {
|
||||||
|
border-radius: $u-checkbox-icon-wrap-circle-border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--square {
|
||||||
|
border-radius: $u-checkbox-icon-wrap-square-border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--checked {
|
||||||
|
color: $u-checkbox-icon-wrap-checked-color;
|
||||||
|
background-color: $u-checkbox-icon-wrap-checked-background-color;
|
||||||
|
border-color: $u-checkbox-icon-wrap-checked-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
background-color: $u-checkbox-icon-wrap-disabled-background-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled--checked {
|
||||||
|
color: $u-checkbox-icon-wrap-disabled-checked-color !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
word-wrap: break-word;
|
||||||
|
/* #endif */
|
||||||
|
margin-left: $u-checkbox-label-margin-left;
|
||||||
|
margin-right: $u-checkbox-label-margin-right;
|
||||||
|
color: $u-checkbox-label-color;
|
||||||
|
font-size: $u-checkbox-label-font-size;
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: $u-checkbox-label-disabled-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
8
node_modules/uview-ui/components/u-circle-progress/props.js
generated
vendored
Normal file
8
node_modules/uview-ui/components/u-circle-progress/props.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
percentage: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.circleProgress.percentage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
198
node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue
generated
vendored
Normal file
198
node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-circle-progress">
|
||||||
|
<view class="u-circle-progress__left">
|
||||||
|
<view
|
||||||
|
class="u-circle-progress__left__circle"
|
||||||
|
:style="[leftSyle]"
|
||||||
|
ref="left-circle"
|
||||||
|
>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="u-circle-progress__right"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-circle-progress__right__circle"
|
||||||
|
ref="right-circle"
|
||||||
|
:style="[rightSyle]"
|
||||||
|
>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="u-circle-progress__circle">
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const animation = uni.requireNativePlugin('animation')
|
||||||
|
// #endif
|
||||||
|
/**
|
||||||
|
* CircleProgress 圆形进度条 TODO: 待完善
|
||||||
|
* @description 展示操作或任务的当前进度,比如上传文件,是一个圆形的进度环。
|
||||||
|
* @tutorial https://www.uviewui.com/components/circleProgress.html
|
||||||
|
* @property {String | Number} percentage 圆环进度百分比值,为数值类型,0-100 (默认 30 )
|
||||||
|
* @example
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-circle-progress',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
leftBorderColor: 'rgb(200, 200, 200)',
|
||||||
|
rightBorderColor: 'rgb(200, 200, 200)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
leftSyle() {
|
||||||
|
const style = {}
|
||||||
|
style.borderTopColor = this.leftBorderColor
|
||||||
|
style.borderRightColor = this.leftBorderColor
|
||||||
|
return style
|
||||||
|
},
|
||||||
|
rightSyle() {
|
||||||
|
const style = {}
|
||||||
|
style.borderLeftColor = this.rightBorderColor
|
||||||
|
style.borderBottomColor = this.rightBorderColor
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
uni.$u.sleep().then(() => {
|
||||||
|
this.rightBorderColor = 'rgb(66, 185, 131)'
|
||||||
|
// this.init()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
animation.transition(this.$refs['right-circle'].ref, {
|
||||||
|
styles: {
|
||||||
|
transform: 'rotate(45deg)',
|
||||||
|
transformOrigin: 'center center'
|
||||||
|
},
|
||||||
|
}, () => {
|
||||||
|
this.rightBorderColor = 'rgb(66, 185, 131)'
|
||||||
|
// animation.transition(this.$refs['right-circle'].ref, {
|
||||||
|
// styles: {
|
||||||
|
// transform: 'rotate(225deg)',
|
||||||
|
// transformOrigin: 'center center'
|
||||||
|
// },
|
||||||
|
// duration: 3000,
|
||||||
|
// }, () => {
|
||||||
|
// animation.transition(this.$refs['left-circle'].ref, {
|
||||||
|
// styles: {
|
||||||
|
// transform: 'rotate(45deg)',
|
||||||
|
// transformOrigin: 'center center'
|
||||||
|
// },
|
||||||
|
// }, () => {
|
||||||
|
// this.leftBorderColor = 'rgb(66, 185, 131)'
|
||||||
|
// animation.transition(this.$refs['left-circle'].ref, {
|
||||||
|
// styles: {
|
||||||
|
// transform: 'rotate(225deg)',
|
||||||
|
// transformOrigin: 'center center'
|
||||||
|
// },
|
||||||
|
// duration: 1500,
|
||||||
|
// }, () => {
|
||||||
|
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-circle-progress {
|
||||||
|
@include flex(row);
|
||||||
|
position: relative;
|
||||||
|
border-radius: 100px;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
// transform: rotate(0deg);
|
||||||
|
// background-color: rgb(66, 185, 131);
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
overflow: hidden;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&__circle {
|
||||||
|
border-radius: 100px;
|
||||||
|
height: 90px;
|
||||||
|
width: 90px;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 50px;
|
||||||
|
height: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
// background-color: rgb(66, 185, 131);
|
||||||
|
// background-color: rgb(200, 200, 200);
|
||||||
|
// transform-origin: left center;
|
||||||
|
|
||||||
|
&__circle {
|
||||||
|
box-sizing: border-box;
|
||||||
|
// background-color: red;
|
||||||
|
border-left-color: transparent;
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
border-top-left-radius: 50px;
|
||||||
|
border-top-right-radius: 50px;
|
||||||
|
border-bottom-right-radius: 50px;
|
||||||
|
// border-left-color: rgb(66, 185, 131);
|
||||||
|
// border-bottom-color: rgb(66, 185, 131);
|
||||||
|
border-top-color: rgb(66, 185, 131);
|
||||||
|
border-right-color: rgb(66, 185, 131);
|
||||||
|
border-width: 5px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
transform: rotate(225deg);
|
||||||
|
// border-radius: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__right {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
width: 50px;
|
||||||
|
height: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__circle {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
// background-color: red;
|
||||||
|
border-top-color: transparent;
|
||||||
|
border-right-color: transparent;
|
||||||
|
border-top-left-radius: 50px;
|
||||||
|
border-bottom-left-radius: 50px;
|
||||||
|
border-bottom-right-radius: 50px;
|
||||||
|
// border-left-color: rgb(66, 185, 131);
|
||||||
|
// border-bottom-color: rgb(66, 185, 131);
|
||||||
|
border-left-color: rgb(200, 200, 200);
|
||||||
|
border-bottom-color: rgb(200, 200, 200);
|
||||||
|
border-width: 5px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
transform-origin: center center;
|
||||||
|
// border-radius: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
node_modules/uview-ui/components/u-code-input/props.js
generated
vendored
Normal file
74
node_modules/uview-ui/components/u-code-input/props.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 最大输入长度
|
||||||
|
maxlength: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.codeInput.maxlength
|
||||||
|
},
|
||||||
|
// 是否用圆点填充
|
||||||
|
dot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.dot
|
||||||
|
},
|
||||||
|
// 显示模式,box-盒子模式,line-底部横线模式
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.codeInput.mode
|
||||||
|
},
|
||||||
|
// 是否细边框
|
||||||
|
hairline: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.hairline
|
||||||
|
},
|
||||||
|
// 字符间的距离
|
||||||
|
space: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.codeInput.space
|
||||||
|
},
|
||||||
|
// 预置值
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.codeInput.value
|
||||||
|
},
|
||||||
|
// 是否自动获取焦点
|
||||||
|
focus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.focus
|
||||||
|
},
|
||||||
|
// 字体是否加粗
|
||||||
|
bold: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.bold
|
||||||
|
},
|
||||||
|
// 字体颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.codeInput.color
|
||||||
|
},
|
||||||
|
// 字体大小
|
||||||
|
fontSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.codeInput.fontSize
|
||||||
|
},
|
||||||
|
// 输入框的大小,宽等于高
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.codeInput.size
|
||||||
|
},
|
||||||
|
// 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
|
||||||
|
disabledKeyboard: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.disabledKeyboard
|
||||||
|
},
|
||||||
|
// 边框和线条颜色
|
||||||
|
borderColor: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.codeInput.borderColor
|
||||||
|
},
|
||||||
|
// 是否禁止输入"."符号
|
||||||
|
disabledDot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.codeInput.disabledDot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
251
node_modules/uview-ui/components/u-code-input/u-code-input.vue
generated
vendored
Normal file
251
node_modules/uview-ui/components/u-code-input/u-code-input.vue
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-code-input">
|
||||||
|
<view
|
||||||
|
class="u-code-input__item"
|
||||||
|
:style="[itemStyle(index)]"
|
||||||
|
v-for="(item, index) in codeLength"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-code-input__item__dot"
|
||||||
|
v-if="dot && codeArray.length > index"
|
||||||
|
></view>
|
||||||
|
<text
|
||||||
|
v-else
|
||||||
|
:style="{
|
||||||
|
fontSize: $u.addUnit(fontSize),
|
||||||
|
fontWeight: bold ? 'bold' : 'normal',
|
||||||
|
color: color
|
||||||
|
}"
|
||||||
|
>{{codeArray[index]}}</text>
|
||||||
|
<view
|
||||||
|
class="u-code-input__item__line"
|
||||||
|
v-if="mode === 'line'"
|
||||||
|
:style="[lineStyle]"
|
||||||
|
></view>
|
||||||
|
<!-- #ifndef APP-PLUS -->
|
||||||
|
<view v-if="isFocus && codeArray.length === index" :style="{backgroundColor: color}" class="u-code-input__item__cursor"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<input
|
||||||
|
:disabled="disabledKeyboard"
|
||||||
|
type="number"
|
||||||
|
:focus="focus"
|
||||||
|
:value="inputValue"
|
||||||
|
:maxlength="maxlength"
|
||||||
|
class="u-code-input__input"
|
||||||
|
@input="inputHandler"
|
||||||
|
:style="{
|
||||||
|
height: $u.addUnit(size)
|
||||||
|
}"
|
||||||
|
@focus="isFocus = true"
|
||||||
|
@blur="isFocus = false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* CodeInput 验证码输入
|
||||||
|
* @description 该组件一般用于验证用户短信验证码的场景,也可以结合uView的键盘组件使用
|
||||||
|
* @tutorial https://www.uviewui.com/components/codeInput.html
|
||||||
|
* @property {String | Number} maxlength 最大输入长度 (默认 6 )
|
||||||
|
* @property {Boolean} dot 是否用圆点填充 (默认 false )
|
||||||
|
* @property {String} mode 显示模式,box-盒子模式,line-底部横线模式 (默认 'box' )
|
||||||
|
* @property {Boolean} hairline 是否细边框 (默认 false )
|
||||||
|
* @property {String | Number} space 字符间的距离 (默认 10 )
|
||||||
|
* @property {String | Number} value 预置值
|
||||||
|
* @property {Boolean} focus 是否自动获取焦点 (默认 false )
|
||||||
|
* @property {Boolean} bold 字体和输入横线是否加粗 (默认 false )
|
||||||
|
* @property {String} color 字体颜色 (默认 '#606266' )
|
||||||
|
* @property {String | Number} fontSize 字体大小,单位px (默认 18 )
|
||||||
|
* @property {String | Number} size 输入框的大小,宽等于高 (默认 35 )
|
||||||
|
* @property {Boolean} disabledKeyboard 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true (默认 false )
|
||||||
|
* @property {String} borderColor 边框和线条颜色 (默认 '#c9cacc' )
|
||||||
|
* @property {Boolean} disabledDot 是否禁止输入"."符号 (默认 true )
|
||||||
|
*
|
||||||
|
* @event {Function} change 输入内容发生改变时触发,具体见上方说明 value:当前输入的值
|
||||||
|
* @event {Function} finish 输入字符个数达maxlength值时触发,见上方说明 value:当前输入的值
|
||||||
|
* @example <u-code-input v-model="value4" :focus="true"></u-code-input>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-code-input',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
inputValue: '',
|
||||||
|
isFocus: this.focus
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
// 转为字符串,超出部分截掉
|
||||||
|
this.inputValue = String(val).substring(0, this.maxlength)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
|
||||||
|
codeLength() {
|
||||||
|
return new Array(Number(this.maxlength))
|
||||||
|
},
|
||||||
|
// 循环item的样式
|
||||||
|
itemStyle() {
|
||||||
|
return index => {
|
||||||
|
const addUnit = uni.$u.addUnit
|
||||||
|
const style = {
|
||||||
|
width: addUnit(this.size),
|
||||||
|
height: addUnit(this.size)
|
||||||
|
}
|
||||||
|
// 盒子模式下,需要额外进行处理
|
||||||
|
if (this.mode === 'box') {
|
||||||
|
// 设置盒子的边框,如果是细边框,则设置为0.5px宽度
|
||||||
|
style.border = `${this.hairline ? 0.5 : 1}px solid ${this.borderColor}`
|
||||||
|
// 如果盒子间距为0的话
|
||||||
|
if (uni.$u.getPx(this.space) === 0) {
|
||||||
|
// 给第一和最后一个盒子设置圆角
|
||||||
|
if (index === 0) {
|
||||||
|
style.borderTopLeftRadius = '3px'
|
||||||
|
style.borderBottomLeftRadius = '3px'
|
||||||
|
}
|
||||||
|
if (index === this.codeLength.length - 1) {
|
||||||
|
style.borderTopRightRadius = '3px'
|
||||||
|
style.borderBottomRightRadius = '3px'
|
||||||
|
}
|
||||||
|
// 最后一个盒子的右边框需要保留
|
||||||
|
if (index !== this.codeLength.length - 1) {
|
||||||
|
style.borderRight = 'none'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index !== this.codeLength.length - 1) {
|
||||||
|
// 设置验证码字符之间的距离,通过margin-right设置,最后一个字符,无需右边框
|
||||||
|
style.marginRight = addUnit(this.space)
|
||||||
|
} else {
|
||||||
|
// 最后一个盒子的有边框需要保留
|
||||||
|
style.marginRight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 将输入的值,转为数组,给item历遍时,根据当前的索引显示数组的元素
|
||||||
|
codeArray() {
|
||||||
|
return String(this.inputValue).split('')
|
||||||
|
},
|
||||||
|
// 下划线模式下,横线的样式
|
||||||
|
lineStyle() {
|
||||||
|
const style = {}
|
||||||
|
style.height = this.hairline ? '2px' : '4px'
|
||||||
|
style.width = uni.$u.addUnit(this.size)
|
||||||
|
// 线条模式下,背景色即为边框颜色
|
||||||
|
style.backgroundColor = this.borderColor
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 监听输入框的值发生变化
|
||||||
|
inputHandler(e) {
|
||||||
|
const value = e.detail.value
|
||||||
|
this.inputValue = value
|
||||||
|
// 是否允许输入“.”符号
|
||||||
|
if(this.disabledDot) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.inputValue = value.replace('.', '')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 未达到maxlength之前,发送change事件,达到后发送finish事件
|
||||||
|
this.$emit('change', value)
|
||||||
|
// 修改通过v-model双向绑定的值
|
||||||
|
this.$emit('input', value)
|
||||||
|
// 达到用户指定输入长度时,发出完成事件
|
||||||
|
if (String(value).length >= Number(this.maxlength)) {
|
||||||
|
this.$emit('finish', value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
$u-code-input-cursor-width: 1px;
|
||||||
|
$u-code-input-cursor-height: 40%;
|
||||||
|
$u-code-input-cursor-animation-duration: 1s;
|
||||||
|
$u-code-input-cursor-animation-name: u-cursor-flicker;
|
||||||
|
|
||||||
|
.u-code-input {
|
||||||
|
@include flex;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
@include flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
color: $u-content-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: $u-content-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__line {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 100px;
|
||||||
|
width: 40px;
|
||||||
|
background-color: $u-content-color;
|
||||||
|
}
|
||||||
|
/* #ifndef APP-PLUS */
|
||||||
|
&__cursor {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
width: $u-code-input-cursor-width;
|
||||||
|
height: $u-code-input-cursor-height;
|
||||||
|
animation: $u-code-input-cursor-animation-duration u-cursor-flicker infinite;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
// 之所以需要input输入框,是因为有它才能唤起键盘
|
||||||
|
// 这里将它设置为两倍的屏幕宽度,再将左边的一半移出屏幕,为了不让用户看到输入的内容
|
||||||
|
position: absolute;
|
||||||
|
left: -750rpx;
|
||||||
|
width: 1500rpx;
|
||||||
|
top: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-PLUS */
|
||||||
|
@keyframes u-cursor-flicker {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
</style>
|
||||||
34
node_modules/uview-ui/components/u-code/props.js
generated
vendored
Normal file
34
node_modules/uview-ui/components/u-code/props.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 倒计时总秒数
|
||||||
|
seconds: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.code.seconds
|
||||||
|
},
|
||||||
|
// 尚未开始时提示
|
||||||
|
startText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.code.startText
|
||||||
|
},
|
||||||
|
// 正在倒计时中的提示
|
||||||
|
changeText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.code.changeText
|
||||||
|
},
|
||||||
|
// 倒计时结束时的提示
|
||||||
|
endText: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.code.endText
|
||||||
|
},
|
||||||
|
// 是否在H5刷新或各端返回再进入时继续倒计时
|
||||||
|
keepRunning: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.code.keepRunning
|
||||||
|
},
|
||||||
|
// 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
|
||||||
|
uniqueKey: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.code.uniqueKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
node_modules/uview-ui/components/u-code/u-code.vue
generated
vendored
Normal file
129
node_modules/uview-ui/components/u-code/u-code.vue
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-code">
|
||||||
|
<!-- 此组件功能由js完成,无需写html逻辑 -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* Code 验证码输入框
|
||||||
|
* @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件 不提供界面显示,只提供提示语,由用户将提示语嵌入到具体的场景
|
||||||
|
* @tutorial https://www.uviewui.com/components/code.html
|
||||||
|
* @property {String | Number} seconds 倒计时所需的秒数(默认 60 )
|
||||||
|
* @property {String} startText 开始前的提示语,见官网说明(默认 '获取验证码' )
|
||||||
|
* @property {String} changeText 倒计时期间的提示语,必须带有字母"x",见官网说明(默认 'X秒重新获取' )
|
||||||
|
* @property {String} endText 倒计结束的提示语,见官网说明(默认 '重新获取' )
|
||||||
|
* @property {Boolean} keepRunning 是否在H5刷新或各端返回再进入时继续倒计时( 默认false )
|
||||||
|
* @property {String} uniqueKey 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
|
||||||
|
*
|
||||||
|
* @event {Function} change 倒计时期间,每秒触发一次
|
||||||
|
* @event {Function} start 开始倒计时触发
|
||||||
|
* @event {Function} end 结束倒计时触发
|
||||||
|
* @example <u-code ref="uCode" @change="codeChange" seconds="20"></u-code>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-code",
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
secNum: this.seconds,
|
||||||
|
timer: null,
|
||||||
|
canGetCode: true, // 是否可以执行验证码操作
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.checkKeepRunning()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
seconds: {
|
||||||
|
immediate: true,
|
||||||
|
handler(n) {
|
||||||
|
this.secNum = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkKeepRunning() {
|
||||||
|
// 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
|
||||||
|
let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'))
|
||||||
|
if(!lastTimestamp) return this.changeEvent(this.startText)
|
||||||
|
// 当前秒的时间戳
|
||||||
|
let nowTimestamp = Math.floor((+ new Date()) / 1000)
|
||||||
|
// 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
|
||||||
|
if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
|
||||||
|
// 剩余尚未执行完的倒计秒数
|
||||||
|
this.secNum = lastTimestamp - nowTimestamp
|
||||||
|
// 清除本地保存的变量
|
||||||
|
uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp')
|
||||||
|
// 开始倒计时
|
||||||
|
this.start()
|
||||||
|
} else {
|
||||||
|
// 如果不存在需要继续上一次的倒计时,执行正常的逻辑
|
||||||
|
this.changeEvent(this.startText)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 开始倒计时
|
||||||
|
start() {
|
||||||
|
// 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
|
||||||
|
if(this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
this.$emit('start')
|
||||||
|
this.canGetCode = false
|
||||||
|
// 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
|
||||||
|
this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
|
||||||
|
this.setTimeToStorage()
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
if (--this.secNum) {
|
||||||
|
// 用当前倒计时的秒数替换提示字符串中的"x"字母
|
||||||
|
this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
|
||||||
|
} else {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
this.changeEvent(this.endText)
|
||||||
|
this.secNum = this.seconds
|
||||||
|
this.$emit('end')
|
||||||
|
this.canGetCode = true
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
// 重置,可以让用户再次获取验证码
|
||||||
|
reset() {
|
||||||
|
this.canGetCode = true
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.secNum = this.seconds
|
||||||
|
this.changeEvent(this.endText)
|
||||||
|
},
|
||||||
|
changeEvent(text) {
|
||||||
|
this.$emit('change', text)
|
||||||
|
},
|
||||||
|
// 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
|
||||||
|
setTimeToStorage() {
|
||||||
|
if(!this.keepRunning || !this.timer) return
|
||||||
|
// 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
|
||||||
|
// 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
|
||||||
|
if(this.secNum > 0 && this.secNum <= this.seconds) {
|
||||||
|
// 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
|
||||||
|
let nowTimestamp = Math.floor((+ new Date()) / 1000)
|
||||||
|
// 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
|
||||||
|
uni.setStorage({
|
||||||
|
key: this.uniqueKey + '_$uCountDownTimestamp',
|
||||||
|
data: nowTimestamp + Number(this.secNum)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
|
||||||
|
beforeDestroy() {
|
||||||
|
this.setTimeToStorage()
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
</style>
|
||||||
29
node_modules/uview-ui/components/u-col/props.js
generated
vendored
Normal file
29
node_modules/uview-ui/components/u-col/props.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 占父容器宽度的多少等分,总分为12份
|
||||||
|
span: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.col.span
|
||||||
|
},
|
||||||
|
// 指定栅格左侧的间隔数(总12栏)
|
||||||
|
offset: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.col.offset
|
||||||
|
},
|
||||||
|
// 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`)
|
||||||
|
justify: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.col.justify
|
||||||
|
},
|
||||||
|
// 垂直对齐方式,可选值为top、center、bottom、stretch
|
||||||
|
align: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.col.align
|
||||||
|
},
|
||||||
|
// 文字对齐方式
|
||||||
|
textAlign: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.col.textAlign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
162
node_modules/uview-ui/components/u-col/u-col.vue
generated
vendored
Normal file
162
node_modules/uview-ui/components/u-col/u-col.vue
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="u-col"
|
||||||
|
ref="u-col"
|
||||||
|
:class="[
|
||||||
|
'u-col-' + span
|
||||||
|
]"
|
||||||
|
:style="[colStyle]"
|
||||||
|
@tap="clickHandler"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
/**
|
||||||
|
* CodeInput 栅格系统的列
|
||||||
|
* @description 该组件一般用于Layout 布局 通过基础的 12 分栏,迅速简便地创建布局
|
||||||
|
* @tutorial https://www.uviewui.com/components/Layout.html
|
||||||
|
* @property {String | Number} span 栅格占据的列数,总12等份 (默认 12 )
|
||||||
|
* @property {String | Number} offset 分栏左边偏移,计算方式与span相同 (默认 0 )
|
||||||
|
* @property {String} justify 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`) (默认 'start' )
|
||||||
|
* @property {String} align 垂直对齐方式,可选值为top、center、bottom、stretch (默认 'stretch' )
|
||||||
|
* @property {String} textAlign 文字水平对齐方式 (默认 'left' )
|
||||||
|
* @property {Object} customStyle 定义需要用到的外部样式
|
||||||
|
* @event {Function} click col被点击,会阻止事件冒泡到row
|
||||||
|
* @example <u-col span="3" offset="3" > <view class="demo-layout bg-purple"></view> </u-col>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'u-col',
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
width: 0,
|
||||||
|
parentData: {
|
||||||
|
gutter: 0
|
||||||
|
},
|
||||||
|
gridNum: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
uJustify() {
|
||||||
|
if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify
|
||||||
|
else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify
|
||||||
|
else return this.justify
|
||||||
|
},
|
||||||
|
uAlignItem() {
|
||||||
|
if (this.align == 'top') return 'flex-start'
|
||||||
|
if (this.align == 'bottom') return 'flex-end'
|
||||||
|
else return this.align
|
||||||
|
},
|
||||||
|
colStyle() {
|
||||||
|
const style = {
|
||||||
|
// 这里写成"padding: 0 10px"的形式是因为nvue的需要
|
||||||
|
paddingLeft: uni.$u.addUnit(uni.$u.getPx(this.parentData.gutter)/2),
|
||||||
|
paddingRight: uni.$u.addUnit(uni.$u.getPx(this.parentData.gutter)/2),
|
||||||
|
alignItems: this.uAlignItem,
|
||||||
|
justifyContent: this.uJustify,
|
||||||
|
textAlign: this.textAlign,
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
// 在非nvue上,使用百分比形式
|
||||||
|
flex: `0 0 ${100 / this.gridNum * this.span}%`,
|
||||||
|
marginLeft: 100 / 12 * this.offset + '%',
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 在nvue上,由于无法使用百分比单位,这里需要获取父组件的宽度,再计算得出该有对应的百分比尺寸
|
||||||
|
width: uni.$u.addUnit(Math.floor(this.width / this.gridNum * Number(this.span))),
|
||||||
|
marginLeft: uni.$u.addUnit(Math.floor(this.width / this.gridNum * Number(this.offset))),
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async init() {
|
||||||
|
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
|
||||||
|
this.updateParentData()
|
||||||
|
this.width = await this.parent.getComponentWidth()
|
||||||
|
},
|
||||||
|
updateParentData() {
|
||||||
|
this.getParentData('u-row')
|
||||||
|
},
|
||||||
|
clickHandler(e) {
|
||||||
|
this.$emit('click');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-col {
|
||||||
|
padding: 0;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
box-sizing:border-box;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef MP */
|
||||||
|
display: block;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
// nvue下百分比无效
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.u-col-0 {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-1 {
|
||||||
|
width: calc(100%/12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-2 {
|
||||||
|
width: calc(100%/12 * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-3 {
|
||||||
|
width: calc(100%/12 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-4 {
|
||||||
|
width: calc(100%/12 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-5 {
|
||||||
|
width: calc(100%/12 * 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-6 {
|
||||||
|
width: calc(100%/12 * 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-7 {
|
||||||
|
width: calc(100%/12 * 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-8 {
|
||||||
|
width: calc(100%/12 * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-9 {
|
||||||
|
width: calc(100%/12 * 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-10 {
|
||||||
|
width: calc(100%/12 * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-11 {
|
||||||
|
width: calc(100%/12 * 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-col-12 {
|
||||||
|
width: calc(100%/12 * 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
59
node_modules/uview-ui/components/u-collapse-item/props.js
generated
vendored
Normal file
59
node_modules/uview-ui/components/u-collapse-item/props.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.collapseItem.title
|
||||||
|
},
|
||||||
|
// 标题右侧内容
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.collapseItem.value
|
||||||
|
},
|
||||||
|
// 标题下方的描述信息
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.collapseItem.label
|
||||||
|
},
|
||||||
|
// 是否禁用折叠面板
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.collapseItem.disabled
|
||||||
|
},
|
||||||
|
// 是否展示右侧箭头并开启点击反馈
|
||||||
|
isLink: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.collapseItem.isLink
|
||||||
|
},
|
||||||
|
// 是否开启点击反馈
|
||||||
|
clickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.collapseItem.clickable
|
||||||
|
},
|
||||||
|
// 是否显示内边框
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: uni.$u.props.collapseItem.border
|
||||||
|
},
|
||||||
|
// 标题的对齐方式
|
||||||
|
align: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.collapseItem.align
|
||||||
|
},
|
||||||
|
// 唯一标识符
|
||||||
|
name: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: uni.$u.props.collapseItem.name
|
||||||
|
},
|
||||||
|
// 标题左侧图片,可为绝对路径的图片或内置图标
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: uni.$u.props.collapseItem.icon
|
||||||
|
},
|
||||||
|
// 面板展开收起的过渡时间,单位ms
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: uni.$u.props.collapseItem.duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
225
node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue
generated
vendored
Normal file
225
node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-collapse-item">
|
||||||
|
<u-cell
|
||||||
|
:title="title"
|
||||||
|
:value="value"
|
||||||
|
:label="label"
|
||||||
|
:icon="icon"
|
||||||
|
:isLink="isLink"
|
||||||
|
:clickable="clickable"
|
||||||
|
:border="parentData.border && showBorder"
|
||||||
|
@click="clickHandler"
|
||||||
|
:arrowDirection="expanded ? 'up' : 'down'"
|
||||||
|
:disabled="disabled"
|
||||||
|
>
|
||||||
|
<!-- #ifndef MP-WEIXIN -->
|
||||||
|
<!-- 微信小程序不支持,因为微信中不支持 <slot name="title" slot="title" />的写法 -->
|
||||||
|
<template slot="title">
|
||||||
|
<slot name="title"></slot>
|
||||||
|
</template>
|
||||||
|
<template slot="icon">
|
||||||
|
<slot name="icon"></slot>
|
||||||
|
</template>
|
||||||
|
<template slot="value">
|
||||||
|
<slot name="value"></slot>
|
||||||
|
</template>
|
||||||
|
<template slot="right-icon">
|
||||||
|
<slot name="right-icon"></slot>
|
||||||
|
</template>
|
||||||
|
<!-- #endif -->
|
||||||
|
</u-cell>
|
||||||
|
<view
|
||||||
|
class="u-collapse-item__content"
|
||||||
|
:animation="animationData"
|
||||||
|
ref="animation"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="u-collapse-item__content__text content-class"
|
||||||
|
:id="elId"
|
||||||
|
:ref="elId"
|
||||||
|
><slot /></view>
|
||||||
|
</view>
|
||||||
|
<u-line v-if="parentData.border"></u-line>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import props from './props.js';
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const animation = uni.requireNativePlugin('animation')
|
||||||
|
const dom = uni.requireNativePlugin('dom')
|
||||||
|
// #endif
|
||||||
|
/**
|
||||||
|
* collapseItem 折叠面板Item
|
||||||
|
* @description 通过折叠面板收纳内容区域(搭配u-collapse使用)
|
||||||
|
* @tutorial https://www.uviewui.com/components/collapse.html
|
||||||
|
* @property {String} title 标题
|
||||||
|
* @property {String} value 标题右侧内容
|
||||||
|
* @property {String} label 标题下方的描述信息
|
||||||
|
* @property {Boolean} disbled 是否禁用折叠面板 ( 默认 false )
|
||||||
|
* @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 ( 默认 true )
|
||||||
|
* @property {Boolean} clickable 是否开启点击反馈 ( 默认 true )
|
||||||
|
* @property {Boolean} border 是否显示内边框 ( 默认 true )
|
||||||
|
* @property {String} align 标题的对齐方式 ( 默认 'left' )
|
||||||
|
* @property {String | Number} name 唯一标识符
|
||||||
|
* @property {String} icon 标题左侧图片,可为绝对路径的图片或内置图标
|
||||||
|
* @event {Function} change 某个item被打开或者收起时触发
|
||||||
|
* @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "u-collapse-item",
|
||||||
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
elId: uni.$u.guid(),
|
||||||
|
// uni.createAnimation的导出数据
|
||||||
|
animationData: {},
|
||||||
|
// 是否展开状态
|
||||||
|
expanded: false,
|
||||||
|
// 根据expanded确定是否显示border,为了控制展开时,cell的下划线更好的显示效果,进行一定时间的延时
|
||||||
|
showBorder: false,
|
||||||
|
// 是否动画中,如果是则不允许继续触发点击
|
||||||
|
animating: false,
|
||||||
|
// 父组件u-collapse的参数
|
||||||
|
parentData: {
|
||||||
|
accordion: false,
|
||||||
|
border: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
expanded(n) {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
// 这里根据expanded的值来进行一定的延时,是为了cell的下划线更好的显示效果
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.showBorder = n
|
||||||
|
}, n ? 10 : 290)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 异步获取内容,或者动态修改了内容时,需要重新初始化
|
||||||
|
init() {
|
||||||
|
// 初始化数据
|
||||||
|
this.updateParentData()
|
||||||
|
if (!this.parent) {
|
||||||
|
return uni.$u.error('u-collapse-item必须要搭配u-collapse组件使用')
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
value,
|
||||||
|
accordion,
|
||||||
|
children = []
|
||||||
|
} = this.parent
|
||||||
|
|
||||||
|
if (accordion) {
|
||||||
|
if (uni.$u.test.array(value)) {
|
||||||
|
return uni.$u.error('手风琴模式下,u-collapse组件的value参数不能为数组')
|
||||||
|
}
|
||||||
|
this.expanded = this.name == value
|
||||||
|
} else {
|
||||||
|
if (!uni.$u.test.array(value) && value !== null) {
|
||||||
|
return uni.$u.error('非手风琴模式下,u-collapse组件的value参数必须为数组')
|
||||||
|
}
|
||||||
|
this.expanded = (value || []).some(item => item == this.name)
|
||||||
|
}
|
||||||
|
// 设置组件的展开或收起状态
|
||||||
|
this.$nextTick(function() {
|
||||||
|
this.setContentAnimate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateParentData() {
|
||||||
|
// 此方法在mixin中
|
||||||
|
this.getParentData('u-collapse')
|
||||||
|
},
|
||||||
|
async setContentAnimate() {
|
||||||
|
// 每次面板打开或者收起时,都查询元素尺寸
|
||||||
|
// 好处是,父组件从服务端获取内容后,变更折叠面板后可以获得最新的高度
|
||||||
|
const rect = await this.queryRect()
|
||||||
|
const height = this.expanded ? rect.height : 0
|
||||||
|
this.animating = true
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const ref = this.$refs['animation'].ref
|
||||||
|
animation.transition(ref, {
|
||||||
|
styles: {
|
||||||
|
height: height + 'px'
|
||||||
|
},
|
||||||
|
duration: this.duration,
|
||||||
|
// 必须设置为true,否则会到面板收起或展开时,页面其他元素不会随之调整它们的布局
|
||||||
|
needLayout: true,
|
||||||
|
timingFunction: 'ease-in-out',
|
||||||
|
}, () => {
|
||||||
|
this.animating = false
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
const animation = uni.createAnimation({
|
||||||
|
timingFunction: 'ease-in-out',
|
||||||
|
});
|
||||||
|
animation
|
||||||
|
.height(height)
|
||||||
|
.step({
|
||||||
|
duration: this.duration,
|
||||||
|
})
|
||||||
|
.step()
|
||||||
|
// 导出动画数据给面板的animationData值
|
||||||
|
this.animationData = animation.export()
|
||||||
|
// 标识动画结束
|
||||||
|
uni.$u.sleep(this.duration).then(() => {
|
||||||
|
this.animating = false
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// 点击collapsehead头部
|
||||||
|
clickHandler() {
|
||||||
|
if (this.disabled && this.animating) return
|
||||||
|
// 设置本组件为相反的状态
|
||||||
|
this.parent && this.parent.onChange(this)
|
||||||
|
},
|
||||||
|
// 查询内容高度
|
||||||
|
queryRect() {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
// $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://www.uviewui.com/js/getRect.html
|
||||||
|
// 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.$uGetRect(`#${this.elId}`).then(size => {
|
||||||
|
resolve(size)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// nvue下,使用dom模块查询元素高度
|
||||||
|
// 返回一个promise,让调用此方法的主体能使用then回调
|
||||||
|
return new Promise(resolve => {
|
||||||
|
dom.getComponentRect(this.$refs[this.elId], res => {
|
||||||
|
resolve(res.size)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../libs/css/components.scss";
|
||||||
|
|
||||||
|
.u-collapse-item {
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
overflow: hidden;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
padding: 12px 15px;
|
||||||
|
color: $u-content-color;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user