Commit dc322a14 authored by 李苏's avatar 李苏 💬

徐工道路app初始化

parent 0409e501
Pipeline #181 failed with stages
/package-lock.json
node_modules/
.project unpackage/
.DS_Store
unpackage/
uni_modules
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/xgdlapp.iml" filepath="$PROJECT_DIR$/.idea/xgdlapp.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<script>
import Vue from 'vue'
import appUpdate from 'common/util/appUpdate.js'
import api from 'api/api.js'
export default {
onLaunch: function() {
// appUpdate()
uni.getSystemInfo({
success: function(e) {
// #ifdef APP-PLUS
// 检测升级
appUpdate()
// #endif
// #ifndef MP
Vue.prototype.StatusBar = e.statusBarHeight;
if (e.platform == 'android') {
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
Vue.prototype.CustomBar = e.statusBarHeight + 45;
};
// #endif
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
let custom = wx.getMenuButtonBoundingClientRect();
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
// #endif
// #ifdef MP-ALIPAY
Vue.prototype.StatusBar = e.statusBarHeight;
Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
// #endif
// #ifdef APP-PLUS
//Vue.prototype.$api.listenTranMsg()
// var info = plus.push.getClientInfo();
// /* 5+ push 消息推送 ps:使用:H5+的方式监听,实现推送*/
// plus.push.addEventListener("click", function(msg) {
// console.log("click:" + JSON.stringify(msg));
// console.log(msg.payload);
// console.log(JSON.stringify(msg));
// //这里可以写跳转业务代码
// }, false);
// // 监听在线消息事件
// plus.push.addEventListener("receive", function(msg) {
// // plus.ui.alert(2);
// //这里可以写跳转业务代码
// console.log("recevice:" + JSON.stringify(msg))
// }, false);
// #endif
//Vue.prototype.$api.initLogin()
}
})
Vue.prototype.ColorList = [{
title: '嫣红',
name: 'red',
color: '#e54d42'
},
{
title: '桔橙',
name: 'orange',
color: '#f37b1d'
},
{
title: '明黄',
name: 'yellow',
color: '#fbbd08'
},
{
title: '橄榄',
name: 'olive',
color: '#8dc63f'
},
{
title: '森绿',
name: 'green',
color: '#39b54a'
},
{
title: '天青',
name: 'cyan',
color: '#1cbbb4'
},
{
title: '海蓝',
name: 'blue',
color: '#0081ff'
},
{
title: '姹紫',
name: 'purple',
color: '#6739b6'
},
{
title: '木槿',
name: 'mauve',
color: '#9c26b0'
},
{
title: '桃粉',
name: 'pink',
color: '#e03997'
},
{
title: '棕褐',
name: 'brown',
color: '#a5673f'
},
{
title: '玄灰',
name: 'grey',
color: '#8799a3'
},
{
title: '草灰',
name: 'gray',
color: '#aaaaaa'
},
{
title: '墨黑',
name: 'black',
color: '#333333'
},
{
title: '雅白',
name: 'white',
color: '#ffffff'
},
]
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
@import "plugin/colorui/main.css";
@import "plugin/colorui/icon.css";
@import "plugin/colorui/animation.css";
.nav-list {
display: flex;
flex-wrap: wrap;
padding: 0px 40upx 0px;
justify-content: space-between;
}
.nav-li {
padding: 30upx;
border-radius: 12upx;
width: 45%;
margin: 0 2.5% 40upx;
background-image: url(https://cdn.nlark.com/yuque/0/2019/png/280374/1552996358352-assets/web-upload/cc3b1807-c684-4b83-8f80-80e5b8a6b975.png);
background-size: cover;
background-position: center;
position: relative;
z-index: 1;
}
.nav-li::after {
content: "";
position: absolute;
z-index: -1;
background-color: inherit;
width: 100%;
height: 100%;
left: 0;
bottom: -10%;
border-radius: 10upx;
opacity: 0.2;
transform: scale(0.9, 0.9);
}
.nav-li.cur {
color: #fff;
background: rgb(94, 185, 94);
box-shadow: 4upx 4upx 6upx rgba(94, 185, 94, 0.4);
}
.nav-title {
font-size: 32upx;
font-weight: 300;
}
.nav-title::first-letter {
font-size: 40upx;
margin-right: 4upx;
}
.nav-name {
font-size: 28upx;
text-transform: Capitalize;
margin-top: 20upx;
position: relative;
}
.nav-name::before {
content: "";
position: absolute;
display: block;
width: 40upx;
height: 6upx;
background: #fff;
bottom: 0;
right: 0;
opacity: 0.5;
}
.nav-name::after {
content: "";
position: absolute;
display: block;
width: 100upx;
height: 1px;
background: #fff;
bottom: 0;
right: 40upx;
opacity: 0.3;
}
.nav-name::first-letter {
font-weight: bold;
font-size: 36upx;
margin-right: 1px;
}
.nav-li text {
position: absolute;
right: 30upx;
top: 30upx;
font-size: 52upx;
width: 60upx;
height: 60upx;
text-align: center;
line-height: 60upx;
}
.text-light {
font-weight: 300;
}
@keyframes show {
0% {
transform: translateY(-50px);
}
60% {
transform: translateY(40upx);
}
100% {
transform: translateY(0px);
}
}
@-webkit-keyframes show {
0% {
transform: translateY(-50px);
}
60% {
transform: translateY(40upx);
}
100% {
transform: translateY(0px);
}
}
</style>
import { http } from '@/common/service/service.js'
import configService from '@/common/service/config.service.js';
const apiService = {
/**
* 登录
*/
login(params) {
return http.post('/login',params)
},
/**
* 手机号码登录
*/
phoneNoLogin(params) {
return http.post('/sys/phoneLogin',params);
},
/**
* 退出
*/
logout(params) {
return http.post('/sys/logout',params);
},
/*数据请求 */
postData(url,params){
return http.post(url,params);
},
/**
* 获取文件访问路径
* @param avatar
* @param subStr
* @returns {*}
*/
getFileAccessHttpUrl(avatar,subStr){
if(!subStr) subStr = 'http'
if(avatar && avatar.startsWith(subStr)){
return avatar;
}else{
return configService.staticDomainURL + "/" + avatar;
}
}
};
export default apiService;
/**
* Request 2.0.1
* @Class Request
* @description luch-request 2.0.1 http请求插件
* @Author lu-ch
* @Date 2020-05-01
* @Email webwork.s@qq.com
* http://ext.dcloud.net.cn/plugin?id=392
* hbuilderx:2.6.15
*/
import buildURL from '../helpers/buildURL'
import buildFullPath from './buildFullPath'
import { isBoolean } from '../utils'
export default class Request {
config = {
baseUrl: '',
header: {},
method: 'GET',
dataType: 'json',
// #ifndef MP-ALIPAY || APP-PLUS
responseType: 'text',
// #endif
custom: {},
// #ifdef MP-ALIPAY || MP-WEIXIN
timeout: 30000,
// #endif
// #ifdef APP-PLUS
sslVerify: true,
// #endif
// #ifdef H5
withCredentials: false
// #endif
}
/**
* @property {Function} request 请求拦截器
* @property {Function} response 响应拦截器
* @type {{request: Request.interceptor.request, response: Request.interceptor.response}}
*/
interceptor = {
/**
* @param {Request~requestCallback} cb - 请求之前拦截,接收一个函数(config, cancel)=> {return config}。第一个参数为全局config,第二个参数为函数,调用则取消本次请求。
*/
request: (cb) => {
if (cb) {
this.requestBeforeFun = cb
}
},
/**
* @param {Request~responseCallback} cb 响应拦截器,对响应数据做点什么
* @param {Request~responseErrCallback} ecb 响应拦截器,对响应错误做点什么
*/
response: (cb, ecb) => {
if (cb) {
this.requestComFun = cb
}
if (ecb) {
this.requestComFail = ecb
}
}
}
requestBeforeFun = (config) => {
return config
}
requestComFun = (response) => {
return response
}
requestComFail = (response) => {
return response
}
/**
* 自定义验证器,如果返回true 则进入响应拦截器的响应成功函数(resolve),否则进入响应拦截器的响应错误函数(reject)
* @param { Number } statusCode - 请求响应体statusCode(只读)
* @return { Boolean } 如果为true,则 resolve, 否则 reject
*/
validateStatus(statusCode) {
return statusCode === 200
}
/**
* @Function
* @param {Request~setConfigCallback} f - 设置全局默认配置
*/
setConfig(f) {
this.config = f(this.config)
}
/**
* @Function
* @param {Object} options - 请求配置项
* @prop {String} options.url - 请求路径
* @prop {Object} options.data - 请求参数
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
* @prop {Object} [options.header = config.header] - 请求header
* @prop {Object} [options.method = config.method] - 请求方法
* @returns {Promise<unknown>}
*/
async request(options = {}) {
return new Promise((resolve, reject) => {
options.baseUrl = this.config.baseUrl
options.dataType = options.dataType || this.config.dataType
// #ifndef MP-ALIPAY || APP-PLUS
options.responseType = options.responseType || this.config.responseType
// #endif
// #ifdef MP-ALIPAY || MP-WEIXIN
options.timeout = options.timeout || this.config.timeout
// #endif
// #ifdef H5
options.withCredentials = isBoolean(options.withCredentials) ? options.withCredentials : this.config.withCredentials
// #endif
options.url = options.url || ''
options.data = options.data || {}
options.params = options.params || {}
options.header = {...this.config.header, ...(options.header || {})}
options.method = options.method || this.config.method
options.custom = {...this.config.custom,...(options.custom || {})}
// #ifdef APP-PLUS
options.sslVerify = options.sslVerify === undefined ? this.config.sslVerify : options.sslVerify
// #endif
options.getTask = options.getTask || this.config.getTask
let next = true
const cancel = (t = 'handle cancel', config = options) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(options, cancel)}
const _config = {...handleRe}
if (!next) return
const requestTask = uni.request({
url: buildURL(buildFullPath(_config.baseUrl, _config.url), _config.params),
data: _config.data,
header: _config.header,
method: _config.method,
// #ifdef MP-ALIPAY || MP-WEIXIN
timeout: _config.timeout,
// #endif
dataType: _config.dataType,
// #ifndef MP-ALIPAY || APP-PLUS
responseType: _config.responseType,
// #endif
// #ifdef APP-PLUS
sslVerify: _config.sslVerify,
// #endif
// #ifdef H5
withCredentials: _config.withCredentials,
// #endif
complete: (response) => {
response.config = handleRe
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
})
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
get(url, options = {}) {
return this.request({
url,
method: 'GET',
...options
})
}
post(url, data, options = {}) {
return this.request({
url,
data,
method: 'POST',
...options
})
}
// #ifndef MP-ALIPAY
put(url, data, options = {}) {
return this.request({
url,
data,
method: 'PUT',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
delete(url, data, options = {}) {
return this.request({
url,
data,
method: 'DELETE',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN
connect(url, data, options = {}) {
return this.request({
url,
data,
method: 'CONNECT',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
head(url, data, options = {}) {
return this.request({
url,
data,
method: 'HEAD',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
options(url, data, options = {}) {
return this.request({
url,
data,
method: 'OPTIONS',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN
trace(url, data, options = {}) {
return this.request({
url,
data,
method: 'TRACE',
...options
})
}
// #endif
upload(url, {
// #ifdef APP-PLUS || H5
files,
// #endif
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
name,
// #ifdef H5
file,
// #endif
header = {},
formData = {},
custom = {},
params = {},
getTask
}) {
return new Promise((resolve, reject) => {
let next = true
const globalHeader = {...this.config.header}
delete globalHeader['content-type']
delete globalHeader['Content-Type']
const pubConfig = {
baseUrl: this.config.baseUrl,
url,
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
method: 'UPLOAD',
name,
header: {...globalHeader, ...header},
formData,
params,
custom: {...this.config.custom, ...custom},
getTask: getTask || this.config.getTask
}
// #ifdef APP-PLUS || H5
if (files) {
pubConfig.files = files
}
// #endif
// #ifdef H5
if (file) {
pubConfig.file = file
}
// #endif
const cancel = (t = 'handle cancel', config = pubConfig) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(pubConfig, cancel)}
const _config = {
url: buildURL(buildFullPath(handleRe.baseUrl, handleRe.url), handleRe.params),
// #ifdef MP-ALIPAY
fileType: handleRe.fileType,
// #endif
filePath: handleRe.filePath,
name: handleRe.name,
header: handleRe.header,
formData: handleRe.formData,
complete: (response) => {
response.config = handleRe
try {
// 对可能字符串不是json 的情况容错
if (typeof response.data === 'string') {
response.data = JSON.parse(response.data)
}
// eslint-disable-next-line no-empty
} catch (e) {
}
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
}
// #ifdef APP-PLUS || H5
if (handleRe.files) {
_config.files = handleRe.files
}
// #endif
// #ifdef H5
if (handleRe.file) {
_config.file = handleRe.file
}
// #endif
if (!next) return
const requestTask = uni.uploadFile(_config)
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
download(url, options = {}) {
return new Promise((resolve, reject) => {
let next = true
const pubConfig = {
baseUrl: this.config.baseUrl,
url,
method: 'DOWNLOAD',
header: {...this.config.header, ...(options.header || {})},
params: options.params || {},
custom: {...this.config.custom, ...(options.custom || {})},
getTask: options.getTask || this.config.getTask
}
const cancel = (t = 'handle cancel', config = pubConfig) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(pubConfig, cancel)}
if (!next) return
const requestTask = uni.downloadFile({
url: buildURL(buildFullPath(handleRe.baseUrl, handleRe.url), handleRe.params),
header: handleRe.header,
complete: (response) => {
response.config = handleRe
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
})
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
}
/**
* setConfig回调
* @return {Object} - 返回操作后的config
* @callback Request~setConfigCallback
* @param {Object} config - 全局默认config
*/
/**
* 请求拦截器回调
* @return {Object} - 返回操作后的config
* @callback Request~requestCallback
* @param {Object} config - 全局config
* @param {Function} [cancel] - 取消请求钩子,调用会取消本次请求
*/
/**
* 响应拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseCallback
* @param {Object} response - 请求结果 response
*/
/**
* 响应错误拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseErrCallback
* @param {Object} response - 请求结果 response
*/
'use strict'
import isAbsoluteURL from '../helpers/isAbsoluteURL'
import combineURLs from '../helpers/combineURLs'
/**
* Creates a new URL by combining the baseURL with the requestedURL,
* only when the requestedURL is not already an absolute URL.
* If the requestURL is absolute, this function returns the requestedURL untouched.
*
* @param {string} baseURL The base URL
* @param {string} requestedURL Absolute or relative URL to combine
* @returns {string} The combined full path
*/
export default function buildFullPath(baseURL, requestedURL) {
if (baseURL && !isAbsoluteURL(requestedURL)) {
return combineURLs(baseURL, requestedURL)
}
return requestedURL
}
'use strict'
import * as utils from './../utils'
function encode(val) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, '+').
replace(/%5B/gi, '[').
replace(/%5D/gi, ']')
}
/**
* Build a URL by appending params to the end
*
* @param {string} url The base of the url (e.g., http://www.google.com)
* @param {object} [params] The params to be appended
* @returns {string} The formatted url
*/
export default function buildURL(url, params) {
/*eslint no-param-reassign:0*/
if (!params) {
return url
}
var serializedParams
if (utils.isURLSearchParams(params)) {
serializedParams = params.toString()
} else {
var parts = []
utils.forEach(params, function serialize(val, key) {
if (val === null || typeof val === 'undefined') {
return
}
if (utils.isArray(val)) {
key = key + '[]'
} else {
val = [val]
}
utils.forEach(val, function parseValue(v) {
if (utils.isDate(v)) {
v = v.toISOString()
} else if (utils.isObject(v)) {
v = JSON.stringify(v)
}
parts.push(encode(key) + '=' + encode(v))
})
})
serializedParams = parts.join('&')
}
if (serializedParams) {
var hashmarkIndex = url.indexOf('#')
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex)
}
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
}
return url
}
'use strict'
/**
* Creates a new URL by combining the specified URLs
*
* @param {string} baseURL The base URL
* @param {string} relativeURL The relative URL
* @returns {string} The combined URL
*/
export default function combineURLs(baseURL, relativeURL) {
return relativeURL
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
: baseURL
}
'use strict'
/**
* Determines whether the specified URL is absolute
*
* @param {string} url The URL to test
* @returns {boolean} True if the specified URL is absolute, otherwise false
*/
export default function isAbsoluteURL(url) {
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
// by any combination of letters, digits, plus, period, or hyphen.
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
}
import Request from './core/Request'
export default Request
'use strict'
// utils is a library of generic helper functions non-specific to axios
var toString = Object.prototype.toString
/**
* Determine if a value is an Array
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an Array, otherwise false
*/
export function isArray (val) {
return toString.call(val) === '[object Array]'
}
/**
* Determine if a value is an Object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an Object, otherwise false
*/
export function isObject (val) {
return val !== null && typeof val === 'object'
}
/**
* Determine if a value is a Date
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a Date, otherwise false
*/
export function isDate (val) {
return toString.call(val) === '[object Date]'
}
/**
* Determine if a value is a URLSearchParams object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
*/
export function isURLSearchParams (val) {
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
}
/**
* Iterate over an Array or an Object invoking a function for each item.
*
* If `obj` is an Array callback will be called passing
* the value, index, and complete array for each item.
*
* If 'obj' is an Object callback will be called passing
* the value, key, and complete object for each property.
*
* @param {Object|Array} obj The object to iterate
* @param {Function} fn The callback to invoke for each item
*/
export function forEach (obj, fn) {
// Don't bother if no value provided
if (obj === null || typeof obj === 'undefined') {
return
}
// Force an array if not already something iterable
if (typeof obj !== 'object') {
/*eslint no-param-reassign:0*/
obj = [obj]
}
if (isArray(obj)) {
// Iterate over array values
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj)
}
} else {
// Iterate over object keys
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj)
}
}
}
}
/**
* 是否为boolean 值
* @param val
* @returns {boolean}
*/
export function isBoolean(val) {
return typeof val === 'boolean'
}
import modules from './modules'
import Vue from 'vue'
import Router from '@/plugin/uni-simple-router/index.js'
import {ACCESS_TOKEN} from '@/common/util/constants.js'
Vue.use(Router)
//初始化
const router = new Router({
encodeURI:true,
routes: [...modules]//路由表
});
const whiteList = ['/pages/login/login','/pages/login/fwqsz']
//全局路由前置守卫
router.beforeEach((to, from, next) => {
let token=uni.getStorageSync(ACCESS_TOKEN);
if(token){
next()
}else{
if (whiteList.indexOf(to.path) !== -1) {
next()
}else{
next({ path: '/pages/login/login'})
}
next()
}
})
// 全局路由后置守卫
router.afterEach((to, from) => {
console.log("afterEach");
})
export default router;
\ No newline at end of file
const files = require.context('.', false, /\.js$/)
const modules = []
files.keys().forEach(key => {
if (key === './index.js') return
const item = files(key).default
modules.push(...item)
})
export default modules
\ No newline at end of file
const routes = [
{
path: "/pages/login/login",
name: 'login',
meta: {
title: '登录',
},
},
{
path: "/pages/login/fwqsz",
name: 'fwqsz',
meta: {
title: '服务器设置',
},
},
{
//注意:path必须跟pages.json中的地址对应,最前面别忘了加'/'哦
path: '/pages/homepage/homepage',
name: 'homepage',
meta: {
title: '主页',
},
},
{
//注意:path必须跟pages.json中的地址对应,最前面别忘了加'/'哦
path: '/pages/index/index',
name: 'index',
meta: {
title: '首页',
},
},
{
path: '/pages/user/people',
name: 'people',
meta: {
title: '个人中心',
},
},
{
path: '/pages/user/userdetail',
name: 'userdetail',
meta: {
title: '个人详情',
},
},
{
path: '/pages/user/useredit',
name: 'useredit',
meta: {
title: '个人编辑',
},
},
{
path: '/pages/common/exit',
name: 'exit',
meta: {
title: '退出',
},
},
{
path: '/pages/common/success',
name: 'success',
meta: {
title: 'success',
},
},
{
path: '/pages/xzck/xzck',
name: 'xzck',
meta: {
title: '选择仓库',
},
},
/* 徐工道路入库 */
{
path: '/pages/dl_putin_storage/index',
name: 'putin_storage',
meta: {
title: '入库登记',
},
},
{
path: '/pages/dl_putin_storage/putin_register',
name: 'putin_register',
meta: {
title: '登记信息',
},
},
/* 出库 */
{
path: '/pages/dl_putout_storage/index',
name: 'putout_storage',
meta: {
title: '出库登记',
},
},
{
path: '/pages/dl_putout_storage/putin_register',
name: 'putout_register',
meta: {
title: '登记信息',
},
},
/* 工位叫料 */
{
path: '/pages/dl_cmaterial/index',
name: 'cmaterial',
meta: {
title: '工位叫料',
},
},
{
path: '/pages/dl_cmaterial/xzwl',
name: 'xzwl',
meta: {
title: '选择物料',
},
},
/* 调整 */
{
path: '/pages/dl_tray_adjust/index',
name: 'trayAdjust',
meta: {
title: '托盘调整',
},
},
{
path: '/pages/dl_tray_clear/index',
name: 'trayClear',
meta: {
title: '托盘清空',
},
},
]
export default routes
\ No newline at end of file
let BASE_URL = ''
if (process.env.NODE_ENV == 'development') {
BASE_URL = 'http://192.168.30.57:9080' // 开发环境
} else {
BASE_URL = 'http://192.168.30.57:9080'// 生产环境
}
let staticDomainURL = BASE_URL+ '/sys/common/static';
const configService = {
apiUrl: BASE_URL,
staticDomainURL: staticDomainURL
};
export default configService
\ No newline at end of file
import Request from '@/common/luch-request/index.js'
import {ACCESS_TOKEN} from '@/common/util/constants.js'
import configService from './config.service.js'
import tip from '@/common/util/tip.js';
import store from '@/store/index.js';
let apiUrl = configService.apiUrl;
const getTokenStorage = () => {
let token = ''
try{
token = uni.getStorageSync(ACCESS_TOKEN)
}catch(e){
//TODO handle the exception
console.log("getTokenStorage",token)
}
return token
}
const http = new Request()
http.setConfig((config) => { /* 设置全局配置 */
config.baseUrl = apiUrl /* 根域名不同 */
config.header = {
...config.header
}
return config
})
/**
* 自定义验证器,如果返回true 则进入响应拦截器的响应成功函数(resolve),否则进入响应拦截器的响应错误函数(reject)
* @param { Number } statusCode - 请求响应体statusCode(只读)
* @return { Boolean } 如果为true,则 resolve, 否则 reject
*/
// 有默认,非必写
http.validateStatus = (statusCode) => {
return statusCode === 200
}
http.interceptor.request((config, cancel) => { /* 请求之前拦截器 */
// tip.alert(config.baseUrl)
uni.getStorageInfo({
success: function (res) {
if(uni.getStorageSync('storage_key')){
config.baseUrl=uni.getStorageSync('storage_key');
}
}
})
config.header = {
...config.header,
'X-Access-Token':getTokenStorage()
}
/*
if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行
cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在'
}
*/
return config
})
// 必须使用异步函数,注意
http.interceptor.response(async (response) => { /* 请求之后拦截器 */
// if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
// return Promise.reject(response)
// }
return response
}, (response) => {
// 请求错误做点什么
tip.alert("网络请求异常,请检查网络")
// this.$tip.alert("网络请求异常,请检查网络");
console.log("请求错误做点什么",response);
if (response) {
let data = response.data
const token = uni.getStorageSync(ACCESS_TOKEN)
console.log("------异常响应------",token)
console.log("------异常响应------",data.status)
switch (data.status) {
case 403:
tip.error('拒绝访问');
break
case 500:
if(!token || data.message=="Token失效,请重新登录"){
let timeout=setTimeout(tip.alert('登录已过期'), 1000);
store.dispatch('Logout').then(() => {
clearTimeout(timeout)
window.location.reload()
})
}
break
case 404:
break
case 504:
break
case 401:
if (token) {
/* store.dispatch('Logout').then(() => {
setTimeout(() => {
window.location.reload()
}, 1500)
}) */
}
break
default:
tip.error({
duration: 0,
forbidClick: true,
message: data.message
});
break
}
}
return response
})
export {
http
}
let cacheMap = new Map()
let timeoutDefault = 1200
function isTimeout (name) {
const data = cacheMap.get(name)
if (!data) return true
if (data.timeout === 0) return false
const currentTime = Date.now()
const overTime = (currentTime - data.createTime) / 1000
if (overTime > data.timeout) {
cacheMap.delete(name)
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
} catch (e) {
console.log(e)
}
}
return true
}
return false
}
class CacheCell {
constructor (data, timeout) {
this.data = data
this.timeout = timeout
this.createTime = Date.now()
}
}
class MinCache {
constructor (timeout) {
try {
const res = uni.getStorageInfoSync()
res.keys.forEach(name => {
try {
const value = uni.getStorageSync(name)
cacheMap.set(name, value)
} catch (e) {
console.log(e)
}
})
} catch (e) {
console.log(e)
}
timeoutDefault = timeout
}
set (name, data, timeout = timeoutDefault) {
const cachecell = new CacheCell(data, timeout)
let cache = null
if (name.startsWith('_')) {
try {
uni.setStorageSync(name, cachecell)
cache = cacheMap.set(name, cachecell)
} catch (e) {
console.log(e)
}
} else {
cache = cacheMap.set(name, cachecell)
}
return cache
}
get (name) {
return isTimeout(name) ? null : cacheMap.get(name).data
}
delete (name) {
let value = false
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
value = cacheMap.delete(name)
} catch (e) {
console.log(e)
}
} else {
value = cacheMap.delete(name)
}
return value
}
has (name) {
return !isTimeout(name)
}
clear () {
let value = false
try {
uni.clearStorageSync()
cacheMap.clear()
value = true
} catch (e) {
console.log(e)
}
return value
}
}
MinCache.install = function (Vue, {timeout = 1200} = {}) {
Vue.prototype.$cache = new MinCache(timeout)
}
export default MinCache
//APP更新
import api from 'api/api.js'
export default function appUpdate() {
/* let url="http://119.3.92.249:17007/app/download/datacenter.apk";
plus.runtime.openURL(url, function(ress) {
console.log(ress);
}); */
api.postData('/getAppVersion',{
/* version: plus.runtime.version,
imei: plus.device.imei, */
apptype:"0",
// appid: plus.runtime.appid,
appid:"__UNI__5BC4E2F"
}).then((res) => {
if(res){
plus.runtime.getProperty(plus.runtime.appid, function(wgtinfo) {
let client_version = wgtinfo.version;
var flag_update_v =Number(client_version.split(".")[0]);
var flag_update_v2=Number(res.data.version);
console.log(flag_update_v)
console.log("getAppVersion")
console.log(res)
console.log(flag_update_v2)
var flag_hot =false;
if (flag_update_v<flag_update_v2) {
// 提醒用户更新
uni.showModal({
title: '更新提示',
content: "请进行版本更新,当前版本-"+flag_update_v+",更新版本-"+flag_update_v2,
success: (showResult) => {
if (showResult.confirm) {
plus.nativeUI.toast("正在准备环境,请稍后! ");
uni.showModal({
content:res.data.url
})
plus.runtime.openURL(res.data.url, function(ress) {
console.log(ress);
});
/* var dtask = plus.downloader.createDownload(res.data.url, {
method: 'GET',
filename: '_doc/update/'
}, function(d, status) {
if (status == 200) {
var path = d.filename; //下载apk
plus.runtime.install(path); // 自动安装apk文件
} else {
plus.nativeUI.alert('版本更新失败:' + status);
}
}); */
dtask.start();
}
}
})
} else if (flag_hot) {
uni.downloadFile({
url: res.data.url,
success: (downloadResult) => {
console.log(downloadResult.tempFilePath)
if (downloadResult.statusCode === 200) {
plus.nativeUI.toast(`正在热更新!${res.data.versionCode}`);
plus.runtime.install(downloadResult.tempFilePath, {
force: false
}, function() {
plus.nativeUI.toast("热更新成功");
plus.runtime.restart();
}, function(e) {
console.log(e)
plus.nativeUI.toast(`热更新失败:${e.message}`);
});
}
}
});
}
});
}
}).catch((err) => {
}).finally(()=>{
})
}
export const ACCESS_TOKEN = 'Access-Token'
export const USER_NAME = 'login_username'
export const USER_INFO = 'login_user_info'
const STORAGE_OPTIONS = {
namespace: 'pro__', // key prefix
name: 'ls', // name variable Vue.[ls] or this.[$ls],
storage: 'local', // storage name session, local, memory
}
export default STORAGE_OPTIONS;
// 对Date的扩展,将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
Date.prototype.Format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
export function formatTimeToStr(times, pattern) {
var d = new Date(times).Format("yyyy-MM-dd hh:mm:ss");
if (pattern) {
d = new Date(times).Format(pattern);
}
return d.toLocaleString();
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
import Vue from 'vue'
var eventBus = new Vue({});
export default eventBus;
\ No newline at end of file
/**
* [js-md5]{@link https://github.com/emn178/js-md5}
*
* @namespace md5
* @version 0.7.3
* @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2014-2017
* @license MIT
*/
(function () {
'use strict';
var ERROR = 'input is invalid type';
var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {};
if (root.JS_MD5_NO_WINDOW) {
WINDOW = false;
}
var WEB_WORKER = !WINDOW && typeof self === 'object';
var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) {
root = global;
} else if (WEB_WORKER) {
root = self;
}
var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
var HEX_CHARS = '0123456789abcdef'.split('');
var EXTRA = [128, 32768, 8388608, -2147483648];
var SHIFT = [0, 8, 16, 24];
var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];
var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
var blocks = [], buffer8;
if (ARRAY_BUFFER) {
var buffer = new ArrayBuffer(68);
buffer8 = new Uint8Array(buffer);
blocks = new Uint32Array(buffer);
}
if (root.JS_MD5_NO_NODE_JS || !Array.isArray) {
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
}
if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
ArrayBuffer.isView = function (obj) {
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
};
}
/**
* @method hex
* @memberof md5
* @description Output hash as hex string
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {String} Hex string
* @example
* md5.hex('The quick brown fox jumps over the lazy dog');
* // equal to
* md5('The quick brown fox jumps over the lazy dog');
*/
/**
* @method digest
* @memberof md5
* @description Output hash as bytes array
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {Array} Bytes array
* @example
* md5.digest('The quick brown fox jumps over the lazy dog');
*/
/**
* @method array
* @memberof md5
* @description Output hash as bytes array
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {Array} Bytes array
* @example
* md5.array('The quick brown fox jumps over the lazy dog');
*/
/**
* @method arrayBuffer
* @memberof md5
* @description Output hash as ArrayBuffer
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {ArrayBuffer} ArrayBuffer
* @example
* md5.arrayBuffer('The quick brown fox jumps over the lazy dog');
*/
/**
* @method buffer
* @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
* @memberof md5
* @description Output hash as ArrayBuffer
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {ArrayBuffer} ArrayBuffer
* @example
* md5.buffer('The quick brown fox jumps over the lazy dog');
*/
/**
* @method base64
* @memberof md5
* @description Output hash as base64 string
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {String} base64 string
* @example
* md5.base64('The quick brown fox jumps over the lazy dog');
*/
var createOutputMethod = function (outputType) {
return function (message) {
return new Md5(true).update(message)[outputType]();
};
};
/**
* @method create
* @memberof md5
* @description Create Md5 object
* @returns {Md5} Md5 object.
* @example
* var hash = md5.create();
*/
/**
* @method update
* @memberof md5
* @description Create and update Md5 object
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {Md5} Md5 object.
* @example
* var hash = md5.update('The quick brown fox jumps over the lazy dog');
* // equal to
* var hash = md5.create();
* hash.update('The quick brown fox jumps over the lazy dog');
*/
var createMethod = function () {
var method = createOutputMethod('hex');
if (NODE_JS) {
method = nodeWrap(method);
}
method.create = function () {
return new Md5();
};
method.update = function (message) {
return method.create().update(message);
};
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
var type = OUTPUT_TYPES[i];
method[type] = createOutputMethod(type);
}
return method;
};
var nodeWrap = function (method) {
var crypto = eval("require('crypto')");
var Buffer = eval("require('buffer').Buffer");
var nodeMethod = function (message) {
if (typeof message === 'string') {
return crypto.createHash('md5').update(message, 'utf8').digest('hex');
} else {
if (message === null || message === undefined) {
throw ERROR;
} else if (message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
}
}
if (Array.isArray(message) || ArrayBuffer.isView(message) ||
message.constructor === Buffer) {
return crypto.createHash('md5').update(new Buffer(message)).digest('hex');
} else {
return method(message);
}
};
return nodeMethod;
};
/**
* Md5 class
* @class Md5
* @description This is internal class.
* @see {@link md5.create}
*/
function Md5(sharedMemory) {
if (sharedMemory) {
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
this.blocks = blocks;
this.buffer8 = buffer8;
} else {
if (ARRAY_BUFFER) {
var buffer = new ArrayBuffer(68);
this.buffer8 = new Uint8Array(buffer);
this.blocks = new Uint32Array(buffer);
} else {
this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
}
this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0;
this.finalized = this.hashed = false;
this.first = true;
}
/**
* @method update
* @memberof Md5
* @instance
* @description Update hash
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {Md5} Md5 object.
* @see {@link md5.update}
*/
Md5.prototype.update = function (message) {
if (this.finalized) {
return;
}
var notString, type = typeof message;
if (type !== 'string') {
if (type === 'object') {
if (message === null) {
throw ERROR;
} else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
} else if (!Array.isArray(message)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
throw ERROR;
}
}
} else {
throw ERROR;
}
notString = true;
}
var code, index = 0, i, length = message.length, blocks = this.blocks;
var buffer8 = this.buffer8;
while (index < length) {
if (this.hashed) {
this.hashed = false;
blocks[0] = blocks[16];
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
}
if (notString) {
if (ARRAY_BUFFER) {
for (i = this.start; index < length && i < 64; ++index) {
buffer8[i++] = message[index];
}
} else {
for (i = this.start; index < length && i < 64; ++index) {
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
}
}
} else {
if (ARRAY_BUFFER) {
for (i = this.start; index < length && i < 64; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
buffer8[i++] = code;
} else if (code < 0x800) {
buffer8[i++] = 0xc0 | (code >> 6);
buffer8[i++] = 0x80 | (code & 0x3f);
} else if (code < 0xd800 || code >= 0xe000) {
buffer8[i++] = 0xe0 | (code >> 12);
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
buffer8[i++] = 0x80 | (code & 0x3f);
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
buffer8[i++] = 0xf0 | (code >> 18);
buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
buffer8[i++] = 0x80 | (code & 0x3f);
}
}
} else {
for (i = this.start; index < length && i < 64; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
blocks[i >> 2] |= code << SHIFT[i++ & 3];
} else if (code < 0x800) {
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
}
}
}
}
this.lastByteIndex = i;
this.bytes += i - this.start;
if (i >= 64) {
this.start = i - 64;
this.hash();
this.hashed = true;
} else {
this.start = i;
}
}
if (this.bytes > 4294967295) {
this.hBytes += this.bytes / 4294967296 << 0;
this.bytes = this.bytes % 4294967296;
}
return this;
};
Md5.prototype.finalize = function () {
if (this.finalized) {
return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex;
blocks[i >> 2] |= EXTRA[i & 3];
if (i >= 56) {
if (!this.hashed) {
this.hash();
}
blocks[0] = blocks[16];
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
}
blocks[14] = this.bytes << 3;
blocks[15] = this.hBytes << 3 | this.bytes >>> 29;
this.hash();
};
Md5.prototype.hash = function () {
var a, b, c, d, bc, da, blocks = this.blocks;
if (this.first) {
a = blocks[0] - 680876937;
a = (a << 7 | a >>> 25) - 271733879 << 0;
d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;
d = (d << 12 | d >>> 20) + a << 0;
c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
c = (c << 17 | c >>> 15) + d << 0;
b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
b = (b << 22 | b >>> 10) + c << 0;
} else {
a = this.h0;
b = this.h1;
c = this.h2;
d = this.h3;
a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
a = (a << 7 | a >>> 25) + b << 0;
d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
d = (d << 12 | d >>> 20) + a << 0;
c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
c = (c << 17 | c >>> 15) + d << 0;
b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
b = (b << 22 | b >>> 10) + c << 0;
}
a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
a = (a << 7 | a >>> 25) + b << 0;
d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
d = (d << 12 | d >>> 20) + a << 0;
c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
c = (c << 17 | c >>> 15) + d << 0;
b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
b = (b << 22 | b >>> 10) + c << 0;
a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
a = (a << 7 | a >>> 25) + b << 0;
d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
d = (d << 12 | d >>> 20) + a << 0;
c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
c = (c << 17 | c >>> 15) + d << 0;
b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
b = (b << 22 | b >>> 10) + c << 0;
a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
a = (a << 7 | a >>> 25) + b << 0;
d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
d = (d << 12 | d >>> 20) + a << 0;
c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
c = (c << 17 | c >>> 15) + d << 0;
b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
b = (b << 22 | b >>> 10) + c << 0;
a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
a = (a << 5 | a >>> 27) + b << 0;
d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
d = (d << 9 | d >>> 23) + a << 0;
c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
c = (c << 14 | c >>> 18) + d << 0;
b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
b = (b << 20 | b >>> 12) + c << 0;
a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
a = (a << 5 | a >>> 27) + b << 0;
d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
d = (d << 9 | d >>> 23) + a << 0;
c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
c = (c << 14 | c >>> 18) + d << 0;
b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
b = (b << 20 | b >>> 12) + c << 0;
a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
a = (a << 5 | a >>> 27) + b << 0;
d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
d = (d << 9 | d >>> 23) + a << 0;
c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
c = (c << 14 | c >>> 18) + d << 0;
b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
b = (b << 20 | b >>> 12) + c << 0;
a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
a = (a << 5 | a >>> 27) + b << 0;
d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
d = (d << 9 | d >>> 23) + a << 0;
c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
c = (c << 14 | c >>> 18) + d << 0;
b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
b = (b << 20 | b >>> 12) + c << 0;
bc = b ^ c;
a += (bc ^ d) + blocks[5] - 378558;
a = (a << 4 | a >>> 28) + b << 0;
d += (bc ^ a) + blocks[8] - 2022574463;
d = (d << 11 | d >>> 21) + a << 0;
da = d ^ a;
c += (da ^ b) + blocks[11] + 1839030562;
c = (c << 16 | c >>> 16) + d << 0;
b += (da ^ c) + blocks[14] - 35309556;
b = (b << 23 | b >>> 9) + c << 0;
bc = b ^ c;
a += (bc ^ d) + blocks[1] - 1530992060;
a = (a << 4 | a >>> 28) + b << 0;
d += (bc ^ a) + blocks[4] + 1272893353;
d = (d << 11 | d >>> 21) + a << 0;
da = d ^ a;
c += (da ^ b) + blocks[7] - 155497632;
c = (c << 16 | c >>> 16) + d << 0;
b += (da ^ c) + blocks[10] - 1094730640;
b = (b << 23 | b >>> 9) + c << 0;
bc = b ^ c;
a += (bc ^ d) + blocks[13] + 681279174;
a = (a << 4 | a >>> 28) + b << 0;
d += (bc ^ a) + blocks[0] - 358537222;
d = (d << 11 | d >>> 21) + a << 0;
da = d ^ a;
c += (da ^ b) + blocks[3] - 722521979;
c = (c << 16 | c >>> 16) + d << 0;
b += (da ^ c) + blocks[6] + 76029189;
b = (b << 23 | b >>> 9) + c << 0;
bc = b ^ c;
a += (bc ^ d) + blocks[9] - 640364487;
a = (a << 4 | a >>> 28) + b << 0;
d += (bc ^ a) + blocks[12] - 421815835;
d = (d << 11 | d >>> 21) + a << 0;
da = d ^ a;
c += (da ^ b) + blocks[15] + 530742520;
c = (c << 16 | c >>> 16) + d << 0;
b += (da ^ c) + blocks[2] - 995338651;
b = (b << 23 | b >>> 9) + c << 0;
a += (c ^ (b | ~d)) + blocks[0] - 198630844;
a = (a << 6 | a >>> 26) + b << 0;
d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
d = (d << 10 | d >>> 22) + a << 0;
c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
c = (c << 15 | c >>> 17) + d << 0;
b += (d ^ (c | ~a)) + blocks[5] - 57434055;
b = (b << 21 | b >>> 11) + c << 0;
a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
a = (a << 6 | a >>> 26) + b << 0;
d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
d = (d << 10 | d >>> 22) + a << 0;
c += (a ^ (d | ~b)) + blocks[10] - 1051523;
c = (c << 15 | c >>> 17) + d << 0;
b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
b = (b << 21 | b >>> 11) + c << 0;
a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
a = (a << 6 | a >>> 26) + b << 0;
d += (b ^ (a | ~c)) + blocks[15] - 30611744;
d = (d << 10 | d >>> 22) + a << 0;
c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
c = (c << 15 | c >>> 17) + d << 0;
b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
b = (b << 21 | b >>> 11) + c << 0;
a += (c ^ (b | ~d)) + blocks[4] - 145523070;
a = (a << 6 | a >>> 26) + b << 0;
d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
d = (d << 10 | d >>> 22) + a << 0;
c += (a ^ (d | ~b)) + blocks[2] + 718787259;
c = (c << 15 | c >>> 17) + d << 0;
b += (d ^ (c | ~a)) + blocks[9] - 343485551;
b = (b << 21 | b >>> 11) + c << 0;
if (this.first) {
this.h0 = a + 1732584193 << 0;
this.h1 = b - 271733879 << 0;
this.h2 = c - 1732584194 << 0;
this.h3 = d + 271733878 << 0;
this.first = false;
} else {
this.h0 = this.h0 + a << 0;
this.h1 = this.h1 + b << 0;
this.h2 = this.h2 + c << 0;
this.h3 = this.h3 + d << 0;
}
};
/**
* @method hex
* @memberof Md5
* @instance
* @description Output hash as hex string
* @returns {String} Hex string
* @see {@link md5.hex}
* @example
* hash.hex();
*/
Md5.prototype.hex = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];
};
/**
* @method toString
* @memberof Md5
* @instance
* @description Output hash as hex string
* @returns {String} Hex string
* @see {@link md5.hex}
* @example
* hash.toString();
*/
Md5.prototype.toString = Md5.prototype.hex;
/**
* @method digest
* @memberof Md5
* @instance
* @description Output hash as bytes array
* @returns {Array} Bytes array
* @see {@link md5.digest}
* @example
* hash.digest();
*/
Md5.prototype.digest = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
return [
h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,
h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,
h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,
h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF
];
};
/**
* @method array
* @memberof Md5
* @instance
* @description Output hash as bytes array
* @returns {Array} Bytes array
* @see {@link md5.array}
* @example
* hash.array();
*/
Md5.prototype.array = Md5.prototype.digest;
/**
* @method arrayBuffer
* @memberof Md5
* @instance
* @description Output hash as ArrayBuffer
* @returns {ArrayBuffer} ArrayBuffer
* @see {@link md5.arrayBuffer}
* @example
* hash.arrayBuffer();
*/
Md5.prototype.arrayBuffer = function () {
this.finalize();
var buffer = new ArrayBuffer(16);
var blocks = new Uint32Array(buffer);
blocks[0] = this.h0;
blocks[1] = this.h1;
blocks[2] = this.h2;
blocks[3] = this.h3;
return buffer;
};
/**
* @method buffer
* @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
* @memberof Md5
* @instance
* @description Output hash as ArrayBuffer
* @returns {ArrayBuffer} ArrayBuffer
* @see {@link md5.buffer}
* @example
* hash.buffer();
*/
Md5.prototype.buffer = Md5.prototype.arrayBuffer;
/**
* @method base64
* @memberof Md5
* @instance
* @description Output hash as base64 string
* @returns {String} base64 string
* @see {@link md5.base64}
* @example
* hash.base64();
*/
Md5.prototype.base64 = function () {
var v1, v2, v3, base64Str = '', bytes = this.array();
for (var i = 0; i < 15;) {
v1 = bytes[i++];
v2 = bytes[i++];
v3 = bytes[i++];
base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +
BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +
BASE64_ENCODE_CHAR[v3 & 63];
}
v1 = bytes[i];
base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
BASE64_ENCODE_CHAR[(v1 << 4) & 63] +
'==';
return base64Str;
};
var exports = createMethod();
if (COMMON_JS) {
module.exports = exports;
} else {
/**
* @method md5
* @description Md5 hash function, export to global in browsers.
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
* @returns {String} md5 hashes
* @example
* md5(''); // d41d8cd98f00b204e9800998ecf8427e
* md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6
* md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0
*
* // It also supports UTF-8 encoding
* md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07
*
* // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
* md5([]); // d41d8cd98f00b204e9800998ecf8427e
* md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e
*/
root.md5 = exports;
if (AMD) {
define(function () {
return exports;
});
}
}
})();
/**
* 提示与加载工具类
*/
export default class Tips {
constructor() {
this.isLoading = false;
}
/**
* 弹出提示框
*/
static success(title, duration = 1000) {
setTimeout(() => {
uni.showToast({
title: title,
icon: "none",
mask: true,
duration: duration
});
}, 300);
if (duration > 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
});
}
}
/**
* 弹出确认窗口
*/
static confirm(text,showCancel, payload = {}, title = "提示") {
return new Promise((resolve, reject) => {
uni.showModal({
title: title,
content: text,
showCancel: showCancel,
success: res => {
if (res.confirm) {
resolve(payload);
} else if (res.cancel) {
reject(payload);
}
},
fail: res => {
reject(payload);
}
});
}).catch((e) => {});
}
static toast(title, onHide, icon = "none") {
setTimeout(() => {
uni.showToast({
title: title,
icon: icon,
mask: true,
duration:1000
});
}, 300);
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 警告框
*/
static alert(title) {
uni.showToast({
title: title,
icon:"none",
mask: true,
duration: 1500
});
}
/**
* 错误框
*/
static error(title, onHide) {
uni.showToast({
title: title,
// image: "../../static/error.png",
mask: true,
duration: 1500
});
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 弹出加载提示
*/
static loading(title = "加载中") {
if (Tips.isLoading) {
return;
}
Tips.isLoading = true;
uni.showLoading({
title: title,
mask: true
});
}
/**
* 加载完毕
*/
static loaded() {
if (Tips.isLoading) {
Tips.isLoading = false;
uni.hideLoading();
}
}
}
/**
* 静态变量,是否加载中
*/
Tips.isLoading = false;
import Vconsole from 'vconsole'
const vConsole = new Vconsole()
export default vConsole
\ No newline at end of file
/**
* 常用服务
* useful server
*/
export const us = {
data:[
]
}
/**
* other server 其他服务
*/
export const os = {
data:[
{
title:"检验送检",
icon:"/static/icon/sj.png",
useCount:1000,
page:"jyline"
},
{
title:"送空车",
icon:"/static/icon/car.png",
useCount:1000,
page:"carline"
},
{
title:"调整",
icon:"/static/icon/adjust.png",
useCount:1000,
page:"adjust"
},
]
}
\ No newline at end of file
<template>
<view class="uni-load-more" @click="onClick">
<!-- #ifdef APP-NVUE -->
<loading-indicator v-if="!webviewHide && status === 'loading' && showIcon" :style="{color: color,width:iconSize+'px',height:iconSize+'px'}" :animating="true" class="uni-load-more__img uni-load-more__img--nvue"></loading-indicator>
<!-- #endif -->
<!-- #ifdef H5 -->
<svg width="24" height="24" viewBox="25 25 50 50" v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
:style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--android-H5">
<circle cx="50" cy="50" r="20" fill="none" :style="{color:color}" :stroke-width="3"></circle>
</svg>
<!-- #endif -->
<!-- #ifndef APP-NVUE || H5 -->
<view v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
:style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--android-MP">
<view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
<view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
<view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
</view>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<view v-else-if="!webviewHide && status === 'loading' && showIcon" :style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--ios-H5">
<image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzlBMzU3OTlEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzlBMzU3OUFEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDOUEzNTc5N0Q5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDOUEzNTc5OEQ5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt+ALSwAAA6CSURBVHja1FsLkFZVHb98LM+F5bHL8khA1iSeiyQBCRM+YGqKUnnJTDLGI0BGZlKDIU2MMglUiDApEZvSsZnQtBRJtKwQNKQMFYeRDR10WOLd8ljYXdh+v8v5fR3Od+797t1dnOnO/Ofce77z+J//+b/P+ZqtXbs2sJ9MJhNUV1cHJ06cCJo3bx7EPc2aNcvpy7pWrVoF+/fvDyoqKoI2bdoE9fX1F7TjN8a+EXBn/fkfvw942Tf+wYMHg9mzZwfjxo0LDhw4EPa1x2MbFw/fOGfPng1qa2tzcCkILsLDydq2bRsunpOTMM7TD/W/tZDZhPdeKD+yGxHhdu3aBV27dg3OnDlzMVANMheLAO3btw8KCwuDmpoaX5OxbgUIMEq7K8IcPnw4KCsrC/r37x8cP378/4cAXAB3vqSkJMuiDhTkw+XcuXNhOWbMmKBly5YhUT8xArhyFvP0BfwRsAuwxJZJsm/nzp2DTp06he/OU+cZ64K6o0ePBkOHDg2GDx8e6gEbJ5Q/NHNuAJQ1hgBeHUDlR7nVTkY8rQAvAi4z34vR/mPs1FoRsaCgIJThI0eOBC1atEiFGGV+5MiRoS45efJkqFjJFXV1dQuA012m2WcwTw98fy6CqBdsaiIO4CScrGPHjvk4odhavPquRtFWXEC25VgkREKOCh/qDSq+vn37htzD/mZTOmOc5U7zKzBPEedygWshcDyWvs30igAbU+6oyMgJBCFhwQE0fccxN60Ay9iebbjoDh06hMowjQxT4fXq1SskArmHZpkArvixp/kWzHdMeArExSJEaiXIjjRjRJ4DaAGWpibLzXN3Fm1vA5teBgh3j1Rv3bp1YgKwPdmf2p9zcyNYYgPKMfY0T5f5nNYdw158nJ8QawW4CLKwiOBSEgO/hok2eBydR+3dYH+PLxA5J8Vv0KBBwenTp0P2JWAx6+yFEBfs8lMY+y0SWMBNI9E4ThKi58VKTg3FQZS1RQF1cz27eC0QHMu+3E0SkUowjhVt5VdaWhp07949ZHv2Qd1EjDXM2cla1M0nl3GxAs3J9yREzyTdFVKVFOaE9qRA8GM0WebRuo9JGZKA7Mv2SeS/Z8+eoQ9BArMfFrLGo6jvxbhHbJZnKX2Rzz1O7QhJJ9Cs2ZMaWIyq/zhdeqPNfIoHd58clIQD+JSXl4dKlyIAuBdVXZwFVWKspSSoxE++h8x4k3uCnEhE4I5KwRiFWGOU0QWKiCYLbdoRMRKAu2kQ9vkfLU6dOhX06NEjlH+yMRZSinnuyWnYosVcji8CEA/6Cg2JF+IIUBqnGKUTCNwtwBN4f89RiK1R96DEgO2o0NDmtEdvVFdVVYV+P3UAPUEs6GFwV3PHmXkD4vh74iDFJysVI/MlaQhwKeBNTLYX5VuA8T4/gZxA4MRGFxDB6R7OmYPfyykGRJbyie+XnGYnQIC/coH9+vULiYrxrkL9ZA9+0ykaHIfEpM7ge8TiJ2CsHYwyMfafAF1yCGBHYIbCVDjDjKt7BeB51D+LgQa6OkG7IDYEEtvQ7lnXLKLtLdLuJBpE4gPUXcW2+PkZwOex+4cGDhwYDBkyRL7/HFcEwUGPo/8uWRUpYnfxGHco8HkewLHLyYmAawAPuIFZxhOpDfJQ8gbUv41yORAptMWBNr6oqMhWird5+u+iHmBb2nhjDV7HWBNQTgK8y11l5NetWzc5ULscAtSj7nbNI0skhWeUZCc0W4nyH/jO4Vz0u1IeYhbk4AiwM6tjxIWByHsoZ9qcIBPJd/y+DwPfBESOmCa/QF3WiZHucLlEDpNxcNhmheEOPgdQNx6/VZFQzFZ5TN08AHXQt2Ii3EdyFuUsPtTcGPhW5iMiCNELvz+Gdn9huG4HUJaW/w3g0wxV0XaG7arG2WeKiUWYM4Y7GO5ezshTARbbWGw/DvXkpp/ivVvE0JVoMxN4rpGzJMhE5Pl+xlATsDIqikP9F9D2z3h9nOksEUFhK+qO4rcPkoalMQ/HqJLIyb3F3JdjrCcw1yZ8joyJLR5gCo54etlag7qIoeNh1N1BRYj3DTFJ0elotxPlVzkGuYAmL0VSJVGAJA41c4Z6A3BzTLfn0HYwYKEI6CUAMzZEWvLsIcQOo1AmmyyM72nHJCfYsogflGV6jEk9vyQZXSuq6w4c16NsGcGZbwOPr+H1RkOk2LEzjNepxQkihHSCQ4ynAYNRx2zMKV92CQMWqj8J0BRE8EShxRFN6YrfCRhC0x3r/Zm4IbQCcmJoV0kMamllccR6FjHqUC5F2R/wS2dcymOlfAKOS4KmzQb5cpNC2MC7JhVn5wjXoJ44rYhLh8n0eXOCorJxa7POjbSlCGVczr34/RsAmrcvo9s+wGp3tzVhntxiXiJ4nvEYb4FJkf0O8HocAePmLvCxnL0AORraVekJk6TYjDabRVXfRE2lCN1h6ZQRN1+InUbsCpKwoBZHh0dODN9JBCUffItXxEavTQkUtnfTVAplCWL3JISz29h4NjotnuSsQKJCk8dF+kJR6RARjrqFVmfPnj3ZbK8cIJ0msd6jgHPGtfVTQ8VLmlvh4mct9sobRmPic0DyDQQnx/NlfYUgyz59+oScsH379pAwXABD32nTpoUHIToESeI5mnbE/UqDdyLcafEBf2MCqgC7NwxIbMREJQ0g4D4sfJwnD+AmRrII05cfMWJE+L1169bQr+fip06dGp4oJ83lmYd5wj/EmMa4TaHivo4EeCguYZBnkB5g2aWA69OIEnUHOaGysjIYMGBAMGnSpODYsWPZwCpFmm4lNq+4gSLQA7jcX8DwtjEyRC8wjabnXEx9kfWnTJkSJkAo90xpJVV+FmcVNeYAF5zWngS4C4O91MBxmAv8blLEpbjI5sz9MTdAhcgkCT1RO8mZkAjfiYpTEvStAS53Uw1vAiUGgZ3GpuQEYvoiBqlIan7kSDHnTwJQFNiPu0+5VxCVYhcZIjNrdXUDdp+Eq5AZ3Gkg8QAyVZRZIk4Tl4QAbF9cXJxNYZMAtAokgs4BrNxEpCtteXg7DDTMDKYNSuQdKsnJBek7HxewvxaosWxLYXtw+cJp18217wql4aKCfBNoEu0O5VU+PhctJ0YeXD4C6JQpyrlpSLTojpGGGN5YwNziChdIZLk4lvLcFJ9jMX3QdiImY9bmGQU+TRUL5CHITTRlgF8D9ouD1MfmLoEPl5xokIumZ2cfgMpHt47IW9N64Hsh7wQYYjyIugWuF5fCqYncXRd5vPMWyizzvhi/32+nvG0dZc9vR6fZOu0md5e+uC408FvKSIOZwXlGvxPv95izA2Vtvg1xKFWARI+vMX66HUhpQQb643uW1bSjuTWyw2SBvDrBvjFic1eGGlz5esq3ko9uSIlBRqPuFcCv8F4WIcN12nVaBd0SaYwI6PDDImR11JkqgHcPmQssjxIn6bUshygDFJUTxPMpHk+jfjPgupgdnYV2R/g7xSjtpah8RJBewhwf0gGK6XI92u4wXFEU40afJ4DN4h5LcAd+40HI3JgJecuT0c062W0i2hQJUTcxan3/CMW1PF2K6bbA+Daz4xRs1D3Br1Cm0OihKCqizW78/nXAF/G5TXrEcVzaNMH6CyMswqsAHqDyDLEyou8lwOXnKF8DjI6KjV3KzMBiXkDH8ij/H214J5A596ekrZ3F0zXlWeL7+P5eUrNo3/QwC15uxthuzidy7DzKRwEDaAViiDgKbTbz7CJnzo0bN7pIfIiid8SuPwn25o3QCmpnyjlZkyxPP8EomCJzrGb7GJMx7tNsq4MT2xMUYaiErZOluTzKsnz3gwCeCZyVRZJfYplNEokEjwrPtxlxjeYAk+F1F74VAzPxQRNYYdtpOUvWs8J1sGhBJMNsb7igN8plJs1eSmLIhLKE4rvaCX27gOhLpLOsIzJ7qn/i+wZzcvSOZ23/du8TZjwV8zHIXoP4R3ifBxiFz1dcVpa3aPntPE+c6TmIWE9EtcMmAcPdWAhYhAXxcLOQi9L1WhD1Sc8p1d2oL7XGiRKp8F4A2i8K/nfI+y/gsTDJ/YC/8+AD5Uh04KHiGl+cIFPnBDDrPMjwRGkLXyxO4VGbfQWnDH2v0bVWE3C9QOXlepbgjEfIJQI6XDG3z5ahD9cw2pS78ipB85wyScNTvsVzlzzhL8/jRrnmVjfFJK/m3m4nj9vbgQTguT8XZTjsm672R5uJKEaQmBI/c58gyus8ZDagLpEVSJBIyHp4jn++xqPV71OgQgJYEWOtZ/haxRtKmWOBu8xdBLftWltsY84zE6WIEy/eIOWL+BaayMx+KHtL7EAkqdNDLiEXmEMUHniedtJqg9HmZtfvt26vNi0BdG3Ft3g8ZOf7PAu59TxtzivLNIekyi+wD1i8CuUiD9FXAa8C+/xS3JPmZnomyc7H+fb4/Se0bk41Fel621r4cgVxbq91V4jVqwB7HTe2M7jgB+QWHavZkDRPmZcASoZEmBx6i75bGjPcMdL4/VKGFAGWZkGzPG0XAbdL9A81G5LOmUnC9hHKJeO7dcUMjblSl12867ElFTtaGl20xvvLGPdVz/8TVuU7y0x1PG7vtNg24oz9Uo/Z412++VFWI7Fcog9tu9Lm6gvRmIPv9x1xmQAu6RDkXtbOtlGEmpgD5Nvnyc0dcv0EE6cfdi1HmhMf9wDF3k3gtRvEedhxjpgfqPb9PU9iEJHnyOUA7bQUXh6kq/D7l2iTjWv7XOD530BDr8jIrus+srXjt4MzumJMHuTsBa63YKE1+RR5lBjEikCCnWKWiHdzOgKO+nRIBAF88za/IFmJ3eMZov4CYxGBabcpGL8EYx+SeMXJeRwHNsV/h+vdxeuhEpN3ZyNY78Gm2fknJxVGhyjixPiQvVkNzT1elD9Py/aTAL64Hb9vcYmC9zfdXdT/C1LeGbg4rnBaAihDFJH12W5ulfNCNe/xTsP3bp8ikzJs5BF+5PNfAQYAPaseTdsEcaYAAAAASUVORK5CYII="
mode="widthFix"></image>
</view>
<!-- #endif -->
<text class="uni-load-more__text" :style="{color: color}">{{ status === 'more' ? contentText.contentdown : status === 'loading' ? contentText.contentrefresh : contentText.contentnomore }}</text>
</view>
</template>
<script>
const platform = uni.getSystemInfoSync().platform
/**
* LoadMore 加载更多
* @description 用于列表中,做滚动加载使用,展示 loading 的各种状态
* @tutorial https://ext.dcloud.net.cn/plugin?id=29
* @property {String} status = [more|loading|noMore] loading 的状态
* @value more loading前
* @value loading loading中
* @value noMore 没有更多了
* @property {Number} iconSize 指定图标大小
* @property {Boolean} iconSize = [true|false] 是否显示 loading 图标
* @property {String} iconType = [snow|circle|auto] 指定图标样式
* @value snow ios雪花加载样式
* @value circle 安卓唤醒加载样式
* @value auto 根据平台自动选择加载样式
* @property {String} color 图标和文字颜色
* @property {Object} contentText 各状态文字说明,值为:{contentdown: "上拉显示更多",contentrefresh: "正在加载...",contentnomore: "没有更多数据了"}
* @event {Function} clickLoadMore 点击加载更多时触发
*/
export default {
name: 'UniLoadMore',
props: {
status: {
// 上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
type: String,
default: 'more'
},
showIcon: {
type: Boolean,
default: true
},
iconType: {
type: String,
default: 'auto'
},
iconSize: {
type: Number,
default: 24
},
color: {
type: String,
default: '#777777'
},
contentText: {
type: Object,
default () {
return {
contentdown: '上拉显示更多',
contentrefresh: '正在加载...',
contentnomore: '我是有底线的...'
}
}
}
},
data() {
return {
webviewHide: false,
platform: platform
}
},
// #ifndef APP-NVUE
computed:{
iconSnowWidth(){
console.log((Math.floor(this.iconSize/24)||1)*2);
return (Math.floor(this.iconSize/24)||1)*2
}
},
// #endif
mounted() {
// #ifdef APP-PLUS
var pages = getCurrentPages();
var page = pages[pages.length - 1];
var currentWebview = page.$getAppWebview();
currentWebview.addEventListener('hide', () => {
this.webviewHide = true
})
currentWebview.addEventListener('show', () => {
this.webviewHide = false
})
// #endif
},
methods: {
onClick() {
this.$emit('clickLoadMore', {
detail: {
status: this.status,
}
})
}
}
}
</script>
<style lang="scss" scoped>
@import '@/uni.scss';
.uni-load-more {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
height: 40px;
align-items: center;
justify-content: center;
}
.uni-load-more__text {
font-size: 12px;
}
.uni-load-more__img {
width: 24px;
height: 24px;
margin-right: 8px;
}
.uni-load-more__img--nvue {
color: #666666;
}
.uni-load-more__img--android,
.uni-load-more__img--ios {
width: 24px;
height: 24px;
transform: rotate(0deg);
}
/* #ifndef APP-NVUE */
.uni-load-more__img--android {
animation: loading-ios 1s 0s linear infinite;
}
@keyframes loading-android {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.uni-load-more__img--ios-H5 {
position: relative;
animation: loading-ios-H5 1s 0s step-end infinite;
}
.uni-load-more__img--ios-H5>image {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
@keyframes loading-ios-H5 {
0% {
transform: rotate(0deg);
}
8% {
transform: rotate(30deg);
}
16% {
transform: rotate(60deg);
}
24% {
transform: rotate(90deg);
}
32% {
transform: rotate(120deg);
}
40% {
transform: rotate(150deg);
}
48% {
transform: rotate(180deg);
}
56% {
transform: rotate(210deg);
}
64% {
transform: rotate(240deg);
}
73% {
transform: rotate(270deg);
}
82% {
transform: rotate(300deg);
}
91% {
transform: rotate(330deg);
}
100% {
transform: rotate(360deg);
}
}
/* #endif */
/* #ifdef H5 */
.uni-load-more__img--android-H5 {
animation: loading-android-H5-rotate 2s linear infinite;
transform-origin: center center;
}
.uni-load-more__img--android-H5>circle {
display: inline-block;
animation: loading-android-H5-dash 1.5s ease-in-out infinite;
stroke: currentColor;
stroke-linecap: round;
}
@keyframes loading-android-H5-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes loading-android-H5-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120;
}
}
/* #endif */
/* #ifndef APP-NVUE || H5 */
.uni-load-more__img--android-MP {
position: relative;
width: 24px;
height: 24px;
transform: rotate(0deg);
animation: loading-ios 1s 0s ease infinite;
}
.uni-load-more__img--android-MP>view {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border-radius: 50%;
border: solid 2px transparent;
border-top: solid 2px #777777;
transform-origin: center;
}
.uni-load-more__img--android-MP>view:nth-child(1){
animation: loading-android-MP-1 1s 0s linear infinite;
}
.uni-load-more__img--android-MP>view:nth-child(2){
animation: loading-android-MP-2 1s 0s linear infinite;
}
.uni-load-more__img--android-MP>view:nth-child(3){
animation: loading-android-MP-3 1s 0s linear infinite;
}
@keyframes loading-android {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes loading-android-MP-1{
0%{
transform: rotate(0deg);
}
50%{
transform: rotate(90deg);
}
100%{
transform: rotate(360deg);
}
}
@keyframes loading-android-MP-2{
0%{
transform: rotate(0deg);
}
50%{
transform: rotate(180deg);
}
100%{
transform: rotate(360deg);
}
}
@keyframes loading-android-MP-3{
0%{
transform: rotate(0deg);
}
50%{
transform: rotate(270deg);
}
100%{
transform: rotate(360deg);
}
}
/* #endif */
</style>
import Vue from 'vue'
import App from './App'
import store from './store'
import MinCache from'./common/util/MinCache.js'
import tip from'./common/util/tip.js'
import configService from'./common/service/config.service.js'
import router from './common/router'
import {RouterMount} from './plugin/uni-simple-router/index.js'
// 注册缓存器
Vue.use(MinCache,{timeout: 6})
// store
Vue.prototype.$store=store;
// tip
Vue.prototype.$tip=tip;
// config
Vue.prototype.$config=configService;
// 全局去除空格
// 正则表达式去除字符串空格
Vue.prototype.$trim=function Trim(str)
{
return str.replace(/\s/g,"")
}
// request请求
import { http } from '@/common/service/service.js'
Vue.prototype.$http = http
import interfacepage from './pages/index/index.vue'
Vue.component('interfacepage',interfacepage)
import people from './pages/user/people.vue'
Vue.component('people',people)
import cuCustom from './plugin/colorui/components/cu-custom.vue'
Vue.component('cu-custom',cuCustom)
// import VConsole from '@/common/util/vconsole.min.js'
// var vConsole = new VConsole();
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
store,
MinCache,
...App
})
//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
// #ifdef H5
RouterMount(app,'#app');
// #endif
// #ifndef H5
app.$mount(); //为了兼容小程序及app端必须这样写才有效果
// #endif
{
"name" : "wcs",
"appid" : "__UNI__B0C55F0",
"description" : "徐工道路系统功能",
"versionName" : "1.0.0",
"versionCode" : 100,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {},
/* SDK配置 */
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"h5" : {
"template" : "template.h5.html",
"devServer" : {
"https" : false
},
"title" : "xgapp",
"router" : {
"base" : "./"
}
},
"vueVersion" : "2"
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path" : "pages/login/login",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/homepage/homepage",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": ""
}
}
,
{
"path": "pages/xzck/xzck",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/login/fwqsz",
"style": {
"navigationBarTitleText": ""
}
},
/* 道路入库 */
{
"path" : "pages/dl_putin_storage/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/dl_putin_storage/putin_register",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
/* 道路出库 */
{
"path" : "pages/dl_putout_storage/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/dl_putout_storage/putin_register",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
/* 工位叫料 */
{
"path" : "pages/dl_cmaterial/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/dl_cmaterial/xzwl",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
/* 调整 */
{
"path" : "pages/dl_tray_adjust/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/dl_tray_clear/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
"navigationBarBackgroundColor": "#0081ff",
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
}
<template>
<view class="bg-white">
<cu-custom bgColor="bg-gradual-blue" :isBack="true">
<block slot="backText">返回</block>
<block slot="content">工位叫料</block>
</cu-custom>
<view class="cu-bar bg-white solid-bottom">
<view class="action">
<text class="cuIcon-title text-orange "></text> 工位列表
</view>
</view>
<!-- 卡片 -->
<view class="home-content-h">
<scroll-view scroll-y="true">
<view class="cu-list grid " :class="['col-3']" style="">
<view class="cu-item " style="border: 0px solid #FFFFFF;" v-for="(item,index) in gwinfor" :key="index" @tap="selectedGw(index,item)" >
<view >
<view class="cu-card " >
<view class="cu-item " style="height: 125px;">
<view class="item padding text-center " :class="(item.status)|getColor(item.status)" style="">
<view class="text-lg r3-box">{{item.stationname}}</view>
<view class="margin-top-sm text-Abc" style="overflow: hidden;">{{item.name}}</view>
<view class="margin-top-sm text-Abc">{{(item.status)|getstatus(item.status)}}</view>
</view>
<view class="cu-item" v-show="index==gwSelcetdIndex">
<view class="cuIcon-roundcheckfill text-blue"></view>
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- <view class="cu-form-group" @click="status=='1'?nextTo():null"> -->
<view class="cu-form-group" @click="nextTo()">
<view class="title ">物料</view>
<input disabled="" v-model="wlinfor.wlcode">{{wlinfor.wlcode?'物料已添加':'点击选择物料'}}<text class="lg text-gray" :class="'cuIcon-' + 'right'"></text></input>
</view>
<view class="flex flex-wrap padding bg-grey white radio">
<view class="basis-lg margin-top-xs margin-bottom-xs radius">名称:<span>{{wlinfor.wlname}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius"><span></span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">规格:<span>{{wlinfor.wlgg}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">批号:<span>{{wlinfor.wlph}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">托盘号:<span>{{wlinfor.tpcode}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">数量:<span>{{wlinfor.ztsl}}</span></view>
</view>
<view class="cu-form-group justify-around" style="padding: 0;">
<view class="cu-form-group ">
<view class="title" style="padding: 0;">任务单号</view>
<input disabled="">{{rwdh}}</input>
</view>
<view class="cu-form-group" >
<view class="title " style="padding: 0;">任务状态</view>
<input disabled="">{{rwzt|getstate}}</input>
</view>
</view>
<view class="cu-form-group ">
<view class="title " style="padding: 0;">AGV任务单号</view>
<input disabled="" style="padding: 0;">{{agvrwdh}}</input>
</view>
<view class="cu-form-group ">
<view class="title " style="padding: 0;">AGV任务状态</view>
<input disabled="" style="padding: 0;">{{agvrwzt}}</input>
</view>
<view class="padding flex align-center bg-white justify-around" >
<button class="cu-btn bg-gradual-green wid22" @tap="cmbt()">叫料</button>
<button class="cu-btn bg-gradual-red wid22" @tap="cancelbt()" >取消</button>
<button class="cu-btn bg-gradual-orange wid22" @tap="lockingbt()">锁定</button>
</view>
<view class="padding flex align-center bg-white justify-around" >
<button class="cu-btn bg-gradual-red wid30" @tap="adjustbt()" >托盘调整</button>
<button class="cu-btn bg-gradual-orange wid30" @tap="clearbt()">托盘清空</button>
<button v-if="false" class="cu-btn bg-gradual-orange wid30" @tap="clearbt()">回库</button>
</view>
<view class="cu-modal" :class="modalName=='DialogModal1'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否叫料?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="apiqqjl()">确定</button>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='DialogModal2'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否清空?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="clearinfo()">确定</button>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='DialogModal3'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否取消叫料?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="apiqxjl()">确定</button>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='DialogModal4'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否继续操作?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="apisd()">确定</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
import eventBus from '@/common/util/eventBus.js'
export default {
data() {
return {
masterid:"",
agvrwdh:"",
agvrwzt:"",
rwdh:"",
rwzt:"",
interval_gwinfor:null,
gwinfor:[],
cxinfor:{id:"",
name:""},
wlinfor:{},
gwInterval:{status:0},
status:null,
modalName: null,
loadModal:false,
cxid:"",
cxmc:"产线",
formData:{
gwid:"",
rwdh:"",
rwzt:"",
},
urls:{
gwquery:"jcsj/gw/query"
},
newGwList:[
],
gwList: [
],
gwObj:{
zt:0
},
gwSelcetdIndex:0,
gridCol: 2,
gridBorder: false,
menuBorder: false,
menuArrow: false,
menuCard: false,
skin: false,
listTouchStart: 0,
listTouchDirection: null,
badge:0,
TabCur: 0,
}
},
filters: {
getstate:function(e){
let state={
"C":"完成",
"F":"确认",
"I":"初始"
}
return state[e]
},
getstatus:function(e){
let ztList = {
"1": "正常",
"2": "已占用",
"3": "锁定"
};
return ztList[e]
},
getColor:function(e){
let ztList = {
"1": "bg-green",
"2": "bg-red",
"3": "bg-orange"
};
return ztList[e]
},
formatTime: function(time) {
if(time!=null&&time!="")
{
var date = new Date(time);
return date.Format("MM-dd hh:mm")
}else{
return "";
}
},
ztTrans: function(a) {
const ztList = {
"1": "空闲",
"2": "已占用",
"3": "锁定"
};
return ztList[a]
},
},
methods: {
/* 按钮 */
cmbt(){
uni.showModal({
title: '提示',
content: '是否叫料',
cancelText: "否", // 取消按钮的文字
confirmText: "是", // 确认按钮的文字
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
cancelbt(){
uni.showModal({
title: '提示',
content: '是否取消',
cancelText: "否", // 取消按钮的文字
confirmText: "是", // 确认按钮的文字
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
lockingbt(){
uni.showModal({
title: '提示',
content: '是否锁定',
cancelText: "否", // 取消按钮的文字
confirmText: "是", // 确认按钮的文字
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
adjustbt(){
this.$Router.push({ path:'/pages/dl_tray_adjust/index', query:{
},
})
},
clearbt(){
uni.showModal({
title: '提示',
content: '是否清空托盘',
cancelText: "否", // 取消按钮的文字
confirmText: "是", // 确认按钮的文字
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
// 手动
apisd(){
if(this.agvrwdh==""){
this.hideModal()
this.$tip.alert("当前状态操作")
return false
}
let that=this
api.postData("agv/agvtask/doAgvComplete",{
"ckid":that.$ckid,
"taskCode":this.agvrwdh
}).then((resp) => {
if(resp.data.success){
that.$tip.alert("操作成功");
}else{
that.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
}).finally(()=>{
})
this.hideModal()
},
// 取消叫料
apiqxjl(){
let that=this
api.postData("xgwms/wollzy/delete",{
"ckid":that.$ckid,
"id":this.masterid
}).then((resp) => {
if(resp.data.success){
this.status=1
this.wlinfor={}
this.apigettaskinf()
// that.$tip.alert("取消叫料成功");
that.apiGetgwxx()
}else{
that.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
// let msg = "请求出现错误,请稍后再试"
// this.$tip.alert(msg);
}).finally(()=>{
})
this.hideModal()
}
,
// 清空小车api
apiqkxc(){
this.gwObj=this.gwinfor[this.gwSelcetdIndex];
let that=this
api.postData("jcsj/gw/free",{
"ckid":that.$ckid,
"id":this.gwObj.id,
}).then((resp) => {
if(resp.data.success){
that.$tip.alert("清空成功");
that.status=1
that.apigettaskinf()
that.apiGetgwxx()
}else{
that.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
// let msg = "请求出现错误,请稍后再试"
// this.$tip.alert(msg);
}).finally(()=>{
})
},
// 查询任务单号状态以及物料
apigettaskinf(){
api.postData("xgwms/gwcx/query",{
"ckid":this.$ckid,
"code":this.gwObj.code,
}).then((resp) => {
if(resp.data.success){
if(resp.data.data.records.sjrwmxes[0]){
this.masterid=resp.data.data.records.sjrw.id
this.wlinfor.wlname=resp.data.data.records.sjrwmxes[0].wlname||""
this.wlinfor.wlgg=resp.data.data.records.sjrwmxes[0].wlgg||""
this.wlinfor.ztsl=resp.data.data.records.sjrwmxes[0].ztsl||""
this.wlinfor.tpcode=resp.data.data.records.sjrwmxes[0].tpcode||""
this.wlinfor.wlph=resp.data.data.records.sjrwmxes[0].wlph||""
this.wlinfor.wlcode=resp.data.data.records.sjrwmxes[0].wlcode||""
this.rwdh=resp.data.data.records.sjrw.djid
this.rwzt=resp.data.data.records.sjrw.zt
this.agvrwdh=resp.data.data.records.agvtask.taskCode
this.agvrwzt=resp.data.data.records.agvtask.taskStatusString
}else{
this.wlinfor.wlname=""
this.wlinfor.wlgg=""
this.wlinfor.ztsl=""
this.wlinfor.tpcode=""
this.wlinfor.wlph=""
this.wlinfor.wlcode=""
this.rwdh=""
this.rwzt=""
this.agvrwdh=""
this.agvrwzt=""
}
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
// let msg = "请求出现错误,请稍后再试"
// this.$tip.alert(msg);
}).finally(()=>{
})
},
clearinfo(){
this.apiqkxc()
this.wlinfor={}
this.hideModal()
},
apiqqjl(){
if(!this.wlinfor.wlname){
this.hideModal()
this.$tip.alert("请先选择物料");
return false
}
this.gwObj=this.gwinfor[this.gwSelcetdIndex];
this.wlinfor.gwid=this.gwObj.id
// this.wlinfor.tpid=this.wlinfor.mid
this.wlinfor.code=this.wlinfor.tpcode
api.postData("xgwms/wollzy/genCkzy",{
"ckid":this.$ckid,
"data":this.wlinfor,
}).then((resp) => {
if(resp.data.success){
// this.rwdh=resp.data.data.records.djid
// this.rwzt=resp.data.data.records.zt
this.$tip.alert("叫料成功");
this.apigettaskinf()
this.apiGetgwxx()
this.status=3
this.apigettaskinf()
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
}).finally(()=>{
})
this.hideModal()
},
interval(){
// this.interval_gwinfor=setInterval(()=>{
// this.apiGetgwxx()
// },3000)
},
apiGetgwxx(){
let _self=this;
api.postData(_self.urls.gwquery,{
"ckid":_self.$ckid,
stationid:_self.cxinfor.id
}).then((resp) => {
if(resp.data.success){
_self.gwinfor=resp.data.data.records
this.gwObj=this.gwinfor[this.gwSelcetdIndex];
this.status=this.gwObj.status
if(this.status==1){
// this.wlinfor.wlname=""
// this.wlinfor.wlgg=""
// this.wlinfor.ztsl=""
// this.wlinfor.tpcode=""
// this.wlinfor.wlph=""
// this.wlinfor.wlcode=""
// this.rwdh=""
// this.rwzt=""
// this.agvrwdh=""
// this.agvrwzt=""
}
if(_self.status==null){
_self.gwObj=_self.gwinfor[_self.gwSelcetdIndex]
// _self.apigettaskinf()
_self.status=_self.gwinfor[0].status
}
if(_self.status==2||_self.status==3){
_self.apigettaskinf()
}
if(_self.gwObj.zt==0){
_self.gwObj=_self.gwinfor[0]
}
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
// let msg = "请求出现错误,请稍后再试"
// this.$tip.alert(msg);
}).finally(()=>{
})
},
gotoBackPage(){
this.$Router.replace('/pages/gwjl/gwxz')
},
// 选择物料跳转
nextTo(){
clearInterval(this.interval_gwinfor)
this.$Router.push({ path:'/pages/dl_cmaterial/xzwl', query:{
gwjlinfor:{
status:this.status,
gwSelcetdIndex:this.gwSelcetdIndex,
cxinfor:this.cxinfor
}
},
})
},
confirm2(){
this.modalName="DialogModal2"
},
confirm3(){
this.modalName="DialogModal3"
},
confirm4(){
this.modalName="DialogModal4"
},
// 叫料
confirm(e){
if(this.status=="1")
{
this.modalName="DialogModal"+e
}else{
this.$tip.alert("当前工位非空闲")
}
},
showModal(e) {
this.modalName = e.currentTarget.dataset.target
},
hideModal(e) {
this.modalName = null
},
Gridchange(e) {
this.gridCol = e.detail.value
},
Gridswitch(e) {
this.gridBorder = e.detail.value
},
MenuBorder(e) {
this.menuBorder = e.detail.value
},
MenuArrow(e) {
this.menuArrow = e.detail.value
},
MenuCard(e) {
this.menuCard = e.detail.value
},
selectedGw(e,item){
this.status=item.status
let _self=this;
this.$forceUpdate()
_self.gwSelcetdIndex=e;
_self.gwObj=_self.gwinfor[e];
console.log(this.gwObj.status)
_self.formData.gwid=_self.gwObj.id;
if(this.status!=1){
this.apigettaskinf()
}else if(
this.status==1
){
this.wlinfor.wlname=""
this.wlinfor.wlgg=""
this.wlinfor.ztsl=""
this.wlinfor.tpcode=""
this.wlinfor.wlph=""
this.wlinfor.wlcode=""
this.rwdh=""
this.rwzt=""
this.agvrwdh=""
this.agvrwzt=""
}
// _self.formData.rwdh=_self.gwObj.rwdh;
// _self.formData.rwzt=_self.gwObj.rwzt;
},
/* 查询工位 */
},
onLoad(e) {
eventBus.$on('addressInfo', function(data){
console.log(this.cxmc)
console.log(data,"data");
}.bind(this));
if(!e.query){
return
}
let einfor =JSON.parse(e.query)
if(einfor.xzwl)
{
this.interval()
this.status=einfor.gwjlinfor.status
this.wlinfor=einfor.wlinfor
this.wlinfor.ztsl=einfor.wlinfor.ztsl
this.wlinfor.tpcode=einfor.wlinfor.tpcode
this.wlinfor.tpid=einfor.wlinfor.tpid
console.log(this.wlinfor)
this.cxinfor=einfor.gwjlinfor.cxinfor
this.apiGetgwxx()
this.gwSelcetdIndex=einfor.gwjlinfor.gwSelcetdIndex
// this.gwObj=this.gwList[this.gwSelcetdIndex];
// console.log(this.gwObj)
}else{
this.cxinfor.id=einfor.id
this.cxinfor.name=einfor.name
this.apiGetgwxx()
this.interval()
// this.gwObj=this.gwList[this.gwSelcetdIndex];
// console.log(this.gwObj)
}
},
onUnload(){
clearInterval(this.interval_gwinfor)
},
onHide(){
}
}
</script>
<style scoped>
.cu-form-group{
min-height: 20px;
}
.cu-item{
padding: 0px!important;
}
.b-right{
position: relative;
}
.hide{
display: none;
}
.disable{
background-color: #F5F5F5
}
.wid30{
width: 30%;
}
.wid22{
width: 22%;
}
</style>
<template>
<view>
<view class="cu-bar bg-white search fixed" :style="[{top:70 + 'px'}]">
<view class="search-form round">
<text class="cuIcon-search"></text>
<input type="text" placeholder="输入搜索的信息" confirm-type="search" @confirm="searchFood" v-model="serachName"/>
</view>
<view class="action">
<button class="cu-btn bg-gradual-green shadow-blur round" @tap="searchFood">搜索</button>
</view>
</view>
<view class="bg-white">
<cu-custom bgColor="bg-gradual-blue" :isBack="true"><block slot="content">选择物料</block></cu-custom>
</view>
<view class="cu-bar bg-white solid-bottom">
<view class="action">
<text class="cuIcon-title text-orange "></text> 物料列表
</view>
</view>
<view class="bg-white " v-for="(item,index) in wlinfor" :key="index" @tap="nextTo(item)">
<view class="flex flex-wrap margin-bottom-xs padding bg-grey white radio">
<view class="wid50 margin-top-xs margin-bottom-xs radius">物料:<span>{{item.wlcode}} </span></view>
<view class="wid50 margin-top-xs margin-bottom-xs radius">名称:<span>{{item.wlname}}</span></view>
<view class="wid50 margin-top-xs margin-bottom-xs radius">规格:<span>{{item.wlgg}}</span></view>
<view class="wid50 margin-top-xs margin-bottom-xs radius">托盘号:<span>{{item.tpcode}}</span></view>
<view class="wid50 margin-top-xs margin-bottom-xs radius">批号:<span>{{item.wlph}}</span></view>
<view class="wid50 margin-top-xs margin-bottom-xs radius">剩余数量:<span>{{item.ztsl}}</span></view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
import eventBus from '@/common/util/eventBus.js'
export default {
data() {
return {
serachName:"",
status:"",
gwjlinfor:{},
wlinfor:[
]
}
},
onPullDownRefresh(){
setTimeout(()=>{
uni.stopPullDownRefresh()
},2500)
},
methods:{
apiGetwl(){
let _self=this;
api.postData("xgwms/tpmx/queryWlxx",{
"ckid":_self.$ckid,
"condition":_self.serachName
}).then((resp) => {
if(resp.data.success){
_self.wlinfor=resp.data.data.records
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
}).finally(()=>{
})
},
searchFood(){
this.apiGetwl()
},
nextTo(item){
let info={
gwjlinfor:this.gwjlinfor,
xzwl:"xzwl",
wlinfor:item
}
eventBus.$emit('addressInfo',info);
this.$router.go(-1)
// this.$Router.replace({ path:'/pages/gwjl/gwjl', query:{
// gwjlinfor:this.gwjlinfor,
// xzwl:"xzwl",
// wlinfor:item
// }
// })
},
gotoBackPage(){
this.$router.go(-1)
}
},
onLoad(e) {
if(!e.query){
return 0
}
let einfor =JSON.parse(e.query)
this.gwjlinfor=einfor.gwjlinfor
this.apiGetwl()
}
}
</script>
<style scoped>
.wid50{
width: 50%;
}
</style>
<template>
<view class="bg-white" style="height: 100vh;">
<cu-custom bgColor="bg-gradual-blue" :isBack="true" :reWrite="'homepage'">
<block slot="backText">返回</block>
<block slot="content">托盘信息绑定</block>
</cu-custom>
<view class="padding-xs bg-white">
<view class="cu-form-group ">
<view class="title">配盘单码</view>
<input focus="true" placeholder="请扫描配盘单码"></input>
</view>
</view>
<view class="padding-xs bg-white">
<view class="cu-form-group ">
<view class="title">扫托盘码</view>
<input @confirm="searchTpm" placeholder="请扫描配盘单码"></input>
</view>
</view>
<view class="padding flex justify-around bg-white ">
<button @tap="watchInfo" class="cu-btn bg-gradual-green xs " style="width: 50%;margin-top: 40vh;">查看入库登记信息</button>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
}
},
filters: {
formatTime: function(time) {
if (time != null && time != "") {
var date = new Date(time);
return date.Format("MM-dd hh:mm")
} else {
return "";
}
}
},
methods: {
searchTpm(){
uni.showModal({
title: '提示',
content: '配盘单码:PPM20220426001\n配盘单码:PPM20220426001',
cancelText: "继续扫描", // 取消按钮的文字
confirmText: "开始入库", // 确认按钮的文字
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
watchInfo(){
this.$router.push({name:"putin_register"})
},
// 确认按钮
hideModal(e) {
this.modalName = null
},
// 生成任务
// 扫描托盘号
// 选择物料
// 任务列表
},
onLoad(e) {
}
}
</script>
<style scoped>
input{
border-bottom: #EEEEEE 1px solid;
}
.disable {
background-color: #EEEEEE;
}
.b-right {
position: relative;
}
.wid50 {
width: 50%;
}
</style>
<template>
<view class="bg-white" style="height: 100vh;">
<cu-custom bgColor="bg-gradual-blue" :isBack="true" :reWrite="'homepage'">
<block slot="backText">返回</block>
<block slot="content">入库登记信息</block>
</cu-custom>
<view class="cu-modal" :class="modalName=='Modal'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">库位信息</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl">
<!-- 库位位置 -->
</view>
</view>
</view>
<view class="padding-xs bg-white" style="height: 60vh;overflow: auto;">
<!-- title -->
<view class="tbtit">
<view class="tbtit_son">托盘码</view>
<view class="tbtit_son">库位</view>
<view style="flex: 1;">状态</view>
</view>
<view class="tbtit_row " :class="item.selected?'selected':''" v-for="(item,index) in rkdjlist" :key="index" @tap="selectTb(item,index)">
<view class="tbtit_row_son1">{{item.tpm}}</view>
<view style="flex: 1">{{item.kw}}</view>
<view class="tbtit_row_son3">{{item.zt}}</view>
</view>
</view>
<view class="padding flex justify-around bg-white ">
<view class="padding-xs bg-white" style="">
<view class="cu-form-group ">
<view class="title">库位码</view>
<input focus="true" @confirm="searchKwm()" placeholder="扫描库位码查询"></input>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
modalName:"",
rkdjlist:[{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
}]
}
},
filters: {
formatTime: function(time) {
if (time != null && time != "") {
var date = new Date(time);
return date.Format("MM-dd hh:mm")
} else {
return "";
}
}
},
methods: {
searchKwm(){
/* 三种状态,1,对应库位入库,2,不对应库位,3,非界面的库位 */
uni.showModal({
title: '提示',
content: '确认入库',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
selectTb(item,index){
this.modalName="Modal"
if(this.rkdjlist[index].selected==true){
this.rkdjlist[index].selected=false
/* 清除选中值 */
}else{
this.rkdjlist[index].selected=true
/* 存储选中值 */
}
/* 清除其他选中值 */
this.rkdjlist.forEach((e,eindex)=>{
if(index!=eindex){
this.rkdjlist[eindex].selected=false
}
})
console.log(this.rkdjlist)
},
watchInfo(){
this.$router.push({name:"putin_register"})
},
// 确认按钮
hideModal(e) {
this.modalName = null
},
// 生成任务
// 扫描托盘号
// 选择物料
// 任务列表
},
onLoad(e) {
}
}
</script>
<style scoped>
.selected{
background-color: deepskyblue;
color: #fff;
}
.tbtit{
display: flex;border: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_row{
display: flex;border-bottom: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_son{
flex: 1;border-right: 1px solid #EEEEEE;
}
.tbtit_row_son1{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
.tbtit_row_son3{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
input{
border-bottom: #EEEEEE 1px solid;
}
.disable {
background-color: #EEEEEE;
}
.b-right {
position: relative;
}
.wid50 {
width: 50%;
}
</style>
<template>
<view class="bg-white" style="height: 100vh;">
<cu-custom bgColor="bg-gradual-blue" :isBack="true" :reWrite="'homepage'">
<block slot="backText">返回</block>
<block slot="content">出库登记信息</block>
</cu-custom>
<view class="cu-modal" :class="modalName=='Modal'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">库位信息</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl">
<view class="" style="height: 250px;width: 90vw;display: flex;flex-wrap:wrap">
<view style="height: 20%;width:90%;display: flex;">
<view style="flex: 1;line-height: 40px;"></view>
<view style="flex: 1;line-height: 40px;">G1</view>
<view style="flex: 1;line-height: 40px;">G2</view>
<view style="flex: 1;line-height: 40px;">G3</view>
<view style="flex: 1;line-height: 40px;">G4</view>
<view style="flex: 1;line-height: 40px;">G5</view>
<view style="flex: 1;line-height: 40px;">G6</view>
</view>
<view style="height: 20%;width:90%;display: flex;">
<view style="flex: 1;line-height: 40px;">S1</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位2</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位3</view>
<view style="flex: 1;height: 40px;"></view>
<view style="flex: 1;height: 40px;"></view>
<view style="flex: 1;height: 40px;"></view>
<view style="flex: 1;height: 40px;"></view>
</view>
<view style="height: 20%;width:90%;display: flex;">
<view style="flex: 1;line-height: 40px;">S2</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位2</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位3</view>
<view style="flex: 1;height: 40px;"></view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位5</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位6</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位7</view>
</view>
<view style="height: 20%;width:90%;display: flex;">
<view style="flex: 1;line-height: 40px;">S3</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位2</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位3</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位4</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位5</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位6</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位7</view>
</view>
<view style="height: 20%;width:90%;display: flex;">
<view style="flex: 1;line-height: 40px;">S4</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位2</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位3</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位4</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位5</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位6</view>
<view style="flex: 1;border: 1px solid #666;height: 40px;">库位7</view>
</view>
</view>
</view>
</view>
</view>
<view class="padding-xs bg-white" style="height: 45vh;overflow: auto;">
<!-- title -->
<view class="tbtit">
<view class="tbtit_son">托盘码</view>
<view class="tbtit_son">库位</view>
<view style="flex: 1;">状态</view>
</view>
<view class="tbtit_row " :class="item.selected?'selected':''" v-for="(item,index) in rkdjlist" :key="index" @tap="selectTb(item,index)">
<view class="tbtit_row_son1">{{item.tpm}}</view>
<view style="flex: 1">{{item.kw}}</view>
<view class="tbtit_row_son3">{{item.zt}}</view>
</view>
</view>
<view class="padding flex justify-around bg-white ">
<view class="padding-xs bg-white" style="">
<view class="cu-form-group ">
<view class="title">库位码</view>
<input focus="true" @confirm="searchKwm()" placeholder="扫描库位码查询"></input>
</view>
</view>
</view>
<view class=" flex justify-around bg-white ">
<view class="padding-xs bg-white" style="">
<view class="cu-form-group ">
<view class="title">取料区码</view>
<input focus="true" @confirm="searchQlqm()" placeholder="扫描取料区码查询"></input>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
modalName:"",
rkdjlist:[{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
}]
}
},
filters: {
formatTime: function(time) {
if (time != null && time != "") {
var date = new Date(time);
return date.Format("MM-dd hh:mm")
} else {
return "";
}
}
},
methods: {
searchQlqm(){
/* 三种状态,1,对应库位入库,2,不对应库位,3,非界面的库位 */
uni.showModal({
title: '提示',
content: '确认入库',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
searchKwm(){
/* 三种状态,1,对应库位入库,2,不对应库位,3,非界面的库位 */
uni.showModal({
title: '提示',
content: '确认入库',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
selectTb(item,index){
this.modalName="Modal"
if(this.rkdjlist[index].selected==true){
this.rkdjlist[index].selected=false
/* 清除选中值 */
}else{
this.rkdjlist[index].selected=true
/* 存储选中值 */
}
/* 清除其他选中值 */
this.rkdjlist.forEach((e,eindex)=>{
if(index!=eindex){
this.rkdjlist[eindex].selected=false
}
})
console.log(this.rkdjlist)
},
watchInfo(){
this.$router.push({name:"putin_register"})
},
// 确认按钮
hideModal(e) {
this.modalName = null
},
// 生成任务
// 扫描托盘号
// 选择物料
// 任务列表
},
onLoad(e) {
}
}
</script>
<style scoped>
.selected{
background-color: deepskyblue;
color: #fff;
}
.tbtit{
display: flex;border: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_row{
display: flex;border-bottom: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_son{
flex: 1;border-right: 1px solid #EEEEEE;
}
.tbtit_row_son1{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
.tbtit_row_son3{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
input{
border-bottom: #EEEEEE 1px solid;
}
.disable {
background-color: #EEEEEE;
}
.b-right {
position: relative;
}
.wid50 {
width: 50%;
}
</style>
<template>
<view class="bg-white" style="height: 100vh;">
<cu-custom bgColor="bg-gradual-blue" :isBack="true" :reWrite="'homepage'">
<block slot="backText">返回</block>
<block slot="content">入库登记信息</block>
</cu-custom>
<view class="cu-modal" :class="modalName=='Modal'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">库位信息</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl">
<!-- 库位位置 -->
</view>
</view>
</view>
<view class="padding-xs bg-white" style="height: 60vh;overflow: auto;">
<!-- title -->
<view class="tbtit">
<view class="tbtit_son">托盘码</view>
<view class="tbtit_son">库位</view>
<view style="flex: 1;">状态</view>
</view>
<view class="tbtit_row " :class="item.selected?'selected':''" v-for="(item,index) in rkdjlist" :key="index" @tap="selectTb(item,index)">
<view class="tbtit_row_son1">{{item.tpm}}</view>
<view style="flex: 1">{{item.kw}}</view>
<view class="tbtit_row_son3">{{item.zt}}</view>
</view>
</view>
<view class="padding flex justify-around bg-white ">
<view class="padding-xs bg-white" style="">
<view class="cu-form-group ">
<view class="title">库位码</view>
<input focus="true" @confirm="searchKwm()" placeholder="扫描库位码查询"></input>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
modalName:"",
rkdjlist:[{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
},
{
tpm:100010,
kw:100031,
zt:'zt',
selected:false
}]
}
},
filters: {
formatTime: function(time) {
if (time != null && time != "") {
var date = new Date(time);
return date.Format("MM-dd hh:mm")
} else {
return "";
}
}
},
methods: {
searchKwm(){
/* 三种状态,1,对应库位入库,2,不对应库位,3,非界面的库位 */
uni.showModal({
title: '提示',
content: '确认入库',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
selectTb(item,index){
this.modalName="Modal"
if(this.rkdjlist[index].selected==true){
this.rkdjlist[index].selected=false
/* 清除选中值 */
}else{
this.rkdjlist[index].selected=true
/* 存储选中值 */
}
/* 清除其他选中值 */
this.rkdjlist.forEach((e,eindex)=>{
if(index!=eindex){
this.rkdjlist[eindex].selected=false
}
})
console.log(this.rkdjlist)
},
watchInfo(){
this.$router.push({name:"putin_register"})
},
// 确认按钮
hideModal(e) {
this.modalName = null
},
// 生成任务
// 扫描托盘号
// 选择物料
// 任务列表
},
onLoad(e) {
}
}
</script>
<style scoped>
.selected{
background-color: deepskyblue;
color: #fff;
}
.tbtit{
display: flex;border: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_row{
display: flex;border-bottom: 1px solid #EEEEEE;height: 30px;width: 100%;line-height: 30px;text-align: center;
}
.tbtit_son{
flex: 1;border-right: 1px solid #EEEEEE;
}
.tbtit_row_son1{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
.tbtit_row_son3{
flex: 1;border-right: 1px solid #EEEEEE;border-left: #EEEEEE 1px solid;
}
input{
border-bottom: #EEEEEE 1px solid;
}
.disable {
background-color: #EEEEEE;
}
.b-right {
position: relative;
}
.wid50 {
width: 50%;
}
</style>
<template>
<view class="bg-white">
<cu-custom bgColor="bg-gradual-blue" :isBack="true"><block slot="content">托盘调整</block>
<block slot="backText">返回</block></cu-custom>
<view class="cu-form-group" >
<view class="title ">托盘号</view>
<input v-model="tpcode" placeholder="请扫描托盘号" focus="true" @confirm="apigetinfor()" ></input>
</view>
<view class="cu-form-group disable" >
<view class="title ">已扫托盘号</view>
<input v-model="ystpcode" disabled="" focus="true" @confirm="apigetinfor()" ></input>
</view>
<view v-for="(item,index) in wlinfor" :key="index">
<view class="flex flex-wrap padding bg-grey white radio" style="position: relative;">
<button @tap="deldata(item,index)" style="position: absolute;right: 10px;top: 5px;color: red;font-size: 12px;">
<span style="" >删除</span>
</button>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">物料<span>{{item.wlcode}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">名称:<span>{{item.wlname}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">规格:<span>{{item.wlgg}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">数量:<span>{{item.ztsl}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">托盘号:<span>{{item.tpcode}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">物料批号:<span>{{item.wlph}}</span></view>
</view>
<view class="cu-form-group" >
<view class="title ">物料数量维护</view>
<uni-number-box :min="0" :max="99999" v-model="item.ztsl" ></uni-number-box>
</view>
</view>
<!-- 假数据 -->
<view class="flex flex-wrap padding bg-grey white radio" style="position: relative;">
<button @tap="deldata(item,index)" style="position: absolute;right: 10px;top: 45px;color: #fff;background-color: red;font-size: 12px;">
<span style="" >删除</span>
</button>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">物料:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">名称:<span>{{'样式'}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">规格:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">数量:<span>{{'样式'}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">托盘号:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">物料批号:<span>{{'样式'}}</span></view>
</view>
<view class="cu-form-group" >
<view class="title ">物料数量维护</view>
<uni-number-box :min="0" :max="99999" v-model="testys" ></uni-number-box>
</view>
<view class="padding flex align-center bg-white justify-around">
<button class="cu-btn bg-gradual-green lg wid50" @tap="isbctz(2)">调整</button>
</view>
<view class="cu-modal" :class="modalName=='DialogModal1'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否删除该条信息?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="cdeldata()">确定</button>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='DialogModal2'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否保存并调整?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="apibctz()">确定</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
testys:10,
selected:"",
ystpcode:"",
modalName:"",
tpcode:"",
wlinfor:[],
}
},
methods:{
// api保存调整
apibctz(){
this.hideModal()
api.postData("xgwms/tpmx/adjustTpByCode",{
"ckid":this.$ckid,
"code":this.tpcode,
"data":this.wlinfor
}).then((resp) => {
if(resp.data.success)
{
this.$tip.alert("调整成功");
}
else{
this.$tip.alert(res.data.message || "操作失败");
}
this.tpcode=""
this.ystpcode=""
this.wlinfor=[]
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
this.tpcode=""
}).finally(()=>{
})
},
isbctz(){
if(this.ystpcode){
this.confirm(2)
}else{
this.$tip.alert("请先扫描有效托盘信息");
}
},
hideModal(){
this.modalName=""
},
// 弹框
confirm(e){
this.modalName="DialogModal"+e
},
// 删除确认
deldata(item,index){
this.selected=index
this.confirm(1)
},
// 确认删除
cdeldata(){
this.hideModal()
this.wlinfor.splice(this.selected,1)
this.selected=""
},
// 获取托盘信息
apigetinfor(){
this.tpcode=this.$trim(this.tpcode)
api.postData("xgwms/tpmx/searchTpmxsByCode",{
"ckid":this.$ckid,
"code":this.tpcode
}).then((resp) => {
if(resp.data.data.records)
{ this.ystpcode=this.tpcode
this.wlinfor=resp.data.data.records
}
else{
this.$tip.alert("该托盘无数据");
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
this.tpcode=""
}).finally(()=>{
})
}
},
onLoad() {
}
}
</script>
<style scoped>
/deep/.uni-numbox-btns{
width: 27.69px!important;
}
.disable{
background-color: #F5F5F5
}
.wid50{
width: 50%;
}
</style>
<template>
<view class="bg-white">
<cu-custom bgColor="bg-gradual-blue" :isBack="true"><block slot="content">托盘调整</block>
<block slot="backText">返回</block></cu-custom>
<view class="cu-form-group" >
<view class="title ">托盘号</view>
<input v-model="tpcode" placeholder="请扫描托盘号" focus="true" @confirm="apigetinfor()" ></input>
</view>
<view class="cu-form-group disable" >
<view class="title ">已扫托盘号</view>
<input v-model="ystpcode" disabled="" focus="true" @confirm="apigetinfor()" ></input>
</view>
<view v-for="(item,index) in wlinfor" :key="index">
<view class="flex flex-wrap padding bg-grey white radio" style="position: relative;">
<button @tap="deldata(item,index)" style="position: absolute;right: 10px;top: 5px;color: red;font-size: 12px;">
<span style="" >删除</span>
</button>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">物料<span>{{item.wlcode}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">名称:<span>{{item.wlname}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">规格:<span>{{item.wlgg}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">数量:<span>{{item.ztsl}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">托盘号:<span>{{item.tpcode}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">物料批号:<span>{{item.wlph}}</span></view>
</view>
<!-- <view class="cu-form-group" >
<view class="title ">物料数量维护</view>
<uni-number-box v-model="item.ztsl" ></uni-number-box>
</view> -->
</view>
<!-- 假数据 -->
<view class="flex flex-wrap padding bg-grey white radio" style="position: relative;">
<button @tap="deldata(item,index)" style="position: absolute;right: 10px;top: 45px;color: #fff;background-color: red;font-size: 12px;">
<span style="" >删除</span>
</button>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">物料:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">名称:<span>{{'样式'}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">规格:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">数量:<span>{{'样式'}}</span></view>
<view class="basis-sm margin-top-xs margin-bottom-xs radius">托盘号:<span>{{'样式'}}</span></view>
<view class="basis-lg margin-top-xs margin-bottom-xs radius">物料批号:<span>{{'样式'}}</span></view>
</view>
<!-- <view class="cu-form-group" >
<view class="title ">物料数量维护</view>
<uni-number-box min="0" max="99999" v-model="testys" ></uni-number-box>
</view> -->
<view class="padding flex align-center bg-white justify-around">
<button class="cu-btn bg-gradual-green lg wid50" @tap="isbctz(2)">清空</button>
</view>
<view class="cu-modal" :class="modalName=='DialogModal1'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否删除该条信息?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="cdeldata()">确定</button>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='DialogModal2'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">提示</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xl bg-white">
是否保存并调整?
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
<button class="cu-btn bg-green margin-left" @tap="apibctz()">确定</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api/api.js';
export default {
data() {
return {
testys:10,
selected:"",
ystpcode:"",
modalName:"",
tpcode:"",
wlinfor:[],
}
},
methods:{
// api保存调整
apibctz(){
this.hideModal()
api.postData("xgwms/tpmx/adjustTpByCode",{
"ckid":this.$ckid,
"code":this.tpcode,
"data":this.wlinfor
}).then((resp) => {
if(resp.data.success)
{
this.$tip.alert("调整成功");
}
else{
this.$tip.alert(res.data.message || "操作失败");
}
this.tpcode=""
this.ystpcode=""
this.wlinfor=[]
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
this.tpcode=""
}).finally(()=>{
})
},
isbctz(){
if(this.ystpcode){
this.confirm(2)
}else{
this.$tip.alert("请先扫描有效托盘信息");
}
},
hideModal(){
this.modalName=""
},
// 弹框
confirm(e){
this.modalName="DialogModal"+e
},
// 删除确认
deldata(item,index){
this.selected=index
this.confirm(1)
},
// 确认删除
cdeldata(){
this.hideModal()
this.wlinfor.splice(this.selected,1)
this.selected=""
},
// 获取托盘信息
apigetinfor(){
this.tpcode=this.$trim(this.tpcode)
api.postData("xgwms/tpmx/searchTpmxsByCode",{
"ckid":this.$ckid,
"code":this.tpcode
}).then((resp) => {
if(resp.data.data.records)
{ this.ystpcode=this.tpcode
this.wlinfor=resp.data.data.records
}
else{
this.$tip.alert("该托盘无数据");
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
this.tpcode=""
}).finally(()=>{
})
}
},
onLoad() {
}
}
</script>
<style scoped>
/deep/.uni-numbox-btns{
width: 27.69px!important;
}
.disable{
background-color: #F5F5F5
}
.wid50{
width: 50%;
}
</style>
<template>
<view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>
<template>
<view>
<interfacepage :cur="PageCur" v-if="PageCur=='index'" :key="commponent1Key"></interfacepage>
<people v-if="PageCur=='people'" :key="commponent2Key"></people>
<view class="cu-bar tabbar bg-white shadow foot">
<view :class="PageCur=='index'?'action text-green':'action text-gray'" @click="NavChange" data-cur="index">
<view class='cuIcon-homefill'></view>主页
</view>
<view :class="PageCur=='people'?'action text-green':'action text-gray'" @click="NavChange" data-cur="people">
<view class='cuIcon-people'></view>个人
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
PageCur: 'index',
commponent1Key: 0,
commponent2Key: 0,
}
},
onLoad:function(){
this.PageCur='index'
++this.commponent1Key
++this.commponent2Key
},
methods: {
NavChange: function(e) {
this.PageCur = e.currentTarget.dataset.cur
}
}
}
</script>
<style>
</style>
<template name="interfacepage">
<view>
<cu-custom bgColor="bg-gradual-blue">
<block slot="content">徐工道路WCS</block>
</cu-custom>
<scroll-view>
<view class="homepage" style="">
</view>
<!-- 徐工道路功能列表 -->
<view class="padding-sm">
<view class="cu-bar bg-white solid-bottom" >
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>仓库管理
</view>
</view>
<view class="grid col-2 bg-white">
<view class="padding-sm" v-for="(item,index) in ckglList" :key="index" @tap="goPage(item.page)">
<view class="radius text-center shadow-blur ">
<view class="cu-avatar lg "
:style="{background: 'url('+ item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}">
<view class="cu-tag badge" v-if="getTtemDotInfo(item)">{{getTtemDotInfo(item)}}</view>
</view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="padding-sm">
<view class="cu-bar bg-white solid-bottom" >
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>工位叫料
</view>
</view>
<view class="grid col-2 bg-white">
<view class="padding-sm" v-for="(item,index) in gwjlList" :key="index" @tap="goPage(item.page)">
<view class="radius text-center shadow-blur ">
<view class="cu-avatar lg "
:style="{background: 'url('+ item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}">
<view class="cu-tag badge" v-if="getTtemDotInfo(item)">{{getTtemDotInfo(item)}}</view>
</view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="padding-sm">
<view class="cu-bar bg-white solid-bottom" >
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>托盘管理
</view>
</view>
<view class="grid col-2 bg-white">
<view class="padding-sm" v-for="(item,index) in tpglList" :key="index" @tap="goPage(item.page)">
<view class="radius text-center shadow-blur ">
<view class="cu-avatar lg "
:style="{background: 'url('+ item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}">
<view class="cu-tag badge" v-if="getTtemDotInfo(item)">{{getTtemDotInfo(item)}}</view>
</view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<!-- 常用服务 -->
<view class="padding-sm" v-if="newusList.length!=0">
<view class="cu-bar bg-white solid-bottom" >
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>入库管理
</view>
</view>
<view class="grid col-2 bg-white">
<view class="padding-sm" v-for="(item,index) in newusList" :key="index" @tap="goPage(item.page)">
<view class="radius text-center shadow-blur ">
<view class="cu-avatar lg "
:style="{background: 'url('+ item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}">
<view class="cu-tag badge" v-if="getTtemDotInfo(item)">{{getTtemDotInfo(item)}}</view>
</view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="padding-sm" v-if="newosList.length!=0">
<view class="cu-bar bg-white solid-bottom">
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>工位叫料
</view>
</view>
<view class="bg-white grid col-2 padding-sm">
<view class="" v-for="(item,index) in newosList" :key="index" @tap="goPage(item.page)">
<view class="padding radius text-center shadow-blur solid-right">
<view class="cu-avatar lg " :style="{background: 'url(' + item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}"><!-- <view class="cu-tag badge">99</view> --></view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="padding-sm" v-if="newwsList.length!=0">
<view class="cu-bar bg-white solid-bottom">
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>出库管理
</view>
</view>
<view class="bg-white grid col-2 padding-sm">
<view class="" v-for="(item,index) in newwsList" :key="index" @tap="goPage(item.page)">
<view class="padding radius text-center shadow-blur solid-right">
<view class="cu-avatar lg " :style="{background: 'url(' + item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}"><!-- <view class="cu-tag badge">99</view> --></view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="padding-sm" v-if="newmsList.length!=0">
<view class="cu-bar bg-white solid-bottom">
<view class="action text-bold">
<text class='cuIcon-title text-blue'></text>调整
</view>
</view>
<view class="bg-white grid col-2 padding-sm">
<view class="" v-for="(item,index) in newmsList" :key="index" @tap="goPage(item.page)">
<view class="padding radius text-center shadow-blur solid-right">
<view class="cu-avatar lg " :style="{background: 'url(' + item.icon + ') no-repeat',backgroundSize:'56upx 56upx'}"><!-- <view class="cu-tag badge">99</view> --></view>
<view class="text-lg margin-top">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="cu-tabbar-height">
</view>
</scroll-view>
</view>
</template>
<script>
import api from '@/api/api.js';
import { us,os } from '@/common/util/work.js'
import tip from '@/common/util/tip.js';
export default {
name: 'interfacepage',
props:{
cur:String,
},
watch: {
cur: {
immediate: true,
handler() {
this.apiqx()
this.initMenu()
},
},
},
data() {
return {
/* 功能列表 */
ckglList:[
{
title:"入库登记",
icon:"/static/icon/work.png",
useCount:1000,
page:"putin_storage"
},
{
title:"出库登记",
icon:"/static/icon/work3.png",
useCount:1000,
page:"putout_storage"
},
],
gwjlList:[
{
title:"工位叫料",
icon:"/static/icon/wl2.png",
useCount:1000,
page:"cmaterial"
}
],
tpglList:[
{
title:"托盘调整",
icon:"/static/icon/work5.png",
useCount:1000,
page:"trayAdjust"
},
{
title:"清空托盘",
icon:"/static/icon/work6.png",
useCount:1000,
page:"trayClear"
}
],
// icon:"/wcs/apps/static/icon/work.png",pc端图标路径
//手机端去除/wcs/xgapps
swiperList: [
],
usList:[
// {
// title:"原材入库",
// icon:"/static/icon/work.png",
// useCount:1000,
// page:"putin-storage"
// },
// {
// title:"生产入库",
// icon:"/static/icon/work.png",
// useCount:1000,
// page:"ascrk"
// },
// {
// title:"其它入库",
// icon:"/static/icon/work2.png",
// useCount:1000,
// page:"qtrk"
// },
// {
// title:"托盘检验",
// icon:"/static/icon/tpjy.png",
// useCount:1000,
// page:"tpjy"
// }
],
newusList:[],
osList:[
// {
// title:"工位叫料",
// icon:"/static/icon/wl2.png",
// useCount:1000,
// page:"gwxz"
// },
// {
// title:"清洗送料",
// icon:"/static/icon/wl2.png",
// useCount:1000,
// page:"qxslgwxz"
// }
],
newosList:[],
wsList:[
// {
// title:"产品出库",
// icon:"/static/icon/work3.png",
// useCount:1000,
// page:"ckd"
// },
// {
// title:"其它出库",
// icon:"/static/icon/work4.png",
// useCount:1000,
// page:"qtck"
// }
],
newwsList:[],
msList:[
// {
// title:"托盘调整",
// icon:"/static/icon/work5.png",
// useCount:1000,
// page:"tptz"
// },
// {
// title:"清空托盘",
// icon:"/static/icon/work6.png",
// useCount:1000,
// page:"qktp"
// }
],
newmsList:[],
websock:'',
heartCheck:null,
lockReconnect:false,
msgCount:0,
dot:{
mailHome:false
}
}
},
methods: {
// api获取权限
apiqx(){
let _self=this;
api.postData("/frame/init/mobile",{
}).then((resp) => {
if(resp.data.success){
let getqx=resp.data.data.menu
// 入库管理遍历
let newusList=[]
getqx.forEach(e=>{
this.usList.forEach(a=>{
if(a.title==e.mkmc){
newusList.push(a)
}
})
})
this.newusList=newusList
// 工位叫料遍历
let newosList=[]
getqx.forEach(e=>{
this.osList.forEach(a=>{
if(a.title==e.mkmc){
newosList.push(a)
}
})
})
this.newosList=newosList
// 出库管理
let newwsList=[]
getqx.forEach(e=>{
this.wsList.forEach(a=>{
if(a.title==e.mkmc){
newwsList.push(a)
}
})
})
this.newwsList=newwsList
// 调整
let newmsList=[]
getqx.forEach(e=>{
this.msList.forEach(a=>{
if(a.title==e.mkmc){
newmsList.push(a)
}
})
})
this.newmsList=newmsList
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
}).finally(()=>{
})
},
returnPage(){
this.$Router.replace({name: 'login'})
},
initMenu(){
// this.initWebSocket();
this.loadCount(0);
},
goPage(page){
if(!page){
return false;
}
if(page==='annotationList'){
this.msgCount = 0
}
this.dot[page]=false
this.$Router.push({name: page})
},
initWebSocket: function () {
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
var userId = this.$store.getters.userid;
var url = this.$config.apiUrl.replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;
this.websock = new WebSocket(url);
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
this.websock.onmessage = this.websocketOnmessage;
this.websock.onclose = this.websocketOnclose;
},
websocketOnopen: function () {
//心跳检测重置
//this.heartCheck.reset().start();
},
websocketOnerror: function () {
this.reconnect();
},
websocketOnmessage: function (e) {
var data = eval("(" + e.data + ")"); //解析对象
if(data.cmd == "topic"){
//系统通知
this.loadCount('1')
}else if(data.cmd == "user"){
//用户消息
this.loadCount('2')
} else if(data.cmd == 'email'){
this.loadEmailCount()
}
//心跳检测重置
//this.heartCheck.reset().start();
},
websocketOnclose: function (e) {
this.reconnect();
},
websocketSend(text) { // 数据发送
try {
this.websock.send(text);
} catch (err) {
}
},
reconnect() {
var that = this;
if(that.lockReconnect) return;
that.lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
setTimeout(function () {
that.initWebSocket();
that.lockReconnect = false;
}, 5000);
},
loadCount(flag){
/* let url = '/sys/annountCement/listByUser';
this.$http.get(url).then(res=>{
if(res.data.success){
let msg1Count = res.data.result.anntMsgTotal;
let msg2Count = res.data.result.sysMsgTotal;
this.msgCount = msg1Count + msg2Count
}
}) */
},
loadEmailCount(){
this.dot.mailHome = true
},
getTtemDotInfo(item){
if(item.page==='annotationList' && this.msgCount>0){
return this.msgCount
}
return '';
},
},
}
</script>
<style scoped>
.homepage{
height: 25vh;width: 100%;background-image: url(/static/home/u3.png);background-size: 100% 100%;
}
.line2-icon {
width: 28px;
height: 28px;
}
.screen-swiper{
height: 90px!important;
min-height: 90px!important;
}
.nav-li{
margin: 0 2.5% 0px;
}
.text-df {
font-size: 14px;
margin-left: 6px;
}
.text-lg{
font-size: 14px;
}
</style>
<template>
<view class="bg-white">
<cu-custom :isxzck="false" :isBack="true" bgColor="bg-gradual-blue" >
<block slot="backText">返回</block>
<block slot="content">设置服务器</block>
</cu-custom>
<view>
<view class="cu-form-group " >
<view class="title">当前地址:</view>
<input disabled="" placeholder="" name="input" >
{{fwq||'未设置'}}
</input>
</view>
<view class="cu-form-group " v-for="(item,index) in fwqlist" :key="index">
<view class="title">地址{{index+1}}:</view>
<input placeholder="" v-model="item.fwq" name="input" >
<view class="flex" style="width: 90px;justify-content: space-around;">
<view style="color: red;" @tap="delfwq(item,index)">删除</view>
<!-- <view style="color: #007AFF;">编辑</view> -->
<view style="color:#39B54A;" @tap="select(item)">选择</view>
</view>
</input>
</view>
<view class="padding">
<button class="cu-btn block line-orange lg margin " @tap="adddz()">
<text class="cuIcon-add"></text> 新增地址</button>
</view>
</view>
</view>
</template>
<script>
import http from '@/common/service/service.js';
export default {
data:function(){
return{
fwq:"",
fwqlist:[],
infor:{userName:"",password:""}
}
},
methods:{
delfwq(item,index){
this.fwqlist.splice(index,1);
},
adddz(){
this.fwqlist.push({fwq:""})
},
select(item){
let newfwqlist=[]
this.fwqlist.forEach(e=>{
if(e.fwq!=""){
newfwqlist.push(e)
}
})
uni.setStorage({
key: 'fwqlist',
data: newfwqlist,
success: function () {
}
});
if(item.fwq){
uni.setStorage({
key: 'storage_key',
data: "http://"+item.fwq+'/wcs',
success: function () {
uni.showToast({
title: '设置成功',
duration: 2000
})
// that.logining=false;
},
fail:function(){
uni.showToast({
title: '设置失败',
duration: 2000
})
}
});
uni.setStorage({
key: 'sqlPort',
data: item.fwq,
success: function () {
uni.showToast({
title: '设置成功',
duration: 2000
})
},
fail:function(){
uni.showToast({
title: '设置失败',
duration: 2000
})
}
});
this.$Router.push({
path: '/pages/login/login', query:{
infor:this.infor
},
})
}else{
this.$tip.toast('请填入地址!')
}
}
},
onLoad(d) {
let infor=JSON.parse(d.query).infor
this.infor=infor
let that =this
// 获取本地服务器列表
uni.getStorage({
key:'fwqlist',
success:function(e){
that.fwqlist=e.data
},
fail() {
console.log("获取失败,请手动输入")
}
})
uni.getStorage({
key:'sqlPort',
success:function(e){
that.fwq=e.data
},
fail() {
}
})
}
}
</script>
<style>
</style>
<template>
<view class="container" style="background-color: #FFFFFF;">
<!-- <view class="left-bottom-sign"></view> -->
<view class="back-btn yticon icon-zuojiantou-up" @click="navBack"></view>
<!-- <view class="right-top-sign"></view> -->
<!-- 设置白色背景防止软键盘把下部绝对定位元素顶上来盖住输入框等 -->
<view class="wrapper">
<view class="left-top-sign"></view>
<view class="welcome">
欢迎您!
</view>
<view v-if="loginType === 'phone'" class="input-content">
<view class="input-item">
<text class="tit">用户名</text>
<input type="text" v-model="userName" data-key="phone" @input="inputChange" />
</view>
<view class="input-item">
<text class="tit">密码</text>
<input type="password" v-model="password" placeholder-class="input-empty" maxlength="20"
password data-key="password" @input="inputChange" @confirm="toLogin" />
</view>
<!-- <view class="input-item">
<text class="tit">服务器:端口号</text>
<input type="text" v-model="sqlForm.sqlPort"/>
</view> -->
<!-- <view class="input-item">
<text class="tit">端口</text>
<input type="text" v-model="sqlForm.port"/>
</view> -->
<view @click="gofwqsz" class="padding text-right" style="color: #4399FC;">
服务器设置
</view>
<checkbox-group class="flex" @change="CheckboxChange">
<view></view>
<checkbox class='round' :class="checkbox[0].checked?'checked':''" :checked="checkbox[0].checked?true:false" value="Y"></checkbox>
<view class="title margin-left">记住密码
</view>
</checkbox-group>
</view>
<!-- #ifdef MP-WEIXIN -->
<button v-if="loginType === 'wechat'" class="confirm-btn" open-type="getUserInfo" @getuserinfo="miniWechatLogin"
:disabled="logining">微信授权登录</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button v-if="loginType === 'wechat'" class="confirm-btn" @click="wechatLogin" :disabled="logining">微信授权登录</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button v-if="loginType === 'wechat'" class="confirm-btn" @click="wechatH5Login" :disabled="logining">微信授权登录</button>
<!-- #endif -->
<button v-if="loginType === 'phone'" class="confirm-btn" @click="toLogin" >登录</button>
<!-- <view v-if="loginType === 'phone'" class="forget-section">
忘记密码?
</view> -->
<!-- #ifdef APP-PLUS -->
<view class="padding flex flex-direction text-center ">
当前版本:{{version}}
</view>
<!-- #endif -->
</view>
<view v-if="loginType === 'phone'" class="register-section">
还没有账号?
<text >请联系系统管理员</text>
</view>
</view>
</template>
<script>
import md5 from '../../common/util/md5.js'
import { ACCESS_TOKEN,USER_NAME,USER_INFO } from "@/common/util/constants"
import { mapActions } from "vuex"
export default {
data() {
return {
loginType: 'phone',
userName: '',
password: '',
sqlForm:{
sqlPort:'',
},
logining: false,
version:'',
checkbox: [{
value: 'Y',
checked: true
}],
}
},
onShow() {
},
onLoad(options) {
let _self=this;
uni.getStorage({
key:'url_ley',
success:function(e){
let s=JSON.parse(e.data)
_self.userName=s.username;
_self.password=s.password;
},
fail() {
}
})
// uni.getStorage({
// key:'sqlPort',
// success:function(e){
// _self.sqlForm.sqlPort=e.data
// },
// fail() {
// }
// })
// uni.getStorageInfo({
// success: function (res) {
// if(uni.getStorageSync('storage_key')){
// _self.sql=uni.getStorageSync('storage_key');
// }
// }
// })
// #ifdef APP-PLUS
var that=this
plus.runtime.getProperty( plus.runtime.appid, function ( wgtinfo ) {
that.version=wgtinfo.version
} );
// #endif
},
methods: {
...mapActions(['mLogin']),
gofwqsz(){
this.$Router.push({
path: '/pages/login/fwqsz', query:{
infor:{
userName:this.userName,
password:this.password
}
},
})
},
inputChange(e) {
const key = e.currentTarget.dataset.key;
this[key] = e.detail.value;
},
chooseLoginType(type) {
this.loginType = type
},
navBack() {
uni.navigateBack();
},
toRegist() {
uni.redirectTo({
url: '/pages/public/register'
})
},
CheckboxChange(e) {
var items = this.checkbox,
values = e.detail.value;
for (var i = 0, lenI = items.length; i < lenI; ++i) {
items[i].checked = false;
for (var j = 0, lenJ = values.length; j < lenJ; ++j) {
if (items[i].value == values[j]) {
items[i].checked = true;
break
}
}
}
},
toLogin:function() {
const that = this;
uni.getStorage({
key:'sqlPort',
success:function(e){
console.log(e)
if(e.data=="")
that.$tip.toast('请先设置服务器');
return false
},
fail() {
that.$tip.toast('请先设置服务器');
}
})
if(!this.userName || this.userName.length==0){
this.$tip.toast('请填写用户名');
return;
}
if(!this.password || this.password.length==0){
this.$tip.toast('请填写密码');
return;
}
let loginParams = {
username: this.userName.toLowerCase(),//toLowerCasse()转化小写
password: this.password,
encodePWD:md5(this.userName.toLowerCase() + "USER" + this.password + "PASSWORD")
}
let params={
userid: loginParams.username,
password: loginParams.encodePWD,
newPassword:md5(this.password)
}
this.logining=true;
//#ifdef MP-WEIXIN
//若是小程序平台,则获取到openId。整个过程是静默完成的
uni.login({
provider: 'weixin',
success: (wxres => {
that.$api.request('user', 'login', {
phone: that.phone,
password: that.password,
loginType: 1,
raw: JSON.stringify(wxres)
}, failres => {
that.logining = false
uni.showToast({
title: failres.errmsg,
icon: "none"
});
}).then(res => {
that.logining = false
that.$store.commit('login', res.data)
uni.setStorageSync('userInfo', res.data)
if (that.$api.prePage().loadData) {
that.$api.prePage().loadData()
}
uni.navigateBack()
})
})
})
//#endif
//#ifdef APP-PLUS || H5
//若是App登录,则不需要保存OpenId。可直接登录
this.mLogin(params).then((res) => {
this.logining=false;
if(res.data.success){
let s=JSON.stringify({
"username":"",
"password":""
});
if(that.checkbox[0].checked){
s=JSON.stringify({
"username":that.userName,
"password":that.password
});
}else{
s=JSON.stringify({
"username":"",
"password":""
})
}
uni.setStorage({
key:'url_ley',
data:s,
success:function(){
},
fail() {
}
})
this.$tip.success('登录成功!')
this.$Router.replaceAll({name:'homepage'})
}else{
this.$tip.alert(res.data.message);
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
}).finally(()=>{
this.loading=false;
this.logining=false;
})
//#endif
},
miniWechatLogin(e) {
const that = this
that.logining = true
let loginType = 1
let userInfo = e.detail.userInfo
uni.login({
provider: 'weixin',
success: (wxres => {
that.logining = false
that.$api.request('user', 'thirdPartLogin', {
loginType: loginType,
raw: JSON.stringify(wxres)
}, failres => {
that.$api.msg(failres.errmsg)
uni.hideLoading()
}).then(res => {
that.$api.setUserInfo(res.data)
if (!res.data.nickname) {
that.$api.request('user', 'syncUserInfo', userInfo).then(syncRes => {
//同步过后
res.data.nickname = userInfo.nickName
res.data.avatarUrl = userInfo.avatarUrl
res.data.gender = userInfo.gender
uni.setStorageSync('userInfo', res.data)
that.$store.commit('login', res.data)
that.$api.setUserInfo(res.data)
if (that.$api.prePage().loadData) {
that.$api.prePage().loadData()
}
uni.hideLoading()
uni.navigateBack()
})
} else {
that.$store.commit('login', res.data)
that.$api.setUserInfo(res.data)
if (that.$api.prePage().loadData) {
that.$api.prePage().loadData()
}
uni.hideLoading()
uni.navigateBack()
}
})
})
})
},
wechatLogin() {
const that = this
that.logining = true
let loginType = 2
uni.showLoading({
title: '正在同步消息'
})
uni.login({
provider: 'weixin',
success: (wxres => {
that.$api.request('user', 'thirdPartLogin', {
loginType: loginType,
raw: JSON.stringify(wxres)
}, failres => {
that.$api.msg(failres.errmsg)
uni.hideLoading()
}).then(res => {
that.logining = false
uni.getUserInfo({
lang: 'zh_CN',
success: (e) => {
uni.setStorageSync('userInfo', res.data)
that.$store.commit('login', res.data)
e.userInfo.nickname = e.userInfo.nickName
that.$api.request('user', 'syncUserInfo', e.userInfo).then(syncRes => {
//同步过后
res.data.nickname = e.userInfo.nickName
res.data.avatarUrl = e.userInfo.avatarUrl
res.data.gender = e.userInfo.gender
uni.setStorageSync('userInfo', res.data)
that.$store.commit('login', res.data)
})
},
complete: (e) => {
if (that.$api.prePage().loadData) {
that.$api.prePage().loadData()
}
uni.hideLoading()
uni.navigateBack()
}
})
})
})
})
},
wechatH5Login() {
const that = this
let href = window.location.origin
let page = that.$api.prePage()
let prePath = '/pages/index/index'
if (page) {
prePath = page.__page__.path
}
window.location = 'https://open.weixin.qq.com/connect/oauth2/authorize?'
+ 'appid=' + that.$api.config.h5Appid + '&redirect_uri=' + escape(href) + '&response_type=code&scope=snsapi_userinfo&state=' + escape(prePath) + '#wechat_redirect'
}
},
}
</script>
<style lang='scss' >
uni-page-body{
/* background-color: #FFFFFF!important;
background-image: none!important; */
}
page {
/* background: #fff; */
}
.container {
padding-top: 115px;
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background: #fff;
}
.wrapper {
position: relative;
z-index: 90;
background: #fff;
padding-bottom: 40upx;
}
.back-btn {
position: absolute;
left: 40upx;
z-index: 9999;
padding-top: var(--status-bar-height);
top: 40upx;
font-size: 40upx;
color: $font-color-dark;
}
.left-top-sign {
font-size: 120upx;
color: $page-color-base;
position: relative;
left: -16upx;
}
.right-top-sign {
position: absolute;
top: 80upx;
right: -30upx;
z-index: 95;
&:before,
&:after {
display: block;
content: "";
width: 400upx;
height: 80upx;
background: #b4f3e2;
}
&:before {
transform: rotate(50deg);
border-radius: 0 50px 0 0;
}
&:after {
position: absolute;
right: -198upx;
top: 0;
transform: rotate(-50deg);
border-radius: 50px 0 0 0;
/* background: pink; */
}
}
.left-bottom-sign {
position: absolute;
left: -270upx;
bottom: -320upx;
border: 100upx solid #d0d1fd;
border-radius: 50%;
padding: 180upx;
}
.welcome {
position: relative;
left: 50upx;
top: -90upx;
font-size: 46upx;
color: #555;
text-shadow: 1px 0px 1px rgba(0, 0, 0, .3);
}
.input-content {
padding: 0 60upx;
}
.input-item {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
padding: 0 30upx;
background: $page-color-light;
height: 120upx;
border-radius: 4px;
margin-bottom: 50upx;
border-radius: 30px;
&:last-child {
margin-bottom: 0;
}
.tit {
height: 50upx;
line-height: 56upx;
font-size: $font-sm+2upx;
color: $font-color-base;
}
input {
height: 60upx;
font-size: $font-base + 2upx;
color: $font-color-dark;
width: 100%;
}
}
.confirm-btn {
width: 630upx;
height: 76upx;
line-height: 76upx;
border-radius: 50px;
margin-top: 70upx;
background: $uni-color-primary;
color: #fff;
font-size: $font-lg;
&:after {
border-radius: 100px;
}
}
.forget-section {
font-size: $font-sm+2upx;
color: $font-color-spec;
text-align: center;
margin-top: 40upx;
}
.register-section {
position: absolute;
left: 0;
bottom: 50upx;
width: 100%;
font-size: $font-sm+2upx;
color: $font-color-base;
text-align: center;
text {
color: $font-color-spec;
margin-left: 10upx;
}
}
.round{
width: 18px!important;
height: 18px!important;
}
</style>
<template>
<view>
<scroll-view scroll-y class="page">
<!-- 头部logo-->
<view class="UCenter-bg" @click="remove">
<image :src="personalList.avatar" round class="png animation-slide-right margin-bottom-sm" mode="widthFix" :style="[{animationDelay: '0.1s'}]"></image>
<view class="text-xl animation-slide-left" :style="[{animationDelay: '0.2s'}]">
{{personalList.depart}}
</view>
<image src="/static/wave.gif" mode="scaleToFill" class="gif-wave"></image>
</view>
<view class="padding flex text-center text-grey bg-white shadow-warp">
<view class="flex flex-sub flex-direction solid-right animation-slide-top" :style="[{animationDelay: '0.2s'}]">
<view class="text-xl text-orange">{{personalList.username}}</view>
<view class="margin-top-sm"><text class="cuIcon-people"></text> 用户</view>
</view>
<view class="flex flex-sub flex-direction animation-slide-top" :style="[{animationDelay: '0.2s'}]">
<view class="text-xl text-green">{{personalList.post?personalList.post:'员工'}}</view>
<view class="margin-top-sm"><text class="cuIcon-news"></text> 职务</view>
</view>
</view>
<!-- 列表list-->
<view class="cu-list menu card-menu margin-top-xl margin-bottom-xl shadow-lg radius">
<view class="cu-item arrow animation-slide-bottom" :style="[{animationDelay: '0.7s'}]">
<navigator class="content" url="/pages/login/login" hover-class="none" @tap="logout">
<text class="cuIcon-exit text-cyan"></text>
<text class="text-grey">退出</text>
</navigator>
</view>
</view>
<view class="cu-tabbar-height"></view>
</scroll-view>
</view>
</template>
<script>
import appUpdate from 'common/util/appUpdate.js'
import api from '@/api/api'
export default {
name: "people",
data() {
return {
personalList:{
avatar:'',
realname:'',
username:'',
post:''
},
positionUrl:'/sys/position/list',
departUrl:'/sys/user/userDepartList',
userUrl:'/sys/user/queryById',
userId:'',
id:''
};
},
watch: {
cur: {
immediate: true,
handler() {
this.load()
// #ifdef APP-PLUS
// 检测升级
console.log("appUpdate")
appUpdate()
// #endif
},
},
},
methods: {
remove(){
uni.removeStorageSync('Access-Token')
},
load(){
},
logout(){
let url="/logout";
api.postData(url,{}).then((res) => {
})
}
}
}
</script>
<style>
.UCenter-bg {
background-image: url(https://image.weilanwl.com/color2.0/index.jpg);
background-size: cover;
height: 400rpx;
display: flex;
justify-content: center;
padding-top: 40rpx;
overflow: hidden;
position: relative;
flex-direction: column;
align-items: center;
color: #fff;
font-weight: 300;
text-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
}
.UCenter-bg text {
opacity: 0.8;
}
.UCenter-bg image {
width: 200rpx;
height: 200rpx;
}
.UCenter-bg .gif-wave{
position: absolute;
width: 100%;
bottom: 0;
left: 0;
z-index: 99;
mix-blend-mode: screen;
height: 100rpx;
}
map,.mapBox{
left: 0;
z-index: 99;
mix-blend-mode: screen;
height: 100rpx;
}
map,.mapBox{
width: 750rpx;
height: 300rpx;
}
</style>
<template name="user">
<view>
<scroll-view scroll-y class="page">
<image src="/static/componentBg.png " mode="widthFix" class="response"></image>
<view class="nav-list">
<navigator hover-class="none" :url="'/pages/common/' + item.name" class="nav-li" navigateTo :class="'bg-'+item.color"
:style="[{animation: 'show ' + ((index+1)*0.2+1) + 's 1'}]" v-for="(item,index) in elements" :key="index">
<view class="nav-title">{{item.title}}</view>
<view class="nav-name">{{item.name}}</view>
<text :class="'cuIcon-' + item.cuIcon"></text>
</navigator>
</view>
<view class="cu-tabbar-height"></view>
</scroll-view>
</view>
</template>
<script>
export default {
name: 'user',
data() {
return {
elements: [{
title: '退出',
name: 'exit',
color: 'cyan',
cuIcon: 'newsfill',
auth: 'ac'
}
],
}
},
methods: {}
}
</script>
<style>
</style>
<template>
<view>
<scroll-view scroll-y class="page">
<cu-custom bgColor="bg-gradual-pink" :isBack="true">
<block slot="backText">返回</block>
<block slot="content">用户详情</block>
<view slot="right" @tap="rightClick">编辑</view>
</cu-custom>
<!-- list列表 -->
<view class="cu-list menu">
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.1s'}]">
<view class="content">
<text class="text-grey">头像</text>
</view>
<view class="action">
<view class="cu-avatar round sm" :style="{backgroundImage: 'url(' + personalMsg.avatar + ')'}"></view>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.2s'}]">
<view class="content">
<text class="text-grey">姓名</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.realname}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.3s'}]">
<view class="content">
<text class="text-grey">性别</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.sex}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.4s'}]">
<view class="content">
<text class="text-grey">生日</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.birthday}}</text>
</view>
</view>
</view>
<view class="cu-list menu">
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.5s'}]">
<view class="content">
<text class="text-grey">对外信息展示</text>
</view>
<view class="action">
<text class="text-grey">{{getSubStringText(personalMsg.realname+'@'+personalMsg.orgCode,11)}}</text>
</view>
</view>
</view>
<view class="cu-list menu">
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.6s'}]">
<view class="content">
<text class="text-grey">所在部门</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.orgCode}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.7s'}]">
<view class="content">
<text class="text-grey">工号</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.workNo}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.8s'}]">
<view class="content">
<text class="text-grey">状态</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.status}}</text>
</view>
</view>
</view>
<view class="cu-list menu">
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '0.9s'}]">
<view class="content">
<text class="text-grey">手机</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.phone}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '1s'}]">
<view class="content">
<text class="text-grey">邮箱</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.email}}</text>
</view>
</view>
</view>
<view class="cu-list menu">
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '1.1s'}]">
<view class="content">
<text class="text-grey">职务</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.post}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" :style="[{animationDelay: '1.2s'}]">
<view class="content">
<text class="text-grey">身份</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.identity}}</text>
</view>
</view>
<view class="cu-item animation-slide-bottom" v-if="personalMsg.identity =='上级'" >
<view class="content">
<text class="text-grey">负责部门</text>
</view>
<view class="action">
<text class="text-grey">{{personalMsg.departIds}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import api from '@/api/api.js'
export default {
data() {
return {
personalMsg:{
avatar:'',
realname:'',
username:'',
sex:1,
birthday:new Date(),
orgCode:'',
workNo:'',
status:1,
phone:'',
telephone:'',
email:'',
post:'',
departIds:'',
identity:'',
},
userUrl:'/sys/user/queryById',
positionUrl:'/sys/position/list',
departUrl:'/sys/user/userDepartList'
};
},
onLoad() {
this.loadinfo()
},
methods: {
getSubStringText(text,len){
if(!text || text.length==0){
return ''
}
if(text.length<len){
return text;
}
return text.substr(0,len)+"..."
},
rightClick(){
this.$Router.push({name:'useredit', params:this.personalMsg})
/* uni.navigateTo({
url: '/pages/user/useredit?item='+item
}); */
},
loadinfo(){
this.$http.get(this.departUrl,{params:{userId:this.$store.getters.userid}}).then(res=> {
if (res.success) {
for (let item of res.result){
this.personalMsg.orgCode = item.title
this.personalMsg.departIds = item.title
}
}
}).catch(e=>{
console.log("请求错误",e)
})
this.$http.get(this.positionUrl).then(res=> {
if (res.success) {
let postArr = res.result.records
for (let item of postArr ){
if (this.personalMsg.post == item.code){
this.personalMsg.post = item.name
}
}
}
}).catch(e=>{
console.log("请求错误",e)
})
},
}
}
</script>
<style>
.page {
height: 100Vh;
width: 100vw;
}
.page.show {
overflow: hidden;
}
.switch-sex::after {
content: "\e716";
}
.switch-sex::before {
content: "\e7a9";
}
.switch-music::after {
content: "\e66a";
}
.switch-music::before {
content: "\e6db";
}
</style>
<template>
<view>
<cu-custom bgColor="bg-gradual-pink" :isBack="true">
<block slot="backText">返回</block>
<block slot="content">编辑资料</block>
</cu-custom>
<form>
<view class="cu-form-group">
<view class="title">姓名</view>
<input placeholder="请输入姓名" name="input" v-model="myFormData.realname"></input>
</view>
<view class="cu-form-group">
<view class="title">用户名</view>
<input placeholder="用户名" name="input" v-model="myFormData.username" disabled></input>
</view>
<view class="cu-form-group">
<view class="title">头像</view>
<view class="grid col-4 grid-square flex-sub">
<view class="bg-img" v-for="(item,index) in imgList" :key="index" @tap="ViewImage" :data-url="imgList[index]">
<image :src="imgList[index]" mode="aspectFill"></image>
<view class="cu-tag bg-red radius" @tap.stop="DelImg" :data-index="index">
<text class='cuIcon-close'></text>
</view>
</view>
<view class="solids" @tap="ChooseImage" v-if="imgList.length<1">
<text class='cuIcon-cameraadd'></text>
</view>
</view>
</view>
<view class="cu-form-group margin-top">
<view class="title">性别</view>
<switch class='switch-sex' @change="SwitchC" :class="switchC?'checked':''" :checked="switchC?true:false"></switch>
</view>
<view class="cu-form-group">
<view class="title">生日</view>
<picker mode="date" :value="myFormData.birthday" @change="DateChange">
<view class="picker">
{{myFormData.birthday}}
</view>
</picker>
</view>
<view class="cu-form-group margin-top">
<view class="title">所在部门</view>
<input placeholder="所在部门" name="input" v-model="myFormData.orgCode" disabled></input>
</view>
<view class="cu-form-group">
<view class="title">工号</view>
<input placeholder="工号" name="input" v-model="myFormData.workNo" disabled></input>
</view>
<view class="cu-form-group margin-top">
<view class="title">手机号码</view>
<input placeholder="输入手机号码" name="input" v-model="myFormData.phone"></input>
<view class="cu-capsule radius">
<view class='cu-tag bg-blue '>
+86
</view>
<view class="cu-tag line-blue">
中国大陆
</view>
</view>
</view>
<view class="cu-form-group">
<view class="title">邮箱</view>
<input placeholder="输入邮箱" name="input" v-model="myFormData.email"></input>
</view>
<view class="padding flex flex-direction">
<button class="cu-btn bg-blue lg" @click="onSubmit">提交</button>
</view>
</form>
</view>
</template>
<script>
export default {
data() {
return {
index: -1,
switchC: true,
imgList: [],
uploadUrl:"/sys/common/upload",
myFormData:{
avatar:'',
realname:'',
username:'',
sex:1,
birthday:'',
orgCode:'',
workNo:'',
phone:'',
email:'',
id:'',
},
};
},
onLoad: function (option) {
console.log("this.$Route.query",this.$Route.query);
let query=this.$Route.query
if(query){
this.myFormData=query;
if(this.myFormData.sex=='女'){
this.switchC = false
}else if(this.myFormData.sex=='男'){
this.switchC = true
}
if(this.myFormData.avatar){
this.imgList=[this.myFormData.avatar]
}
if(!this.myFormData.birthday){
this.myFormData.birthday= '无'
}
if(this.myFormData.identity=='普通成员'){
this.myFormData.identity = 1
}else if(this.myFormData.identity=='上级'){
this.myFormData.identity = 2
}
if(this.myFormData.status=='正常'){
this.myFormData.status = 1
}else if(this.myFormData.status=='冻结'){
this.myFormData.status = 2
}
this.Avatar=this.myFormData.avatar
Object.keys(this.myFormData).map(key=>{
if(this.myFormData[key]=='无'){
this.myFormData[key] = ''
}
})
console.log("this.myFormData",this.myFormData)
}
},
methods: {
onSubmit() {
let myForm = this.myFormData
let checkPhone = new RegExp(/^[1]([3-9])[0-9]{9}$/);
let checkEmail = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/;
console.log("myForm",myForm)
if(!myForm.phone || myForm.phone.length==0){
this.$tip.alert('请输入手机号');
return false
}
if(!checkPhone.test(myForm.phone)){
this.$tip.alert('请输入正确的手机号');
return false
}
if(!checkEmail.test(myForm.email)){
this.$tip.alert('请输入正确的邮箱地址');
return false
}
this.myFormData.id = this.$store.getters.userid
if(this.switchC){
this.myFormData.sex=1
}else{
this.myFormData.sex=2
}
console.log('myform',this.myFormData)
this.$tip.loading();
this.$http.put('/sys/user/appEdit',this.myFormData).then(res=>{
console.log(res)
this.$tip.loaded();
if (res.data.success){
this.$tip.toast('提交成功')
this.$Router.replace({name:'userdetail'})
/* uni.navigateTo({
url: '/pages/user/userdetail'
}) */
}
}).catch(()=>{
this.$tip.loaded();
this.$tip.error('提交失败')
});
},
DateChange(e) {
this.myFormData.birthday = e.detail.value
},
SwitchC(e) {
this.switchC = e.detail.value
},
ChooseImage() {
var that=this;
uni.chooseImage({
count: 4, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: (res) => {
that.$http.upload(that.$config.apiUrl+that.uploadUrl, {
filePath: res.tempFilePaths[0],
name: 'file'
})
.then(res => {
that.myFormData.avatar=res.data.message;
})
.catch(err => {
that.$tip.error(err.data.message)
});
this.imgList = res.tempFilePaths
}
});
},
ViewImage(e) {
uni.previewImage({
urls: this.imgList,
current: e.currentTarget.dataset.url
});
},
DelImg(e) {
uni.showModal({
title: '召唤师',
content: '确定要删除这段回忆吗?',
cancelText: '再看看',
confirmText: '再见',
success: res => {
if (res.confirm) {
this.imgList.splice(e.currentTarget.dataset.index, 1)
}
}
})
}
}
}
</script>
<style>
.cu-form-group .title {
min-width: calc(4em + 15px);
}
</style>
<template>
<view class="bg-white">
<!-- <cu-custom bgColor="bg-gradual-blue" :isBack="true"><block slot="content">选择产线</block></cu-custom> -->
<cu-custom :isxzck="false" bgColor="bg-gradual-blue" >
<block slot="backText">返回</block>
<block slot="content">选择仓库</block>
</cu-custom>
<view class="cu-list menu" >
<view class="cu-item" v-for="(item,index) in gzxxInfor" :key="index" @tap="selectLine(item,index)">
<view class="content">
<text class="text-green">{{index+1}}.</text>
<text class="text-grey">{{item.name}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import Vue from 'vue'
import api from '@/api/api.js';
export default {
data() {
return {
gzxxInfor:[],
loadModal:false,
urls:{
"gzquery":"jcsj/common/ck/queryCkid"
},
cuIconList:[{
cxbm:"testcxbm",
cxmc:"产线1",
id:"1"
},
{
cxbm:"testcxbm",
cxmc:"产线2",
id:"2"
}],
selectedIndex:0
}
},
methods:{
apiGetgzxx(){
let _self=this;
api.postData(_self.urls.gzquery,{
}).then((resp) => {
if(resp.data.success){
_self.gzxxInfor=resp.data.data.records
}else{
this.$tip.alert(resp.data.message||"请求失败");
}
}).catch((err) => {
let msg = err.data.message || "请求出现错误,请稍后再试"
this.$tip.alert(msg);
}).finally(()=>{
})
},
gotoBackPage(){
this.$Router.replace('/pages/homepage/homepage')
},
nextTo(){
this.$Router.push({ path:'/pages/homepage/homepage', query:{}})
},
selectLine(item,index){
this.selectedIndex=index;
// 仓库id
console.log(item)
Vue.prototype.$ckid=item.id
Vue.prototype.$ckmc=item.name
if(this.$ckid!="")
{
this.nextTo();
}
},
},
onLoad() {
this.apiGetgzxx()
}
}
</script>
<style>
</style>
/*
Animation 微动画
基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
*/
/* css 滤镜 控制黑白底色gif的 */
.gif-black{
mix-blend-mode: screen;
}
.gif-white{
mix-blend-mode: multiply;
}
/* Animation css */
[class*=animation-] {
animation-duration: .5s;
animation-timing-function: ease-out;
animation-fill-mode: both
}
.animation-fade {
animation-name: fade;
animation-duration: .8s;
animation-timing-function: linear
}
.animation-scale-up {
animation-name: scale-up
}
.animation-scale-down {
animation-name: scale-down
}
.animation-slide-top {
animation-name: slide-top
}
.animation-slide-bottom {
animation-name: slide-bottom
}
.animation-slide-left {
animation-name: slide-left
}
.animation-slide-right {
animation-name: slide-right
}
.animation-shake {
animation-name: shake
}
.animation-reverse {
animation-direction: reverse
}
@keyframes fade {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@keyframes scale-up {
0% {
opacity: 0;
transform: scale(.2)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes scale-down {
0% {
opacity: 0;
transform: scale(1.8)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes slide-top {
0% {
opacity: 0;
transform: translateY(-100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes slide-bottom {
0% {
opacity: 0;
transform: translateY(100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes shake {
0%,
100% {
transform: translateX(0)
}
10% {
transform: translateX(-9px)
}
20% {
transform: translateX(8px)
}
30% {
transform: translateX(-7px)
}
40% {
transform: translateX(6px)
}
50% {
transform: translateX(-5px)
}
60% {
transform: translateX(4px)
}
70% {
transform: translateX(-3px)
}
80% {
transform: translateX(2px)
}
90% {
transform: translateX(-1px)
}
}
@keyframes slide-left {
0% {
opacity: 0;
transform: translateX(-100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}
@keyframes slide-right {
0% {
opacity: 0;
transform: translateX(100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}
\ No newline at end of file
<template>
<view>
<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
<view class="action" @tap="reWrite?Gopage(reWrite):BackPage()" v-if="isBack">
<text class="cuIcon-back"></text>
<slot name="backText"></slot>
</view>
<view class="content" :style="[{top:StatusBar + 'px'}]">
<slot name="content"></slot>
</view>
<view class="action">
<slot name="right"></slot>
</view>
<view v-if="isxzck" @tap="xzck()" class="action flex flex-wrap" >
<view class="tit-xzck">
选择仓库
</view>
<view class="tit-xzck">
{{this.$ckmc?"("+this.$ckmc+")":'(请选择)'}}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
StatusBar: this.StatusBar,
CustomBar: 70
};
},
name: 'cu-custom',
computed: {
style() {
var StatusBar= this.StatusBar;
var CustomBar= this.CustomBar;
var bgImage = this.bgImage;
var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
if (this.bgImage) {
style = `${style}background-image:url(${bgImage});`;
}
return style
}
},
props: {
isxzck: {
type: [Boolean, String],
default: false
},
// isxzck
bgColor: {
type: String,
default: ''
},
isBack: {
type: [Boolean, String],
default: false
},
bgImage: {
type: String,
default: ''
},
reWrite: {
type: [Boolean, String],
default: false
}
},
methods: {
xzck(){
this.$Router.replaceAll({name:'xzck'})
},
BackPage() {
uni.navigateBack({
delta: 1
});
},
Gopage(page){
this.$Router.replace({name:page})
}
}
}
</script>
<style scoped>
.tit-xzck{
width: 100%;height: 50%;line-height: 35px;text-align: center;
}
</style>
@keyframes cuIcon-spin {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.cuIconfont-spin {
-webkit-animation: cuIcon-spin 2s infinite linear;
animation: cuIcon-spin 2s infinite linear;
display: inline-block;
}
.cuIconfont-pulse {
-webkit-animation: cuIcon-spin 1s infinite steps(8);
animation: cuIcon-spin 1s infinite steps(8);
display: inline-block;
}
[class*="cuIcon-"] {
font-family: "cuIcon";
font-size: inherit;
font-style: normal;
}
@font-face {
font-family: "cuIcon";
src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831');
/* IE9*/
src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'),
/* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'),
/* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#cuIconfont') format('svg');
/* iOS 4.1- */
}
.cuIcon-appreciate:before {
content: "\e644";
}
.cuIcon-check:before {
content: "\e645";
}
.cuIcon-close:before {
content: "\e646";
}
.cuIcon-edit:before {
content: "\e649";
}
.cuIcon-emoji:before {
content: "\e64a";
}
.cuIcon-favorfill:before {
content: "\e64b";
}
.cuIcon-favor:before {
content: "\e64c";
}
.cuIcon-loading:before {
content: "\e64f";
}
.cuIcon-locationfill:before {
content: "\e650";
}
.cuIcon-location:before {
content: "\e651";
}
.cuIcon-phone:before {
content: "\e652";
}
.cuIcon-roundcheckfill:before {
content: "\e656";
}
.cuIcon-roundcheck:before {
content: "\e657";
}
.cuIcon-roundclosefill:before {
content: "\e658";
}
.cuIcon-roundclose:before {
content: "\e659";
}
.cuIcon-roundrightfill:before {
content: "\e65a";
}
.cuIcon-roundright:before {
content: "\e65b";
}
.cuIcon-search:before {
content: "\e65c";
}
.cuIcon-taxi:before {
content: "\e65d";
}
.cuIcon-timefill:before {
content: "\e65e";
}
.cuIcon-time:before {
content: "\e65f";
}
.cuIcon-unfold:before {
content: "\e661";
}
.cuIcon-warnfill:before {
content: "\e662";
}
.cuIcon-warn:before {
content: "\e663";
}
.cuIcon-camerafill:before {
content: "\e664";
}
.cuIcon-camera:before {
content: "\e665";
}
.cuIcon-commentfill:before {
content: "\e666";
}
.cuIcon-comment:before {
content: "\e667";
}
.cuIcon-likefill:before {
content: "\e668";
}
.cuIcon-like:before {
content: "\e669";
}
.cuIcon-notificationfill:before {
content: "\e66a";
}
.cuIcon-notification:before {
content: "\e66b";
}
.cuIcon-order:before {
content: "\e66c";
}
.cuIcon-samefill:before {
content: "\e66d";
}
.cuIcon-same:before {
content: "\e66e";
}
.cuIcon-deliver:before {
content: "\e671";
}
.cuIcon-evaluate:before {
content: "\e672";
}
.cuIcon-pay:before {
content: "\e673";
}
.cuIcon-send:before {
content: "\e675";
}
.cuIcon-shop:before {
content: "\e676";
}
.cuIcon-ticket:before {
content: "\e677";
}
.cuIcon-back:before {
content: "\e679";
}
.cuIcon-cascades:before {
content: "\e67c";
}
.cuIcon-discover:before {
content: "\e67e";
}
.cuIcon-list:before {
content: "\e682";
}
.cuIcon-more:before {
content: "\e684";
}
.cuIcon-scan:before {
content: "\e689";
}
.cuIcon-settings:before {
content: "\e68a";
}
.cuIcon-questionfill:before {
content: "\e690";
}
.cuIcon-question:before {
content: "\e691";
}
.cuIcon-shopfill:before {
content: "\e697";
}
.cuIcon-form:before {
content: "\e699";
}
.cuIcon-pic:before {
content: "\e69b";
}
.cuIcon-filter:before {
content: "\e69c";
}
.cuIcon-footprint:before {
content: "\e69d";
}
.cuIcon-top:before {
content: "\e69e";
}
.cuIcon-pulldown:before {
content: "\e69f";
}
.cuIcon-pullup:before {
content: "\e6a0";
}
.cuIcon-right:before {
content: "\e6a3";
}
.cuIcon-refresh:before {
content: "\e6a4";
}
.cuIcon-moreandroid:before {
content: "\e6a5";
}
.cuIcon-deletefill:before {
content: "\e6a6";
}
.cuIcon-refund:before {
content: "\e6ac";
}
.cuIcon-cart:before {
content: "\e6af";
}
.cuIcon-qrcode:before {
content: "\e6b0";
}
.cuIcon-remind:before {
content: "\e6b2";
}
.cuIcon-delete:before {
content: "\e6b4";
}
.cuIcon-profile:before {
content: "\e6b7";
}
.cuIcon-home:before {
content: "\e6b8";
}
.cuIcon-cartfill:before {
content: "\e6b9";
}
.cuIcon-discoverfill:before {
content: "\e6ba";
}
.cuIcon-homefill:before {
content: "\e6bb";
}
.cuIcon-message:before {
content: "\e6bc";
}
.cuIcon-addressbook:before {
content: "\e6bd";
}
.cuIcon-link:before {
content: "\e6bf";
}
.cuIcon-lock:before {
content: "\e6c0";
}
.cuIcon-unlock:before {
content: "\e6c2";
}
.cuIcon-vip:before {
content: "\e6c3";
}
.cuIcon-weibo:before {
content: "\e6c4";
}
.cuIcon-activity:before {
content: "\e6c5";
}
.cuIcon-friendaddfill:before {
content: "\e6c9";
}
.cuIcon-friendadd:before {
content: "\e6ca";
}
.cuIcon-friendfamous:before {
content: "\e6cb";
}
.cuIcon-friend:before {
content: "\e6cc";
}
.cuIcon-goods:before {
content: "\e6cd";
}
.cuIcon-selection:before {
content: "\e6ce";
}
.cuIcon-explore:before {
content: "\e6d2";
}
.cuIcon-present:before {
content: "\e6d3";
}
.cuIcon-squarecheckfill:before {
content: "\e6d4";
}
.cuIcon-square:before {
content: "\e6d5";
}
.cuIcon-squarecheck:before {
content: "\e6d6";
}
.cuIcon-round:before {
content: "\e6d7";
}
.cuIcon-roundaddfill:before {
content: "\e6d8";
}
.cuIcon-roundadd:before {
content: "\e6d9";
}
.cuIcon-add:before {
content: "\e6da";
}
.cuIcon-notificationforbidfill:before {
content: "\e6db";
}
.cuIcon-explorefill:before {
content: "\e6dd";
}
.cuIcon-fold:before {
content: "\e6de";
}
.cuIcon-game:before {
content: "\e6df";
}
.cuIcon-redpacket:before {
content: "\e6e0";
}
.cuIcon-selectionfill:before {
content: "\e6e1";
}
.cuIcon-similar:before {
content: "\e6e2";
}
.cuIcon-appreciatefill:before {
content: "\e6e3";
}
.cuIcon-infofill:before {
content: "\e6e4";
}
.cuIcon-info:before {
content: "\e6e5";
}
.cuIcon-forwardfill:before {
content: "\e6ea";
}
.cuIcon-forward:before {
content: "\e6eb";
}
.cuIcon-rechargefill:before {
content: "\e6ec";
}
.cuIcon-recharge:before {
content: "\e6ed";
}
.cuIcon-vipcard:before {
content: "\e6ee";
}
.cuIcon-voice:before {
content: "\e6ef";
}
.cuIcon-voicefill:before {
content: "\e6f0";
}
.cuIcon-friendfavor:before {
content: "\e6f1";
}
.cuIcon-wifi:before {
content: "\e6f2";
}
.cuIcon-share:before {
content: "\e6f3";
}
.cuIcon-wefill:before {
content: "\e6f4";
}
.cuIcon-we:before {
content: "\e6f5";
}
.cuIcon-lightauto:before {
content: "\e6f6";
}
.cuIcon-lightforbid:before {
content: "\e6f7";
}
.cuIcon-lightfill:before {
content: "\e6f8";
}
.cuIcon-camerarotate:before {
content: "\e6f9";
}
.cuIcon-light:before {
content: "\e6fa";
}
.cuIcon-barcode:before {
content: "\e6fb";
}
.cuIcon-flashlightclose:before {
content: "\e6fc";
}
.cuIcon-flashlightopen:before {
content: "\e6fd";
}
.cuIcon-searchlist:before {
content: "\e6fe";
}
.cuIcon-service:before {
content: "\e6ff";
}
.cuIcon-sort:before {
content: "\e700";
}
.cuIcon-down:before {
content: "\e703";
}
.cuIcon-mobile:before {
content: "\e704";
}
.cuIcon-mobilefill:before {
content: "\e705";
}
.cuIcon-copy:before {
content: "\e706";
}
.cuIcon-countdownfill:before {
content: "\e707";
}
.cuIcon-countdown:before {
content: "\e708";
}
.cuIcon-noticefill:before {
content: "\e709";
}
.cuIcon-notice:before {
content: "\e70a";
}
.cuIcon-upstagefill:before {
content: "\e70e";
}
.cuIcon-upstage:before {
content: "\e70f";
}
.cuIcon-babyfill:before {
content: "\e710";
}
.cuIcon-baby:before {
content: "\e711";
}
.cuIcon-brandfill:before {
content: "\e712";
}
.cuIcon-brand:before {
content: "\e713";
}
.cuIcon-choicenessfill:before {
content: "\e714";
}
.cuIcon-choiceness:before {
content: "\e715";
}
.cuIcon-clothesfill:before {
content: "\e716";
}
.cuIcon-clothes:before {
content: "\e717";
}
.cuIcon-creativefill:before {
content: "\e718";
}
.cuIcon-creative:before {
content: "\e719";
}
.cuIcon-female:before {
content: "\e71a";
}
.cuIcon-keyboard:before {
content: "\e71b";
}
.cuIcon-male:before {
content: "\e71c";
}
.cuIcon-newfill:before {
content: "\e71d";
}
.cuIcon-new:before {
content: "\e71e";
}
.cuIcon-pullleft:before {
content: "\e71f";
}
.cuIcon-pullright:before {
content: "\e720";
}
.cuIcon-rankfill:before {
content: "\e721";
}
.cuIcon-rank:before {
content: "\e722";
}
.cuIcon-bad:before {
content: "\e723";
}
.cuIcon-cameraadd:before {
content: "\e724";
}
.cuIcon-focus:before {
content: "\e725";
}
.cuIcon-friendfill:before {
content: "\e726";
}
.cuIcon-cameraaddfill:before {
content: "\e727";
}
.cuIcon-apps:before {
content: "\e729";
}
.cuIcon-paintfill:before {
content: "\e72a";
}
.cuIcon-paint:before {
content: "\e72b";
}
.cuIcon-picfill:before {
content: "\e72c";
}
.cuIcon-refresharrow:before {
content: "\e72d";
}
.cuIcon-colorlens:before {
content: "\e6e6";
}
.cuIcon-markfill:before {
content: "\e730";
}
.cuIcon-mark:before {
content: "\e731";
}
.cuIcon-presentfill:before {
content: "\e732";
}
.cuIcon-repeal:before {
content: "\e733";
}
.cuIcon-album:before {
content: "\e734";
}
.cuIcon-peoplefill:before {
content: "\e735";
}
.cuIcon-people:before {
content: "\e736";
}
.cuIcon-servicefill:before {
content: "\e737";
}
.cuIcon-repair:before {
content: "\e738";
}
.cuIcon-file:before {
content: "\e739";
}
.cuIcon-repairfill:before {
content: "\e73a";
}
.cuIcon-taoxiaopu:before {
content: "\e73b";
}
.cuIcon-weixin:before {
content: "\e612";
}
.cuIcon-attentionfill:before {
content: "\e73c";
}
.cuIcon-attention:before {
content: "\e73d";
}
.cuIcon-commandfill:before {
content: "\e73e";
}
.cuIcon-command:before {
content: "\e73f";
}
.cuIcon-communityfill:before {
content: "\e740";
}
.cuIcon-community:before {
content: "\e741";
}
.cuIcon-read:before {
content: "\e742";
}
.cuIcon-calendar:before {
content: "\e74a";
}
.cuIcon-cut:before {
content: "\e74b";
}
.cuIcon-magic:before {
content: "\e74c";
}
.cuIcon-backwardfill:before {
content: "\e74d";
}
.cuIcon-playfill:before {
content: "\e74f";
}
.cuIcon-stop:before {
content: "\e750";
}
.cuIcon-tagfill:before {
content: "\e751";
}
.cuIcon-tag:before {
content: "\e752";
}
.cuIcon-group:before {
content: "\e753";
}
.cuIcon-all:before {
content: "\e755";
}
.cuIcon-backdelete:before {
content: "\e756";
}
.cuIcon-hotfill:before {
content: "\e757";
}
.cuIcon-hot:before {
content: "\e758";
}
.cuIcon-post:before {
content: "\e759";
}
.cuIcon-radiobox:before {
content: "\e75b";
}
.cuIcon-rounddown:before {
content: "\e75c";
}
.cuIcon-upload:before {
content: "\e75d";
}
.cuIcon-writefill:before {
content: "\e760";
}
.cuIcon-write:before {
content: "\e761";
}
.cuIcon-radioboxfill:before {
content: "\e763";
}
.cuIcon-punch:before {
content: "\e764";
}
.cuIcon-shake:before {
content: "\e765";
}
.cuIcon-move:before {
content: "\e768";
}
.cuIcon-safe:before {
content: "\e769";
}
.cuIcon-activityfill:before {
content: "\e775";
}
.cuIcon-crownfill:before {
content: "\e776";
}
.cuIcon-crown:before {
content: "\e777";
}
.cuIcon-goodsfill:before {
content: "\e778";
}
.cuIcon-messagefill:before {
content: "\e779";
}
.cuIcon-profilefill:before {
content: "\e77a";
}
.cuIcon-sound:before {
content: "\e77b";
}
.cuIcon-sponsorfill:before {
content: "\e77c";
}
.cuIcon-sponsor:before {
content: "\e77d";
}
.cuIcon-upblock:before {
content: "\e77e";
}
.cuIcon-weblock:before {
content: "\e77f";
}
.cuIcon-weunblock:before {
content: "\e780";
}
.cuIcon-my:before {
content: "\e78b";
}
.cuIcon-myfill:before {
content: "\e78c";
}
.cuIcon-emojifill:before {
content: "\e78d";
}
.cuIcon-emojiflashfill:before {
content: "\e78e";
}
.cuIcon-flashbuyfill:before {
content: "\e78f";
}
.cuIcon-text:before {
content: "\e791";
}
.cuIcon-goodsfavor:before {
content: "\e794";
}
.cuIcon-musicfill:before {
content: "\e795";
}
.cuIcon-musicforbidfill:before {
content: "\e796";
}
.cuIcon-card:before {
content: "\e624";
}
.cuIcon-triangledownfill:before {
content: "\e79b";
}
.cuIcon-triangleupfill:before {
content: "\e79c";
}
.cuIcon-roundleftfill-copy:before {
content: "\e79e";
}
.cuIcon-font:before {
content: "\e76a";
}
.cuIcon-title:before {
content: "\e82f";
}
.cuIcon-recordfill:before {
content: "\e7a4";
}
.cuIcon-record:before {
content: "\e7a6";
}
.cuIcon-cardboardfill:before {
content: "\e7a9";
}
.cuIcon-cardboard:before {
content: "\e7aa";
}
.cuIcon-formfill:before {
content: "\e7ab";
}
.cuIcon-coin:before {
content: "\e7ac";
}
.cuIcon-cardboardforbid:before {
content: "\e7af";
}
.cuIcon-circlefill:before {
content: "\e7b0";
}
.cuIcon-circle:before {
content: "\e7b1";
}
.cuIcon-attentionforbid:before {
content: "\e7b2";
}
.cuIcon-attentionforbidfill:before {
content: "\e7b3";
}
.cuIcon-attentionfavorfill:before {
content: "\e7b4";
}
.cuIcon-attentionfavor:before {
content: "\e7b5";
}
.cuIcon-titles:before {
content: "\e701";
}
.cuIcon-icloading:before {
content: "\e67a";
}
.cuIcon-full:before {
content: "\e7bc";
}
.cuIcon-mail:before {
content: "\e7bd";
}
.cuIcon-peoplelist:before {
content: "\e7be";
}
.cuIcon-goodsnewfill:before {
content: "\e7bf";
}
.cuIcon-goodsnew:before {
content: "\e7c0";
}
.cuIcon-medalfill:before {
content: "\e7c1";
}
.cuIcon-medal:before {
content: "\e7c2";
}
.cuIcon-newsfill:before {
content: "\e7c3";
}
.cuIcon-newshotfill:before {
content: "\e7c4";
}
.cuIcon-newshot:before {
content: "\e7c5";
}
.cuIcon-news:before {
content: "\e7c6";
}
.cuIcon-videofill:before {
content: "\e7c7";
}
.cuIcon-video:before {
content: "\e7c8";
}
.cuIcon-exit:before {
content: "\e7cb";
}
.cuIcon-skinfill:before {
content: "\e7cc";
}
.cuIcon-skin:before {
content: "\e7cd";
}
.cuIcon-moneybagfill:before {
content: "\e7ce";
}
.cuIcon-usefullfill:before {
content: "\e7cf";
}
.cuIcon-usefull:before {
content: "\e7d0";
}
.cuIcon-moneybag:before {
content: "\e7d1";
}
.cuIcon-redpacket_fill:before {
content: "\e7d3";
}
.cuIcon-subscription:before {
content: "\e7d4";
}
.cuIcon-loading1:before {
content: "\e633";
}
.cuIcon-github:before {
content: "\e692";
}
.cuIcon-global:before {
content: "\e7eb";
}
.cuIcon-settingsfill:before {
content: "\e6ab";
}
.cuIcon-back_android:before {
content: "\e7ed";
}
.cuIcon-expressman:before {
content: "\e7ef";
}
.cuIcon-evaluate_fill:before {
content: "\e7f0";
}
.cuIcon-group_fill:before {
content: "\e7f5";
}
.cuIcon-play_forward_fill:before {
content: "\e7f6";
}
.cuIcon-deliver_fill:before {
content: "\e7f7";
}
.cuIcon-notice_forbid_fill:before {
content: "\e7f8";
}
.cuIcon-fork:before {
content: "\e60c";
}
.cuIcon-pick:before {
content: "\e7fa";
}
.cuIcon-wenzi:before {
content: "\e6a7";
}
.cuIcon-ellipse:before {
content: "\e600";
}
.cuIcon-qr_code:before {
content: "\e61b";
}
.cuIcon-dianhua:before {
content: "\e64d";
}
.cuIcon-cuIcon:before {
content: "\e602";
}
.cuIcon-loading2:before {
content: "\e7f1";
}
.cuIcon-btn:before {
content: "\e601";
}
/*
ColorUi for uniApp v2.1.6 | by 文晓港 2019-05-31 10:44:24
仅供学习交流,如作它用所承受的法律责任一概与作者无关
*使用ColorUi开发扩展与插件时,请注明基于ColorUi开发
(QQ交流群:240787041)
*/
/* ==================
初始化
==================== */
body {
background-color: #f1f1f1;
font-size: 28upx;
color: #333333;
font-family: Helvetica Neue, Helvetica, sans-serif;
}
view,
scroll-view,
swiper,
button,
input,
textarea,
label,
navigator,
image {
box-sizing: border-box;
}
.round {
border-radius: 5000upx;
}
.radius {
border-radius: 6upx;
}
/* ==================
图片
==================== */
image {
max-width: 100%;
display: inline-block;
position: relative;
z-index: 0;
}
image.loading::before {
content: "";
background-color: #f5f5f5;
display: block;
position: absolute;
width: 100%;
height: 100%;
z-index: -2;
}
image.loading::after {
content: "\e7f1";
font-family: "cuIcon";
position: absolute;
top: 0;
left: 0;
width: 32upx;
height: 32upx;
line-height: 32upx;
right: 0;
bottom: 0;
z-index: -1;
font-size: 32upx;
margin: auto;
color: #ccc;
-webkit-animation: cuIcon-spin 2s infinite linear;
animation: cuIcon-spin 2s infinite linear;
display: block;
}
.response {
width: 100%;
}
/* ==================
开关
==================== */
switch,
checkbox,
radio {
position: relative;
}
switch::after,
switch::before {
font-family: "cuIcon";
content: "\e645";
position: absolute;
color: #ffffff !important;
top: 0%;
left: 0upx;
font-size: 26upx;
line-height: 26px;
width: 50%;
text-align: center;
pointer-events: none;
transform: scale(0, 0);
transition: all 0.3s ease-in-out 0s;
z-index: 9;
bottom: 0;
height: 26px;
margin: auto;
}
switch::before {
content: "\e646";
right: 0;
transform: scale(1, 1);
left: auto;
}
switch[checked]::after,
switch.checked::after {
transform: scale(1, 1);
}
switch[checked]::before,
switch.checked::before {
transform: scale(0, 0);
}
/* #ifndef MP-ALIPAY */
radio::before,
checkbox::before {
font-family: "cuIcon";
content: "\e645";
position: absolute;
color: #ffffff !important;
top: 50%;
margin-top: -8px;
right: 0px;
font-size: 32upx;
line-height: 16px;
pointer-events: none;
transform: scale(1, 1);
transition: all 0.3s ease-in-out 0s;
z-index: 9;
}
radio .wx-radio-input,
checkbox .wx-checkbox-input,
radio .uni-radio-input,
checkbox .uni-checkbox-input {
margin: 0;
width: 18px;
height: 18px;
}
checkbox.round .wx-checkbox-input,
checkbox.round .uni-checkbox-input {
border-radius: 100upx;
}
/* #endif */
switch[checked]::before {
transform: scale(0, 0);
}
switch .wx-switch-input,
switch .uni-switch-input {
border: none;
padding: 0 24px;
width: 48px;
height: 26px;
margin: 0;
border-radius: 100upx;
}
switch .wx-switch-input:not([class*="bg-"]),
switch .uni-switch-input:not([class*="bg-"]) {
background: #8799a3 !important;
}
switch .wx-switch-input::after,
switch .uni-switch-input::after {
margin: auto;
width: 26px;
height: 26px;
border-radius: 100upx;
left: 0upx;
top: 0upx;
bottom: 0upx;
position: absolute;
transform: scale(0.9, 0.9);
transition: all 0.1s ease-in-out 0s;
}
switch .wx-switch-input.wx-switch-input-checked::after,
switch .uni-switch-input.uni-switch-input-checked::after {
margin: auto;
left: 22px;
box-shadow: none;
transform: scale(0.9, 0.9);
}
radio-group {
display: inline-block;
}
switch.radius .wx-switch-input::after,
switch.radius .wx-switch-input,
switch.radius .wx-switch-input::before,
switch.radius .uni-switch-input::after,
switch.radius .uni-switch-input,
switch.radius .uni-switch-input::before {
border-radius: 10upx;
}
switch .wx-switch-input::before,
radio.radio::before,
checkbox .wx-checkbox-input::before,
radio .wx-radio-input::before,
switch .uni-switch-input::before,
radio.radio::before,
checkbox .uni-checkbox-input::before,
radio .uni-radio-input::before {
display: none;
}
radio.radio[checked]::after,
radio.radio .uni-radio-input-checked::after {
content: "";
background-color: transparent;
display: block;
position: absolute;
width: 8px;
height: 8px;
z-index: 999;
top: 0upx;
left: 0upx;
right: 0;
bottom: 0;
margin: auto;
border-radius: 200upx;
/* #ifndef MP */
border: 7px solid #ffffff !important;
/* #endif */
/* #ifdef MP */
border: 8px solid #ffffff !important;
/* #endif */
}
.switch-sex::after {
content: "\e71c";
}
.switch-sex::before {
content: "\e71a";
}
.switch-sex .wx-switch-input,
.switch-sex .uni-switch-input {
background: #e54d42 !important;
border-color: #e54d42 !important;
}
.switch-sex[checked] .wx-switch-input,
.switch-sex.checked .uni-switch-input {
background: #0081ff !important;
border-color: #0081ff !important;
}
switch.red[checked] .wx-switch-input.wx-switch-input-checked,
checkbox.red[checked] .wx-checkbox-input,
radio.red[checked] .wx-radio-input,
switch.red.checked .uni-switch-input.uni-switch-input-checked,
checkbox.red.checked .uni-checkbox-input,
radio.red.checked .uni-radio-input {
background-color: #e54d42 !important;
border-color: #e54d42 !important;
color: #ffffff !important;
}
switch.orange[checked] .wx-switch-input,
checkbox.orange[checked] .wx-checkbox-input,
radio.orange[checked] .wx-radio-input,
switch.orange.checked .uni-switch-input,
checkbox.orange.checked .uni-checkbox-input,
radio.orange.checked .uni-radio-input {
background-color: #f37b1d !important;
border-color: #f37b1d !important;
color: #ffffff !important;
}
switch.yellow[checked] .wx-switch-input,
checkbox.yellow[checked] .wx-checkbox-input,
radio.yellow[checked] .wx-radio-input,
switch.yellow.checked .uni-switch-input,
checkbox.yellow.checked .uni-checkbox-input,
radio.yellow.checked .uni-radio-input {
background-color: #fbbd08 !important;
border-color: #fbbd08 !important;
color: #333333 !important;
}
switch.olive[checked] .wx-switch-input,
checkbox.olive[checked] .wx-checkbox-input,
radio.olive[checked] .wx-radio-input,
switch.olive.checked .uni-switch-input,
checkbox.olive.checked .uni-checkbox-input,
radio.olive.checked .uni-radio-input {
background-color: #8dc63f !important;
border-color: #8dc63f !important;
color: #ffffff !important;
}
switch.green[checked] .wx-switch-input,
switch[checked] .wx-switch-input,
checkbox.green[checked] .wx-checkbox-input,
checkbox[checked] .wx-checkbox-input,
radio.green[checked] .wx-radio-input,
radio[checked] .wx-radio-input,
switch.green.checked .uni-switch-input,
switch.checked .uni-switch-input,
checkbox.green.checked .uni-checkbox-input,
checkbox.checked .uni-checkbox-input,
radio.green.checked .uni-radio-input,
radio.checked .uni-radio-input {
background-color: #39b54a !important;
border-color: #39b54a !important;
color: #ffffff !important;
border-color: #39B54A !important;
}
switch.cyan[checked] .wx-switch-input,
checkbox.cyan[checked] .wx-checkbox-input,
radio.cyan[checked] .wx-radio-input,
switch.cyan.checked .uni-switch-input,
checkbox.cyan.checked .uni-checkbox-input,
radio.cyan.checked .uni-radio-input {
background-color: #1cbbb4 !important;
border-color: #1cbbb4 !important;
color: #ffffff !important;
}
switch.blue[checked] .wx-switch-input,
checkbox.blue[checked] .wx-checkbox-input,
radio.blue[checked] .wx-radio-input,
switch.blue.checked .uni-switch-input,
checkbox.blue.checked .uni-checkbox-input,
radio.blue.checked .uni-radio-input {
background-color: #0081ff !important;
border-color: #0081ff !important;
color: #ffffff !important;
}
switch.purple[checked] .wx-switch-input,
checkbox.purple[checked] .wx-checkbox-input,
radio.purple[checked] .wx-radio-input,
switch.purple.checked .uni-switch-input,
checkbox.purple.checked .uni-checkbox-input,
radio.purple.checked .uni-radio-input {
background-color: #6739b6 !important;
border-color: #6739b6 !important;
color: #ffffff !important;
}
switch.mauve[checked] .wx-switch-input,
checkbox.mauve[checked] .wx-checkbox-input,
radio.mauve[checked] .wx-radio-input,
switch.mauve.checked .uni-switch-input,
checkbox.mauve.checked .uni-checkbox-input,
radio.mauve.checked .uni-radio-input {
background-color: #9c26b0 !important;
border-color: #9c26b0 !important;
color: #ffffff !important;
}
switch.pink[checked] .wx-switch-input,
checkbox.pink[checked] .wx-checkbox-input,
radio.pink[checked] .wx-radio-input,
switch.pink.checked .uni-switch-input,
checkbox.pink.checked .uni-checkbox-input,
radio.pink.checked .uni-radio-input {
background-color: #e03997 !important;
border-color: #e03997 !important;
color: #ffffff !important;
}
switch.brown[checked] .wx-switch-input,
checkbox.brown[checked] .wx-checkbox-input,
radio.brown[checked] .wx-radio-input,
switch.brown.checked .uni-switch-input,
checkbox.brown.checked .uni-checkbox-input,
radio.brown.checked .uni-radio-input {
background-color: #a5673f !important;
border-color: #a5673f !important;
color: #ffffff !important;
}
switch.grey[checked] .wx-switch-input,
checkbox.grey[checked] .wx-checkbox-input,
radio.grey[checked] .wx-radio-input,
switch.grey.checked .uni-switch-input,
checkbox.grey.checked .uni-checkbox-input,
radio.grey.checked .uni-radio-input {
background-color: #8799a3 !important;
border-color: #8799a3 !important;
color: #ffffff !important;
}
switch.gray[checked] .wx-switch-input,
checkbox.gray[checked] .wx-checkbox-input,
radio.gray[checked] .wx-radio-input,
switch.gray.checked .uni-switch-input,
checkbox.gray.checked .uni-checkbox-input,
radio.gray.checked .uni-radio-input {
background-color: #f0f0f0 !important;
border-color: #f0f0f0 !important;
color: #333333 !important;
}
switch.black[checked] .wx-switch-input,
checkbox.black[checked] .wx-checkbox-input,
radio.black[checked] .wx-radio-input,
switch.black.checked .uni-switch-input,
checkbox.black.checked .uni-checkbox-input,
radio.black.checked .uni-radio-input {
background-color: #333333 !important;
border-color: #333333 !important;
color: #ffffff !important;
}
switch.white[checked] .wx-switch-input,
checkbox.white[checked] .wx-checkbox-input,
radio.white[checked] .wx-radio-input,
switch.white.checked .uni-switch-input,
checkbox.white.checked .uni-checkbox-input,
radio.white.checked .uni-radio-input {
background-color: #ffffff !important;
border-color: #ffffff !important;
color: #333333 !important;
}
/* ==================
边框
==================== */
/* -- 实线 -- */
.solid,
.solid-top,
.solid-right,
.solid-bottom,
.solid-left,
.solids,
.solids-top,
.solids-right,
.solids-bottom,
.solids-left,
.dashed,
.dashed-top,
.dashed-right,
.dashed-bottom,
.dashed-left {
position: relative;
}
.solid::after,
.solid-top::after,
.solid-right::after,
.solid-bottom::after,
.solid-left::after,
.solids::after,
.solids-top::after,
.solids-right::after,
.solids-bottom::after,
.solids-left::after,
.dashed::after,
.dashed-top::after,
.dashed-right::after,
.dashed-bottom::after,
.dashed-left::after {
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border-radius: inherit;
transform: scale(0.5);
transform-origin: 0 0;
pointer-events: none;
box-sizing: border-box;
}
.solid::after {
border: 1upx solid rgba(0, 0, 0, 0.1);
}
.solid-top::after {
border-top: 1upx solid rgba(0, 0, 0, 0.1);
}
.solid-right::after {
border-right: 1upx solid rgba(0, 0, 0, 0.1);
}
.solid-bottom::after {
border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
}
.solid-left::after {
border-left: 1upx solid rgba(0, 0, 0, 0.1);
}
.solids::after {
border: 8upx solid #eee;
}
.solids-top::after {
border-top: 8upx solid #eee;
}
.solids-right::after {
border-right: 8upx solid #eee;
}
.solids-bottom::after {
border-bottom: 8upx solid #eee;
}
.solids-left::after {
border-left: 8upx solid #eee;
}
/* -- 虚线 -- */
.dashed::after {
border: 1upx dashed #ddd;
}
.dashed-top::after {
border-top: 1upx dashed #ddd;
}
.dashed-right::after {
border-right: 1upx dashed #ddd;
}
.dashed-bottom::after {
border-bottom: 1upx dashed #ddd;
}
.dashed-left::after {
border-left: 1upx dashed #ddd;
}
/* -- 阴影 -- */
.shadow[class*='white'] {
--ShadowSize: 0 1upx 6upx;
}
.shadow-lg {
--ShadowSize: 0upx 40upx 100upx 0upx;
}
.shadow-warp {
position: relative;
box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
}
.shadow-warp:before,
.shadow-warp:after {
position: absolute;
content: "";
top: 20upx;
bottom: 30upx;
left: 20upx;
width: 50%;
box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
transform: rotate(-3deg);
z-index: -1;
}
.shadow-warp:after {
right: 20upx;
left: auto;
transform: rotate(3deg);
}
.shadow-blur {
position: relative;
}
.shadow-blur::before {
content: "";
display: block;
background: inherit;
filter: blur(10upx);
position: absolute;
width: 100%;
height: 100%;
top: 10upx;
left: 10upx;
z-index: -1;
opacity: 0.4;
transform-origin: 0 0;
border-radius: inherit;
transform: scale(1, 1);
}
/* ==================
按钮
==================== */
.cu-btn {
position: relative;
border: 0upx;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 30upx;
font-size: 28upx;
height: 64upx;
line-height: 1;
text-align: center;
text-decoration: none;
overflow: visible;
margin-left: initial;
transform: translate(0upx, 0upx);
margin-right: initial;
}
.cu-btn::after {
display: none;
}
.cu-btn:not([class*="bg-"]) {
background-color: #f0f0f0;
}
.cu-btn[class*="line"] {
background-color: transparent;
}
.cu-btn[class*="line"]::after {
content: " ";
display: block;
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border: 1upx solid currentColor;
transform: scale(0.5);
transform-origin: 0 0;
box-sizing: border-box;
border-radius: 12upx;
z-index: 1;
pointer-events: none;
}
.cu-btn.round[class*="line"]::after {
border-radius: 1000upx;
}
.cu-btn[class*="lines"]::after {
border: 6upx solid currentColor;
}
.cu-btn[class*="bg-"]::after {
display: none;
}
.cu-btn.sm {
padding: 0 20upx;
font-size: 20upx;
height: 48upx;
}
.cu-btn.lg {
padding: 0 40upx;
font-size: 32upx;
height: 80upx;
}
.cu-btn.cuIcon.sm {
width: 48upx;
height: 48upx;
}
.cu-btn.cuIcon {
width: 64upx;
height: 64upx;
border-radius: 500upx;
padding: 0;
}
button.cuIcon.lg {
width: 80upx;
height: 80upx;
}
.cu-btn.shadow-blur::before {
top: 4upx;
left: 4upx;
filter: blur(6upx);
opacity: 0.6;
}
.cu-btn.button-hover {
transform: translate(1upx, 1upx);
}
.block {
display: block;
}
.cu-btn.block {
display: flex;
}
.cu-btn[disabled] {
opacity: 0.6;
color: #ffffff;
}
/* ==================
徽章
==================== */
.cu-tag {
font-size: 24upx;
vertical-align: middle;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0upx 16upx;
height: 48upx;
font-family: Helvetica Neue, Helvetica, sans-serif;
white-space: nowrap;
}
.cu-tag:not([class*="bg"]):not([class*="line"]) {
background-color: #f1f1f1;
}
.cu-tag[class*="line-"]::after {
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border: 1upx solid currentColor;
transform: scale(0.5);
transform-origin: 0 0;
box-sizing: border-box;
border-radius: inherit;
z-index: 1;
pointer-events: none;
}
.cu-tag.radius[class*="line"]::after {
border-radius: 12upx;
}
.cu-tag.round[class*="line"]::after {
border-radius: 1000upx;
}
.cu-tag[class*="line-"]::after {
border-radius: 0;
}
.cu-tag+.cu-tag {
margin-left: 10upx;
}
.cu-tag.sm {
font-size: 20upx;
padding: 0upx 12upx;
height: 32upx;
}
.cu-capsule {
display: inline-flex;
vertical-align: middle;
}
.cu-capsule+.cu-capsule {
margin-left: 10upx;
}
.cu-capsule .cu-tag {
margin: 0;
}
.cu-capsule .cu-tag[class*="line-"]:last-child::after {
border-left: 0upx solid transparent;
}
.cu-capsule .cu-tag[class*="line-"]:first-child::after {
border-right: 0upx solid transparent;
}
.cu-capsule.radius .cu-tag:first-child {
border-top-left-radius: 6upx;
border-bottom-left-radius: 6upx;
}
.cu-capsule.radius .cu-tag:last-child::after,
.cu-capsule.radius .cu-tag[class*="line-"] {
border-top-right-radius: 12upx;
border-bottom-right-radius: 12upx;
}
.cu-capsule.round .cu-tag:first-child {
border-top-left-radius: 200upx;
border-bottom-left-radius: 200upx;
text-indent: 4upx;
}
.cu-capsule.round .cu-tag:last-child::after,
.cu-capsule.round .cu-tag:last-child {
border-top-right-radius: 200upx;
border-bottom-right-radius: 200upx;
text-indent: -4upx;
}
.cu-tag.badge {
border-radius: 200upx;
position: absolute;
top: -10upx;
right: -10upx;
font-size: 20upx;
padding: 0upx 10upx;
height: 28upx;
color: #ffffff;
}
.cu-tag.badge:not([class*="bg-"]) {
background-color: #dd514c;
}
.cu-tag:empty:not([class*="cuIcon-"]) {
padding: 0upx;
width: 16upx;
height: 16upx;
top: -4upx;
right: -4upx;
}
.cu-tag[class*="cuIcon-"] {
width: 32upx;
height: 32upx;
top: -4upx;
right: -4upx;
}
/* ==================
头像
==================== */
.cu-avatar {
font-variant: small-caps;
margin: 0;
padding: 0;
display: inline-flex;
text-align: center;
justify-content: center;
align-items: center;
background-color: #ccc;
color: #ffffff;
white-space: nowrap;
position: relative;
width: 64upx;
height: 64upx;
background-size: cover;
background-position: center;
vertical-align: middle;
font-size: 1.5em;
}
.cu-avatar.sm {
width: 48upx;
height: 48upx;
font-size: 1em;
}
.cu-avatar.lg {
width: 56upx;
height: 56upx;
font-size: 2em;
}
.cu-avatar.xl {
width: 128upx;
height: 128upx;
font-size: 2.5em;
}
.cu-avatar .avatar-text {
font-size: 0.4em;
}
.cu-avatar-group {
direction: rtl;
unicode-bidi: bidi-override;
padding: 0 10upx 0 40upx;
display: inline-block;
}
.cu-avatar-group .cu-avatar {
margin-left: -30upx;
border: 4upx solid #f1f1f1;
vertical-align: middle;
}
.cu-avatar-group .cu-avatar.sm {
margin-left: -20upx;
border: 1upx solid #f1f1f1;
}
/* ==================
进度条
==================== */
.cu-progress {
overflow: hidden;
height: 28upx;
background-color: #ebeef5;
display: inline-flex;
align-items: center;
width: 100%;
}
.cu-progress+view,
.cu-progress+text {
line-height: 1;
}
.cu-progress.xs {
height: 10upx;
}
.cu-progress.sm {
height: 20upx;
}
.cu-progress view {
width: 0;
height: 100%;
align-items: center;
display: flex;
justify-items: flex-end;
justify-content: space-around;
font-size: 20upx;
color: #ffffff;
transition: width 0.6s ease;
}
.cu-progress text {
align-items: center;
display: flex;
font-size: 20upx;
color: #333333;
text-indent: 10upx;
}
.cu-progress.text-progress {
padding-right: 60upx;
}
.cu-progress.striped view {
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 72upx 72upx;
}
.cu-progress.active view {
animation: progress-stripes 2s linear infinite;
}
@keyframes progress-stripes {
from {
background-position: 72upx 0;
}
to {
background-position: 0 0;
}
}
/* ==================
加载
==================== */
.cu-load {
display: block;
line-height: 3em;
text-align: center;
}
.cu-load::before {
font-family: "cuIcon";
display: inline-block;
margin-right: 6upx;
}
.cu-load.loading::before {
content: "\e67a";
animation: cuIcon-spin 2s infinite linear;
}
.cu-load.loading::after {
content: "加载中...";
}
.cu-load.over::before {
content: "\e64a";
}
.cu-load.over::after {
content: "没有更多了";
}
.cu-load.erro::before {
content: "\e658";
}
.cu-load.erro::after {
content: "加载失败";
}
.cu-load.load-cuIcon::before {
font-size: 32upx;
}
.cu-load.load-cuIcon::after {
display: none;
}
.cu-load.load-cuIcon.over {
display: none;
}
.cu-load.load-modal {
position: fixed;
top: 0;
right: 0;
bottom: 140upx;
left: 0;
margin: auto;
width: 260upx;
height: 260upx;
background-color: #ffffff;
border-radius: 10upx;
box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
font-size: 28upx;
z-index: 9999;
line-height: 2.4em;
}
.cu-load.load-modal [class*="cuIcon-"] {
font-size: 60upx;
}
.cu-load.load-modal image {
width: 70upx;
height: 70upx;
}
.cu-load.load-modal::after {
content: "";
position: absolute;
background-color: #ffffff;
border-radius: 50%;
width: 200upx;
height: 200upx;
font-size: 10px;
border-top: 6upx solid rgba(0, 0, 0, 0.05);
border-right: 6upx solid rgba(0, 0, 0, 0.05);
border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
border-left: 6upx solid #f37b1d;
animation: cuIcon-spin 1s infinite linear;
z-index: -1;
}
.load-progress {
pointer-events: none;
top: 0;
position: fixed;
width: 100%;
left: 0;
z-index: 2000;
}
.load-progress.hide {
display: none;
}
.load-progress .load-progress-bar {
position: relative;
width: 100%;
height: 4upx;
overflow: hidden;
transition: all 200ms ease 0s;
}
.load-progress .load-progress-spinner {
position: absolute;
top: 10upx;
right: 10upx;
z-index: 2000;
display: block;
}
.load-progress .load-progress-spinner::after {
content: "";
display: block;
width: 24upx;
height: 24upx;
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: solid 4upx transparent;
border-top-color: inherit;
border-left-color: inherit;
border-radius: 50%;
-webkit-animation: load-progress-spinner 0.4s linear infinite;
animation: load-progress-spinner 0.4s linear infinite;
}
@-webkit-keyframes load-progress-spinner {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load-progress-spinner {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/* ==================
列表
==================== */
.grayscale {
filter: grayscale(1);
}
.cu-list+.cu-list {
margin-top: 30upx
}
.cu-list>.cu-item {
transition: all .6s ease-in-out 0s;
transform: translateX(0upx)
}
.cu-list>.cu-item.move-cur {
transform: translateX(-260upx)
}
.cu-list>.cu-item .move {
position: absolute;
right: 0;
display: flex;
width: 260upx;
height: 100%;
transform: translateX(100%)
}
.cu-list>.cu-item .move view {
display: flex;
flex: 1;
justify-content: center;
align-items: center
}
.cu-list.menu-avatar {
overflow: hidden;
}
.cu-list.menu-avatar>.cu-item {
position: relative;
display: flex;
padding-right: 10upx;
height: 140upx;
background-color: #ffffff;
justify-content: flex-end;
align-items: center
}
.cu-list.menu-avatar>.cu-item>.cu-avatar {
position: absolute;
left: 30upx
}
.cu-list.menu-avatar>.cu-item .flex .text-cut {
max-width: 510upx
}
.cu-list.menu-avatar>.cu-item .content {
position: absolute;
left: 146upx;
width: calc(100% - 96upx - 60upx - 120upx - 20upx);
line-height: 1.6em;
}
.cu-list.menu-avatar>.cu-item .content.flex-sub {
width: calc(100% - 96upx - 60upx - 20upx);
}
.cu-list.menu-avatar>.cu-item .content>view:first-child {
font-size: 30upx;
display: flex;
align-items: center
}
.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
display: inline-block;
margin-left: 10upx;
height: 28upx;
font-size: 16upx;
line-height: 32upx
}
.cu-list.menu-avatar>.cu-item .action {
width: 100upx;
text-align: center
}
.cu-list.menu-avatar>.cu-item .action view+view {
margin-top: 10upx
}
.cu-list.menu-avatar.comment>.cu-item .content {
position: relative;
left: 0;
width: auto;
flex: 1;
}
.cu-list.menu-avatar.comment>.cu-item {
padding: 30upx 30upx 30upx 120upx;
height: auto
}
.cu-list.menu-avatar.comment .cu-avatar {
align-self: flex-start
}
.cu-list.menu>.cu-item {
position: relative;
display: flex;
padding: 0 30upx;
min-height: 100upx;
background-color: #ffffff;
justify-content: space-between;
align-items: center
}
.cu-list.menu>.cu-item:last-child:after {
border: none
}
.cu-list.menu-avatar>.cu-item:after,
.cu-list.menu>.cu-item:after {
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
width: 200%;
height: 200%;
border-bottom: 1upx solid #ddd;
border-radius: inherit;
content: " ";
transform: scale(.5);
transform-origin: 0 0;
pointer-events: none
}
.cu-list.menu>.cu-item.grayscale {
background-color: #f5f5f5
}
.cu-list.menu>.cu-item.cur {
background-color: #fcf7e9
}
.cu-list.menu>.cu-item.arrow {
padding-right: 90upx
}
.cu-list.menu>.cu-item.arrow:before {
position: absolute;
top: 0;
right: 30upx;
bottom: 0;
display: block;
margin: auto;
width: 30upx;
height: 30upx;
color: #8799a3;
content: "\e6a3";
text-align: center;
font-size: 34upx;
font-family: cuIcon;
line-height: 30upx
}
.cu-list.menu>.cu-item button.content {
padding: 0;
background-color: transparent;
justify-content: flex-start
}
.cu-list.menu>.cu-item button.content:after {
display: none
}
.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
border-color: #ffffff
}
.cu-list.menu>.cu-item .content>view:first-child {
display: flex;
align-items: center
}
.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
display: inline-block;
margin-right: 10upx;
width: 1.6em;
text-align: center
}
.cu-list.menu>.cu-item .content>image {
display: inline-block;
margin-right: 10upx;
width: 1.6em;
height: 1.6em;
vertical-align: middle
}
.cu-list.menu>.cu-item .content {
font-size: 30upx;
line-height: 1.6em;
flex: 1
}
.cu-list.menu>.cu-item .content .cu-tag.sm {
display: inline-block;
margin-left: 10upx;
height: 28upx;
font-size: 16upx;
line-height: 32upx
}
.cu-list.menu>.cu-item .action .cu-tag:empty {
right: 10upx
}
.cu-list.menu {
display: block;
overflow: hidden
}
.cu-list.menu.sm-border>.cu-item:after {
left: 30upx;
width: calc(200% - 120upx)
}
.cu-list.grid>.cu-item {
position: relative;
display: flex;
padding: 20upx 0 30upx;
transition-duration: 0s;
flex-direction: column
}
.cu-list.grid>.cu-item:after {
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
width: 200%;
height: 200%;
border-right: 1px solid rgba(0, 0, 0, .1);
border-bottom: 1px solid rgba(0, 0, 0, .1);
border-radius: inherit;
content: " ";
transform: scale(.5);
transform-origin: 0 0;
pointer-events: none
}
.cu-list.grid>.cu-item text {
display: block;
margin-top: 10upx;
color: #888;
font-size: 26upx;
line-height: 40upx
}
.cu-list.grid>.cu-item [class*=cuIcon] {
position: relative;
display: block;
margin-top: 20upx;
width: 100%;
font-size: 48upx
}
.cu-list.grid>.cu-item .cu-tag {
right: auto;
left: 50%;
margin-left: 20upx
}
.cu-list.grid {
background-color: #ffffff;
text-align: center
}
.cu-list.grid.no-border>.cu-item {
padding-top: 10upx;
padding-bottom: 20upx
}
.cu-list.grid.no-border>.cu-item:after {
border: none
}
.cu-list.grid.no-border {
padding: 20upx 10upx
}
.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
border-right-width: 0
}
.cu-list.card-menu {
overflow: hidden;
margin-right: 30upx;
margin-left: 30upx;
border-radius: 20upx
}
/* ==================
操作条
==================== */
.cu-bar {
display: flex;
position: relative;
align-items: center;
min-height: 100upx;
justify-content: space-between;
}
.cu-bar .action {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
max-width: 100%;
}
.cu-bar .action.border-title {
position: relative;
top: -10upx;
}
.cu-bar .action.border-title text[class*="bg-"]:last-child {
position: absolute;
bottom: -0.5rem;
min-width: 2rem;
height: 6upx;
left: 0;
}
.cu-bar .action.sub-title {
position: relative;
top: -0.2rem;
}
.cu-bar .action.sub-title text {
position: relative;
z-index: 1;
}
.cu-bar .action.sub-title text[class*="bg-"]:last-child {
position: absolute;
display: inline-block;
bottom: -0.2rem;
border-radius: 6upx;
width: 100%;
height: 0.6rem;
left: 0.6rem;
opacity: 0.3;
z-index: 0;
}
.cu-bar .action.sub-title text[class*="text-"]:last-child {
position: absolute;
display: inline-block;
bottom: -0.7rem;
left: 0.5rem;
opacity: 0.2;
z-index: 0;
text-align: right;
font-weight: 900;
font-size: 36upx;
}
.cu-bar.justify-center .action.border-title text:last-child,
.cu-bar.justify-center .action.sub-title text:last-child {
left: 0;
right: 0;
margin: auto;
text-align: center;
}
.cu-bar .action:first-child {
margin-left: 30upx;
font-size: 30upx;
}
.cu-bar .action text.text-cut {
text-align: left;
width: 100%;
}
.cu-bar .cu-avatar:first-child {
margin-left: 20upx;
}
.cu-bar .action:first-child>text[class*="cuIcon-"] {
margin-left: -0.3em;
margin-right: 0.3em;
}
.cu-bar .action:last-child {
margin-right: 30upx;
}
.cu-bar .action>text[class*="cuIcon-"],
.cu-bar .action>view[class*="cuIcon-"] {
font-size: 36upx;
}
.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
margin-left: 0.5em;
}
.cu-bar .content {
position: absolute;
text-align: center;
width: calc(100% - 340upx);
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
height: 60upx;
font-size: 32upx;
line-height: 60upx;
cursor: none;
pointer-events: none;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.cu-bar.ios .content {
bottom: 7px;
height: 30px;
font-size: 32upx;
line-height: 30px;
}
.cu-bar.btn-group {
justify-content: space-around;
}
.cu-bar.btn-group button {
padding: 20upx 32upx;
}
.cu-bar.btn-group button {
flex: 1;
margin: 0 20upx;
max-width: 50%;
}
.cu-bar .search-form {
background-color: #f5f5f5;
line-height: 64upx;
height: 64upx;
font-size: 24upx;
color: #333333;
flex: 1;
display: flex;
align-items: center;
margin: 0 30upx;
}
.cu-bar .search-form+.action {
margin-right: 30upx;
}
.cu-bar .search-form input {
flex: 1;
padding-right: 30upx;
height: 64upx;
line-height: 64upx;
font-size: 26upx;
background-color: transparent;
}
.cu-bar .search-form [class*="cuIcon-"] {
margin: 0 0.5em 0 0.8em;
}
.cu-bar .search-form [class*="cuIcon-"]::before {
top: 0upx;
}
.cu-bar.fixed,
.nav.fixed {
position: fixed;
width: 100%;
top: 0;
z-index: 1024;
box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
}
.cu-bar.foot {
position: fixed;
width: 100%;
bottom: 0;
z-index: 1024;
box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
}
.cu-bar.tabbar {
padding: 0;
height: calc(100upx + env(safe-area-inset-bottom) / 2);
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
}
.cu-tabbar-height {
min-height: 100upx;
height: calc(100upx + env(safe-area-inset-bottom) / 2);
}
.cu-bar.tabbar.shadow {
box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
}
.cu-bar.tabbar .action {
font-size: 22upx;
position: relative;
flex: 1;
text-align: center;
padding: 0;
display: block;
height: auto;
line-height: 1;
margin: 0;
background-color: inherit;
overflow: initial;
}
.cu-bar.tabbar.shop .action {
width: 140upx;
flex: initial;
}
.cu-bar.tabbar .action.add-action {
position: relative;
z-index: 2;
padding-top: 50upx;
}
.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
position: absolute;
width: 70upx;
z-index: 2;
height: 70upx;
border-radius: 50%;
line-height: 70upx;
font-size: 50upx;
top: -35upx;
left: 0;
right: 0;
margin: auto;
padding: 0;
}
.cu-bar.tabbar .action.add-action::after {
content: "";
position: absolute;
width: 100upx;
height: 100upx;
top: -50upx;
left: 0;
right: 0;
margin: auto;
box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
border-radius: 50upx;
background-color: inherit;
z-index: 0;
}
.cu-bar.tabbar .action.add-action::before {
content: "";
position: absolute;
width: 100upx;
height: 30upx;
bottom: 30upx;
left: 0;
right: 0;
margin: auto;
background-color: inherit;
z-index: 1;
}
.cu-bar.tabbar .btn-group {
flex: 1;
display: flex;
justify-content: space-around;
align-items: center;
padding: 0 10upx;
}
.cu-bar.tabbar button.action::after {
border: 0;
}
.cu-bar.tabbar .action [class*="cuIcon-"] {
width: 100upx;
position: relative;
display: block;
height: auto;
margin: 0 auto 10upx;
text-align: center;
font-size: 40upx;
}
.cu-bar.tabbar .action .cuIcon-cu-image {
margin: 0 auto;
}
.cu-bar.tabbar .action .cuIcon-cu-image image {
width: 50upx;
height: 50upx;
display: inline-block;
}
.cu-bar.tabbar .submit {
align-items: center;
display: flex;
justify-content: center;
text-align: center;
position: relative;
flex: 2;
align-self: stretch;
}
.cu-bar.tabbar .submit:last-child {
flex: 2.6;
}
.cu-bar.tabbar .submit+.submit {
flex: 2;
}
.cu-bar.tabbar.border .action::before {
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
transform: scale(0.5);
transform-origin: 0 0;
border-right: 1upx solid rgba(0, 0, 0, 0.1);
z-index: 3;
}
.cu-bar.tabbar.border .action:last-child:before {
display: none;
}
.cu-bar.input {
padding-right: 20upx;
background-color: #ffffff;
}
.cu-bar.input input {
overflow: initial;
line-height: 64upx;
height: 64upx;
min-height: 64upx;
flex: 1;
font-size: 30upx;
margin: 0 20upx;
}
.cu-bar.input .action {
margin-left: 20upx;
}
.cu-bar.input .action [class*="cuIcon-"] {
font-size: 48upx;
}
.cu-bar.input input+.action {
margin-right: 20upx;
margin-left: 0upx;
}
.cu-bar.input .action:first-child [class*="cuIcon-"] {
margin-left: 0upx;
}
.cu-custom {
display: block;
position: relative;
}
.cu-custom .cu-bar .content {
width: calc(100% - 440upx);
}
/* #ifdef MP-ALIPAY */
.cu-custom .cu-bar .action .cuIcon-back {
opacity: 0;
}
/* #endif */
.cu-custom .cu-bar .content image {
height: 60upx;
width: 240upx;
}
.cu-custom .cu-bar {
min-height: 0px;
/* #ifdef MP-WEIXIN */
padding-right: 220upx;
/* #endif */
/* #ifdef MP-ALIPAY */
padding-right: 150upx;
/* #endif */
box-shadow: 0upx 0upx 0upx;
z-index: 9999;
}
.cu-custom .cu-bar .border-custom {
position: relative;
background: rgba(0, 0, 0, 0.15);
border-radius: 1000upx;
height: 30px;
}
.cu-custom .cu-bar .border-custom::after {
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border-radius: inherit;
transform: scale(0.5);
transform-origin: 0 0;
pointer-events: none;
box-sizing: border-box;
border: 1upx solid #ffffff;
opacity: 0.5;
}
.cu-custom .cu-bar .border-custom::before {
content: " ";
width: 1upx;
height: 110%;
position: absolute;
top: 22.5%;
left: 0;
right: 0;
margin: auto;
transform: scale(0.5);
transform-origin: 0 0;
pointer-events: none;
box-sizing: border-box;
opacity: 0.6;
background-color: #ffffff;
}
.cu-custom .cu-bar .border-custom text {
display: block;
flex: 1;
margin: auto !important;
text-align: center;
font-size: 34upx;
}
/* ==================
导航栏
==================== */
.nav {
white-space: nowrap;
}
::-webkit-scrollbar {
display: none;
}
.nav .cu-item {
height: 90upx;
display: inline-block;
line-height: 90upx;
margin: 0 10upx;
padding: 0 20upx;
}
.nav .cu-item.cur {
border-bottom: 4upx solid;
}
/* ==================
时间轴
==================== */
.cu-timeline {
display: block;
background-color: #ffffff;
}
.cu-timeline .cu-time {
width: 120upx;
text-align: center;
padding: 20upx 0;
font-size: 26upx;
color: #888;
display: block;
}
.cu-timeline>.cu-item {
padding: 30upx 30upx 30upx 120upx;
position: relative;
display: block;
z-index: 0;
}
.cu-timeline>.cu-item:not([class*="text-"]) {
color: #ccc;
}
.cu-timeline>.cu-item::after {
content: "";
display: block;
position: absolute;
width: 1upx;
background-color: #ddd;
left: 60upx;
height: 100%;
top: 0;
z-index: 8;
}
.cu-timeline>.cu-item::before {
font-family: "cuIcon";
display: block;
position: absolute;
top: 36upx;
z-index: 9;
background-color: #ffffff;
width: 50upx;
height: 50upx;
text-align: center;
border: none;
line-height: 50upx;
left: 36upx;
}
.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
content: "\e763";
}
.cu-timeline>.cu-item[class*="cuIcon-"]::before {
background-color: #ffffff;
width: 50upx;
height: 50upx;
text-align: center;
border: none;
line-height: 50upx;
left: 36upx;
}
.cu-timeline>.cu-item>.content {
padding: 30upx;
border-radius: 6upx;
display: block;
line-height: 1.6;
}
.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
background-color: #f1f1f1;
color: #333333;
}
.cu-timeline>.cu-item>.content+.content {
margin-top: 20upx;
}
/* ==================
聊天
==================== */
.cu-chat {
display: flex;
flex-direction: column;
}
.cu-chat .cu-item {
display: flex;
padding: 30upx 30upx 70upx;
position: relative;
}
.cu-chat .cu-item>.cu-avatar {
width: 80upx;
height: 80upx;
}
.cu-chat .cu-item>.main {
max-width: calc(100% - 260upx);
margin: 0 40upx;
display: flex;
align-items: center;
}
.cu-chat .cu-item>image {
height: 320upx;
}
.cu-chat .cu-item>.main .content {
padding: 20upx;
border-radius: 6upx;
display: inline-flex;
max-width: 100%;
align-items: center;
font-size: 30upx;
position: relative;
min-height: 80upx;
line-height: 40upx;
text-align: left;
}
.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
background-color: #ffffff;
color: #333333;
}
.cu-chat .cu-item .date {
position: absolute;
font-size: 24upx;
color: #8799a3;
width: calc(100% - 320upx);
bottom: 20upx;
left: 160upx;
}
.cu-chat .cu-item .action {
padding: 0 30upx;
display: flex;
align-items: center;
}
.cu-chat .cu-item>.main .content::after {
content: "";
top: 27upx;
transform: rotate(45deg);
position: absolute;
z-index: 100;
display: inline-block;
overflow: hidden;
width: 24upx;
height: 24upx;
left: -12upx;
right: initial;
background-color: inherit;
}
.cu-chat .cu-item.self>.main .content::after {
left: auto;
right: -12upx;
}
.cu-chat .cu-item>.main .content::before {
content: "";
top: 30upx;
transform: rotate(45deg);
position: absolute;
z-index: -1;
display: inline-block;
overflow: hidden;
width: 24upx;
height: 24upx;
left: -12upx;
right: initial;
background-color: inherit;
filter: blur(5upx);
opacity: 0.3;
}
.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
background-color: #333333;
opacity: 0.1;
}
.cu-chat .cu-item.self>.main .content::before {
left: auto;
right: -12upx;
}
.cu-chat .cu-item.self {
justify-content: flex-end;
text-align: right;
}
.cu-chat .cu-info {
display: inline-block;
margin: 20upx auto;
font-size: 24upx;
padding: 8upx 12upx;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 6upx;
color: #ffffff;
max-width: 400upx;
line-height: 1.4;
}
/* ==================
卡片
==================== */
.cu-card {
display: block;
overflow: hidden;
}
.cu-card>.cu-item {
display: block;
background-color: #ffffff;
overflow: hidden;
border-radius: 10upx;
margin: 30upx;
}
.cu-card>.cu-item.shadow-blur {
overflow: initial;
}
.cu-card.no-card>.cu-item {
margin: 0upx;
border-radius: 0upx;
}
.cu-card .grid.grid-square {
margin-bottom: -20upx;
}
.cu-card.case .image {
position: relative;
}
.cu-card.case .image image {
width: 100%;
}
.cu-card.case .image .cu-tag {
position: absolute;
right: 0;
top: 0;
}
.cu-card.case .image .cu-bar {
position: absolute;
bottom: 0;
width: 100%;
background-color: transparent;
padding: 0upx 30upx;
}
.cu-card.case.no-card .image {
margin: 30upx 30upx 0;
overflow: hidden;
border-radius: 10upx;
}
.cu-card.dynamic {
display: block;
}
.cu-card.dynamic>.cu-item {
display: block;
background-color: #ffffff;
overflow: hidden;
}
.cu-card.dynamic>.cu-item>.text-content {
padding: 0 30upx 0;
max-height: 6.4em;
overflow: hidden;
font-size: 30upx;
margin-bottom: 20upx;
}
.cu-card.dynamic>.cu-item .square-img {
width: 100%;
height: 200upx;
border-radius: 6upx;
}
.cu-card.dynamic>.cu-item .only-img {
width: 100%;
height: 320upx;
border-radius: 6upx;
}
/* card.dynamic>.cu-item .comment {
padding: 20upx;
background-color: #f1f1f1;
margin: 0 30upx 30upx;
border-radius: 6upx;
} */
.cu-card.article {
display: block;
}
.cu-card.article>.cu-item {
padding-bottom: 30upx;
}
.cu-card.article>.cu-item .title {
font-size: 30upx;
font-weight: 900;
color: #333333;
line-height: 100upx;
padding: 0 30upx;
}
.cu-card.article>.cu-item .content {
display: flex;
padding: 0 30upx;
}
.cu-card.article>.cu-item .content>image {
width: 240upx;
height: 6.4em;
margin-right: 20upx;
border-radius: 6upx;
}
.cu-card.article>.cu-item .content .desc {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.cu-card.article>.cu-item .content .text-content {
font-size: 28upx;
color: #888;
height: 4.8em;
overflow: hidden;
}
/* ==================
表单
==================== */
.cu-form-group {
background-color: #ffffff;
padding: 1upx 30upx;
display: flex;
align-items: center;
min-height: 100upx;
justify-content: space-between;
}
.cu-form-group+.cu-form-group {
border-top: 1upx solid #eee;
}
.cu-form-group .title {
text-align: justify;
padding-right: 30upx;
font-size: 30upx;
position: relative;
height: 60upx;
line-height: 60upx;
}
.cu-form-group input {
flex: 1;
font-size: 30upx;
color: #555;
padding-right: 20upx;
}
.cu-form-group>text[class*="cuIcon-"] {
font-size: 36upx;
padding: 0;
box-sizing: border-box;
}
.cu-form-group textarea {
margin: 32upx 0 30upx;
height: 4.6em;
width: 100%;
line-height: 1.2em;
flex: 1;
font-size: 28upx;
padding: 0;
}
.cu-form-group.align-start .title {
height: 1em;
margin-top: 32upx;
line-height: 1em;
}
.cu-form-group picker {
flex: 1;
padding-right: 40upx;
overflow: hidden;
position: relative;
}
.cu-form-group picker .picker {
line-height: 100upx;
font-size: 28upx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 100%;
text-align: right;
}
.cu-form-group picker::after {
font-family: cuIcon;
display: block;
content: "\e6a3";
position: absolute;
font-size: 34upx;
color: #8799a3;
line-height: 100upx;
width: 60upx;
text-align: center;
top: 0;
bottom: 0;
right: -20upx;
margin: auto;
}
.cu-form-group textarea[disabled],
.cu-form-group textarea[disabled] .placeholder {
color: transparent;
}
/* ==================
模态窗口
==================== */
.cu-modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1110;
opacity: 0;
outline: 0;
text-align: center;
-ms-transform: scale(1.185);
transform: scale(1.185);
backface-visibility: hidden;
perspective: 2000upx;
background: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out 0s;
pointer-events: none;
}
.cu-modal::before {
content: "\200B";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.cu-modal.show {
opacity: 1;
transition-duration: 0.3s;
-ms-transform: scale(1);
transform: scale(1);
overflow-x: hidden;
overflow-y: auto;
pointer-events: auto;
}
.cu-dialog {
position: relative;
display: inline-block;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 680upx;
max-width: 100%;
background-color: #f8f8f8;
border-radius: 10upx;
overflow: hidden;
}
.cu-modal.bottom-modal::before {
vertical-align: bottom;
}
.cu-modal.bottom-modal .cu-dialog {
width: 100%;
border-radius: 0;
}
.cu-modal.bottom-modal {
margin-bottom: -1000upx;
}
.cu-modal.bottom-modal.show {
margin-bottom: 0;
}
.cu-modal.drawer-modal {
transform: scale(1);
display: flex;
}
.cu-modal.drawer-modal .cu-dialog {
height: 100%;
min-width: 200upx;
border-radius: 0;
margin: initial;
transition-duration: 0.3s;
}
.cu-modal.drawer-modal.justify-start .cu-dialog {
transform: translateX(-100%);
}
.cu-modal.drawer-modal.justify-end .cu-dialog {
transform: translateX(100%);
}
.cu-modal.drawer-modal.show .cu-dialog {
transform: translateX(0%);
}
.cu-modal .cu-dialog>.cu-bar:first-child .action{
min-width: 100rpx;
margin-right: 0;
min-height: 100rpx;
}
/* ==================
轮播
==================== */
swiper .a-swiper-dot {
display: inline-block;
width: 16upx;
height: 16upx;
background: rgba(0, 0, 0, .3);
border-radius: 50%;
vertical-align: middle;
}
swiper[class*="-dot"] .wx-swiper-dots,
swiper[class*="-dot"] .a-swiper-dots,
swiper[class*="-dot"] .uni-swiper-dots {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
}
swiper.square-dot .wx-swiper-dot,
swiper.square-dot .a-swiper-dot,
swiper.square-dot .uni-swiper-dot {
background-color: #ffffff;
opacity: 0.4;
width: 10upx;
height: 10upx;
border-radius: 20upx;
margin: 0 8upx !important;
}
swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
opacity: 1;
width: 30upx;
}
swiper.round-dot .wx-swiper-dot,
swiper.round-dot .a-swiper-dot,
swiper.round-dot .uni-swiper-dot {
width: 10upx;
height: 10upx;
position: relative;
margin: 4upx 8upx !important;
}
swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
content: "";
position: absolute;
width: 10upx;
height: 10upx;
top: 0upx;
left: 0upx;
right: 0;
bottom: 0;
margin: auto;
background-color: #ffffff;
border-radius: 20upx;
}
swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
width: 18upx;
height: 18upx;
}
.screen-swiper {
min-height: 375upx;
}
.screen-swiper image,
.screen-swiper video,
.swiper-item image,
.swiper-item video {
width: 100%;
display: block;
height: 100%;
margin: 0;
pointer-events: none;
}
.card-swiper {
height: 420upx !important;
}
.card-swiper swiper-item {
width: 610upx !important;
left: 70upx;
box-sizing: border-box;
padding: 40upx 0upx 70upx;
overflow: initial;
}
.card-swiper swiper-item .swiper-item {
width: 100%;
display: block;
height: 100%;
border-radius: 10upx;
transform: scale(0.9);
transition: all 0.2s ease-in 0s;
overflow: hidden;
}
.card-swiper swiper-item.cur .swiper-item {
transform: none;
transition: all 0.2s ease-in 0s;
}
.tower-swiper {
height: 420upx;
position: relative;
max-width: 750upx;
overflow: hidden;
}
.tower-swiper .tower-item {
position: absolute;
width: 300upx;
height: 380upx;
top: 0;
bottom: 0;
left: 50%;
margin: auto;
transition: all 0.2s ease-in 0s;
opacity: 1;
}
.tower-swiper .tower-item.none {
opacity: 0;
}
.tower-swiper .tower-item .swiper-item {
width: 100%;
height: 100%;
border-radius: 6upx;
overflow: hidden;
}
/* ==================
步骤条
==================== */
.cu-steps {
display: flex;
}
scroll-view.cu-steps {
display: block;
white-space: nowrap;
}
scroll-view.cu-steps .cu-item {
display: inline-block;
}
.cu-steps .cu-item {
flex: 1;
text-align: center;
position: relative;
min-width: 100upx;
}
.cu-steps .cu-item:not([class*="text-"]) {
color: #8799a3;
}
.cu-steps .cu-item [class*="cuIcon-"],
.cu-steps .cu-item .num {
display: block;
font-size: 40upx;
line-height: 80upx;
}
.cu-steps .cu-item::before,
.cu-steps .cu-item::after,
.cu-steps.steps-arrow .cu-item::before,
.cu-steps.steps-arrow .cu-item::after {
content: "";
display: block;
position: absolute;
height: 0px;
width: calc(100% - 80upx);
border-bottom: 1px solid #ccc;
left: calc(0px - (100% - 80upx) / 2);
top: 40upx;
z-index: 0;
}
.cu-steps.steps-arrow .cu-item::before,
.cu-steps.steps-arrow .cu-item::after {
content: "\e6a3";
font-family: 'cuIcon';
height: 30upx;
border-bottom-width: 0px;
line-height: 30upx;
top: 0;
bottom: 0;
margin: auto;
color: #ccc;
}
.cu-steps.steps-bottom .cu-item::before,
.cu-steps.steps-bottom .cu-item::after {
bottom: 40upx;
top: initial;
}
.cu-steps .cu-item::after {
border-bottom: 1px solid currentColor;
width: 0px;
transition: all 0.3s ease-in-out 0s;
}
.cu-steps .cu-item[class*="text-"]::after {
width: calc(100% - 80upx);
color: currentColor;
}
.cu-steps .cu-item:first-child::before,
.cu-steps .cu-item:first-child::after {
display: none;
}
.cu-steps .cu-item .num {
width: 40upx;
height: 40upx;
border-radius: 50%;
line-height: 40upx;
margin: 20upx auto;
font-size: 24upx;
border: 1px solid currentColor;
position: relative;
overflow: hidden;
}
.cu-steps .cu-item[class*="text-"] .num {
background-color: currentColor;
}
.cu-steps .cu-item .num::before,
.cu-steps .cu-item .num::after {
content: attr(data-index);
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
transition: all 0.3s ease-in-out 0s;
transform: translateY(0upx);
}
.cu-steps .cu-item[class*="text-"] .num::before {
transform: translateY(-40upx);
color: #ffffff;
}
.cu-steps .cu-item .num::after {
transform: translateY(40upx);
color: #ffffff;
transition: all 0.3s ease-in-out 0s;
}
.cu-steps .cu-item[class*="text-"] .num::after {
content: "\e645";
font-family: 'cuIcon';
color: #ffffff;
transform: translateY(0upx);
}
.cu-steps .cu-item[class*="text-"] .num.err::after {
content: "\e646";
}
/* ==================
布局
==================== */
/* -- flex弹性布局 -- */
.flex {
display: flex;
}
.basis-xs {
flex-basis: 20%;
}
.basis-sm {
flex-basis: 40%;
}
.basis-df {
flex-basis: 50%;
}
.basis-lg {
flex-basis: 60%;
}
.basis-xl {
flex-basis: 80%;
}
.basic-all{
flex-basis: 100%;
}
.flex-sub {
flex: 1;
}
.flex-twice {
flex: 2;
}
.flex-treble {
flex: 3;
}
.flex-direction {
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.align-start {
align-items: flex-start;
}
.align-end {
align-items: flex-end;
}
.align-center {
align-items: center;
}
.align-stretch {
align-items: stretch;
}
.self-start {
align-self: flex-start;
}
.self-center {
align-self: flex-center;
}
.self-end {
align-self: flex-end;
}
.self-stretch {
align-self: stretch;
}
.align-stretch {
align-items: stretch;
}
.justify-start {
justify-content: flex-start;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.justify-between {
justify-content: space-between;
}
.justify-around {
justify-content: space-around;
}
/* grid布局 */
.grid {
display: flex;
flex-wrap: wrap;
}
.grid.grid-square {
overflow: hidden;
}
.grid.grid-square .cu-tag {
position: absolute;
right: 0;
top: 0;
border-bottom-left-radius: 6upx;
padding: 6upx 12upx;
height: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.grid.grid-square>view>text[class*="cuIcon-"] {
font-size: 52upx;
position: absolute;
color: #8799a3;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.grid.grid-square>view {
margin-right: 20upx;
margin-bottom: 20upx;
border-radius: 6upx;
position: relative;
overflow: hidden;
}
.grid.grid-square>view.bg-img image {
width: 100%;
height: 100%;
position: absolute;
}
.grid.col-1.grid-square>view {
padding-bottom: 100%;
height: 0;
margin-right: 0;
}
.grid.col-2.grid-square>view {
padding-bottom: calc((100% - 20upx)/2);
height: 0;
width: calc((100% - 20upx)/2);
}
.grid.col-3.grid-square>view {
padding-bottom: calc((100% - 40upx)/3);
height: 0;
width: calc((100% - 40upx)/3);
}
.grid.col-4.grid-square>view {
padding-bottom: calc((100% - 60upx)/4);
height: 0;
width: calc((100% - 60upx)/4);
}
.grid.col-5.grid-square>view {
padding-bottom: calc((100% - 80upx)/5);
height: 0;
width: calc((100% - 80upx)/5);
}
.grid.col-2.grid-square>view:nth-child(2n),
.grid.col-3.grid-square>view:nth-child(3n),
.grid.col-4.grid-square>view:nth-child(4n),
.grid.col-5.grid-square>view:nth-child(5n) {
margin-right: 0;
}
.grid.col-1>view {
width: 100%;
}
.grid.col-2>view {
width: 50%;
}
.grid.col-3>view {
width: 33.33%;
}
.grid.col-4>view {
width: 25%;
}
.grid.col-5>view {
width: 20%;
}
/* -- 内外边距 -- */
.margin-0 {
margin: 0;
}
.margin-xs {
margin: 10upx;
}
.margin-sm {
margin: 20upx;
}
.margin {
margin: 30upx;
}
.margin-lg {
margin: 40upx;
}
.margin-xl {
margin: 50upx;
}
.margin-top-xs {
margin-top: 10upx;
}
.margin-top-sm {
margin-top: 20upx;
}
.margin-top {
margin-top: 30upx;
}
.margin-top-lg {
margin-top: 40upx;
}
.margin-top-xl {
margin-top: 50upx;
}
.margin-right-xs {
margin-right: 10upx;
}
.margin-right-sm {
margin-right: 20upx;
}
.margin-right {
margin-right: 30upx;
}
.margin-right-lg {
margin-right: 40upx;
}
.margin-right-xl {
margin-right: 50upx;
}
.margin-bottom-xs {
margin-bottom: 10upx;
}
.margin-bottom-sm {
margin-bottom: 20upx;
}
.margin-bottom {
margin-bottom: 30upx;
}
.margin-bottom-lg {
margin-bottom: 40upx;
}
.margin-bottom-xl {
margin-bottom: 50upx;
}
.margin-left-xs {
margin-left: 10upx;
}
.margin-left-sm {
margin-left: 20upx;
}
.margin-left {
margin-left: 30upx;
}
.margin-left-lg {
margin-left: 40upx;
}
.margin-left-xl {
margin-left: 50upx;
}
.margin-lr-xs {
margin-left: 10upx;
margin-right: 10upx;
}
.margin-lr-sm {
margin-left: 20upx;
margin-right: 20upx;
}
.margin-lr {
margin-left: 30upx;
margin-right: 30upx;
}
.margin-lr-lg {
margin-left: 40upx;
margin-right: 40upx;
}
.margin-lr-xl {
margin-left: 50upx;
margin-right: 50upx;
}
.margin-tb-xs {
margin-top: 10upx;
margin-bottom: 10upx;
}
.margin-tb-sm {
margin-top: 20upx;
margin-bottom: 20upx;
}
.margin-tb {
margin-top: 30upx;
margin-bottom: 30upx;
}
.margin-tb-lg {
margin-top: 40upx;
margin-bottom: 40upx;
}
.margin-tb-xl {
margin-top: 50upx;
margin-bottom: 50upx;
}
.padding-0 {
padding: 0;
}
.padding-xs {
padding: 10upx;
}
.padding-sm {
padding: 20upx;
}
.padding {
padding: 30upx;
}
.padding-lg {
padding: 40upx;
}
.padding-xl {
padding: 50upx;
}
.padding-top-xs {
padding-top: 10upx;
}
.padding-top-sm {
padding-top: 20upx;
}
.padding-top {
padding-top: 30upx;
}
.padding-top-lg {
padding-top: 40upx;
}
.padding-top-xl {
padding-top: 50upx;
}
.padding-right-xs {
padding-right: 10upx;
}
.padding-right-sm {
padding-right: 20upx;
}
.padding-right {
padding-right: 30upx;
}
.padding-right-lg {
padding-right: 40upx;
}
.padding-right-xl {
padding-right: 50upx;
}
.padding-bottom-xs {
padding-bottom: 10upx;
}
.padding-bottom-sm {
padding-bottom: 20upx;
}
.padding-bottom {
padding-bottom: 30upx;
}
.padding-bottom-lg {
padding-bottom: 40upx;
}
.padding-bottom-xl {
padding-bottom: 50upx;
}
.padding-left-xs {
padding-left: 10upx;
}
.padding-left-sm {
padding-left: 20upx;
}
.padding-left {
padding-left: 30upx;
}
.padding-left-lg {
padding-left: 40upx;
}
.padding-left-xl {
padding-left: 50upx;
}
.padding-lr-xs {
padding-left: 10upx;
padding-right: 10upx;
}
.padding-lr-sm {
padding-left: 20upx;
padding-right: 20upx;
}
.padding-lr {
padding-left: 30upx;
padding-right: 30upx;
}
.padding-lr-lg {
padding-left: 40upx;
padding-right: 40upx;
}
.padding-lr-xl {
padding-left: 50upx;
padding-right: 50upx;
}
.padding-tb-xs {
padding-top: 10upx;
padding-bottom: 10upx;
}
.padding-tb-sm {
padding-top: 20upx;
padding-bottom: 20upx;
}
.padding-tb {
padding-top: 30upx;
padding-bottom: 30upx;
}
.padding-tb-lg {
padding-top: 40upx;
padding-bottom: 40upx;
}
.padding-tb-xl {
padding-top: 50upx;
padding-bottom: 50upx;
}
/* -- 浮动 -- */
.cf::after,
.cf::before {
content: " ";
display: table;
}
.cf::after {
clear: both;
}
.fl {
float: left;
}
.fr {
float: right;
}
/* ==================
背景
==================== */
.line-red::after,
.lines-red::after {
border-color: #e54d42;
}
.line-orange::after,
.lines-orange::after {
border-color: #f37b1d;
}
.line-yellow::after,
.lines-yellow::after {
border-color: #fbbd08;
}
.line-olive::after,
.lines-olive::after {
border-color: #8dc63f;
}
.line-green::after,
.lines-green::after {
border-color: #39b54a;
}
.line-cyan::after,
.lines-cyan::after {
border-color: #1cbbb4;
}
.line-blue::after,
.lines-blue::after {
border-color: #0081ff;
}
.line-purple::after,
.lines-purple::after {
border-color: #6739b6;
}
.line-mauve::after,
.lines-mauve::after {
border-color: #9c26b0;
}
.line-pink::after,
.lines-pink::after {
border-color: #e03997;
}
.line-brown::after,
.lines-brown::after {
border-color: #a5673f;
}
.line-grey::after,
.lines-grey::after {
border-color: #8799a3;
}
.line-gray::after,
.lines-gray::after {
border-color: #aaaaaa;
}
.line-black::after,
.lines-black::after {
border-color: #333333;
}
.line-white::after,
.lines-white::after {
border-color: #ffffff;
}
.bg-red {
background-color: #e54d42;
color: #ffffff;
}
.bg-orange {
background-color: #f37b1d;
color: #ffffff;
}
.bg-yellow {
background-color: #fbbd08;
color: #333333;
}
.bg-olive {
background-color: #8dc63f;
color: #ffffff;
}
.bg-green {
background-color: #39b54a;
color: #ffffff;
}
.bg-cyan {
background-color: #1cbbb4;
color: #ffffff;
}
.bg-blue {
background-color: #0081ff;
color: #ffffff;
}
.bg-purple {
background-color: #6739b6;
color: #ffffff;
}
.bg-mauve {
background-color: #9c26b0;
color: #ffffff;
}
.bg-pink {
background-color: #e03997;
color: #ffffff;
}
.bg-brown {
background-color: #a5673f;
color: #ffffff;
}
.bg-grey {
background-color: #8799a3;
color: #ffffff;
}
.bg-gray {
background-color: #f0f0f0;
color: #333333;
}
.bg-black {
background-color: #333333;
color: #ffffff;
}
.bg-white {
background-color: #ffffff;
color: #666666;
}
.bg-shadeTop {
background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
color: #ffffff;
}
.bg-shadeBottom {
background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
color: #ffffff;
}
.bg-red.light {
color: #e54d42;
background-color: #fadbd9;
}
.bg-orange.light {
color: #f37b1d;
background-color: #fde6d2;
}
.bg-yellow.light {
color: #fbbd08;
background-color: #fef2ced2;
}
.bg-olive.light {
color: #8dc63f;
background-color: #e8f4d9;
}
.bg-green.light {
color: #39b54a;
background-color: #d7f0dbff;
}
.bg-cyan.light {
color: #1cbbb4;
background-color: #d2f1f0;
}
.bg-blue.light {
color: #0081ff;
background-color: #cce6ff;
}
.bg-purple.light {
color: #6739b6;
background-color: #e1d7f0;
}
.bg-mauve.light {
color: #9c26b0;
background-color: #ebd4ef;
}
.bg-pink.light {
color: #e03997;
background-color: #f9d7ea;
}
.bg-brown.light {
color: #a5673f;
background-color: #ede1d9;
}
.bg-grey.light {
color: #8799a3;
background-color: #e7ebed;
}
.bg-gradual-red {
background-image: linear-gradient(45deg, #f43f3b, #ec008c);
color: #ffffff;
}
.bg-gradual-orange {
background-image: linear-gradient(45deg, #ff9700, #ed1c24);
color: #ffffff;
}
.bg-gradual-green {
background-image: linear-gradient(45deg, #39b54a, #8dc63f);
color: #ffffff;
}
.bg-gradual-purple {
background-image: linear-gradient(45deg, #9000ff, #5e00ff);
color: #ffffff;
}
.bg-gradual-pink {
background-image: linear-gradient(45deg, #ec008c, #6739b6);
color: #ffffff;
}
.bg-gradual-blue {
background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
color: #ffffff;
}
.shadow[class*="-red"] {
box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
}
.shadow[class*="-orange"] {
box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
}
.shadow[class*="-yellow"] {
box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
}
.shadow[class*="-olive"] {
box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
}
.shadow[class*="-green"] {
box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
}
.shadow[class*="-cyan"] {
box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
}
.shadow[class*="-blue"] {
box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
}
.shadow[class*="-purple"] {
box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
}
.shadow[class*="-mauve"] {
box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
}
.shadow[class*="-pink"] {
box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
}
.shadow[class*="-brown"] {
box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
}
.shadow[class*="-grey"] {
box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
}
.shadow[class*="-gray"] {
box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
}
.shadow[class*="-black"] {
box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
}
.shadow[class*="-white"] {
box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
}
.text-shadow[class*="-red"] {
text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
}
.text-shadow[class*="-orange"] {
text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
}
.text-shadow[class*="-yellow"] {
text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
}
.text-shadow[class*="-olive"] {
text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
}
.text-shadow[class*="-green"] {
text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
}
.text-shadow[class*="-cyan"] {
text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
}
.text-shadow[class*="-blue"] {
text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
}
.text-shadow[class*="-purple"] {
text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
}
.text-shadow[class*="-mauve"] {
text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
}
.text-shadow[class*="-pink"] {
text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
}
.text-shadow[class*="-brown"] {
text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
}
.text-shadow[class*="-grey"] {
text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
}
.text-shadow[class*="-gray"] {
text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
}
.text-shadow[class*="-black"] {
text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
}
.bg-img {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.bg-mask {
background-color: #333333;
position: relative;
}
.bg-mask::after {
content: "";
border-radius: inherit;
width: 100%;
height: 100%;
display: block;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
}
.bg-mask view,
.bg-mask cover-view {
z-index: 5;
position: relative;
}
.bg-video {
position: relative;
}
.bg-video video {
display: block;
height: 100%;
width: 100%;
-o-object-fit: cover;
object-fit: cover;
position: absolute;
top: 0;
z-index: 0;
pointer-events: none;
}
/* ==================
文本
==================== */
.text-xs {
font-size: 20upx;
}
.text-sm {
font-size: 24upx;
}
.text-df {
font-size: 28upx;
}
.text-lg {
font-size: 32upx;
}
.text-xl {
font-size: 36upx;
}
.text-xxl {
font-size: 44upx;
}
.text-sl {
font-size: 80upx;
}
.text-xsl {
font-size: 120upx;
}
.text-Abc {
text-transform: Capitalize;
}
.text-ABC {
text-transform: Uppercase;
}
.text-abc {
text-transform: Lowercase;
}
.text-price::before {
content: "¥";
font-size: 80%;
margin-right: 4upx;
}
.text-cut {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.text-bold {
font-weight: bold;
}
.text-center {
text-align: center;
}
.text-content {
line-height: 1.6;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-red,
.line-red,
.lines-red {
color: #e54d42;
}
.text-orange,
.line-orange,
.lines-orange {
color: #f37b1d;
}
.text-yellow,
.line-yellow,
.lines-yellow {
color: #fbbd08;
}
.text-olive,
.line-olive,
.lines-olive {
color: #8dc63f;
}
.text-green,
.line-green,
.lines-green {
color: #39b54a;
}
.text-cyan,
.line-cyan,
.lines-cyan {
color: #1cbbb4;
}
.text-blue,
.line-blue,
.lines-blue {
color: #0081ff;
}
.text-purple,
.line-purple,
.lines-purple {
color: #6739b6;
}
.text-mauve,
.line-mauve,
.lines-mauve {
color: #9c26b0;
}
.text-pink,
.line-pink,
.lines-pink {
color: #e03997;
}
.text-brown,
.line-brown,
.lines-brown {
color: #a5673f;
}
.text-grey,
.line-grey,
.lines-grey {
color: #8799a3;
}
.text-gray,
.line-gray,
.lines-gray {
color: #aaaaaa;
}
.text-black,
.line-black,
.lines-black {
color: #333333;
}
.text-white,
.line-white,
.lines-white {
color: #ffffff;
}
# 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>
import { uniAppHook, Global } from '../helpers/config';
import {
callAppHook, getPages, getPageVmOrMp, ruleToUniNavInfo, formatTo, formatFrom, APPGetPageRoute, getPageOnBeforeBack,
} from './util';
import { noop } from '../helpers/util';
import { warn } from '../helpers/warn';
import uniPushTo from './uniNav';
let startBack = false; // 主要是兼容低端手机返回卡 然后多次返回直接提示退出的问题
/**
* 还原并执行所有 拦截下来的生命周期 app.vue 及 index 下的生命周期
* @param {Boolean} callHome // 是否触发首页的生命周期
*
* this 为当前 page 对象
*/
const callwaitHooks = function (callHome) {
return new Promise(async (resolve) => {
const variation = []; // 存储一下在uni-app上的变异生命钩子 奇葩的要死
const {
appVue, indexVue, onLaunch, onShow, waitHooks, variationFuns, indexCallHooks,
} = uniAppHook;
const app = appVue.$options;
await onLaunch.fun[onLaunch.fun.length - 1].call(appVue, onLaunch.args); // 确保只执行最后一个 并且强化异步操作
onShow.fun[onShow.fun.length - 1].call(appVue, onShow.args); // onshow 不保证异步 直接确保执行最后一个
if (callHome) { // 触发首页生命周期
// eslint-disable-next-line
for (const key in waitHooks) {
if (indexCallHooks.includes(key)) { // 只有在被包含的情况下才执行
callAppHook.call(this, waitHooks[key].fun);
}
}
}
if (onLaunch.isHijack) { // 还原 onLaunch生命钩子
app.onLaunch.splice(app.onLaunch.length - 1, 1, onLaunch.fun[0]);
}
if (onShow.isHijack) { // 继续还原 onShow
app.onShow.splice(app.onShow.length - 1, 1, onShow.fun[0]);
}
// eslint-disable-next-line
for (const key in waitHooks) { // 还原 首页下的生命钩子
const item = waitHooks[key];
if (item.isHijack) {
if (variationFuns.includes(key)) { // 变异方法
variation.push({ key, fun: item.fun[0] });
} else {
const indeHooks = indexVue[key];
// 修复 https://github.com/SilurianYang/uni-simple-router/issues/76
setTimeout(() => { // 异步延迟还原 不然 uni-app 给给触发了
indeHooks.splice(indeHooks.length - 1, 1, item.fun[0]);
}, 50);
}
}
}
resolve(variation);
});
};
/**
* 还原剩下的奇葩生命钩子
* @param {Object} variation 当前uni-app中的一些变异方法 奇葩生命钩子
*/
const callVariationHooks = function (variation) {
for (let i = 0; i < variation.length; i += 1) {
const { key, fun } = variation[i];
const indeHooks = uniAppHook.indexVue[key];
indeHooks.splice(indeHooks.length - 1, 1, fun);
}
};
/**
* 主要是对app.vue下onLaunch和onShow生命周期进行劫持
*
* this 为当前 page 对象
*/
export const proxyLaunchHook = function () {
const {
onLaunch,
onShow,
} = this.$options;
uniAppHook.appVue = this; // 缓存 当前app.vue组件对象
if (onLaunch.length > 1) { // 确保有写 onLaunch 可能有其他混入 那也办法
uniAppHook.onLaunch.isHijack = true;
uniAppHook.onLaunch.fun = onLaunch.splice(onLaunch.length - 1, 1, (arg) => {
uniAppHook.onLaunch.args = arg;
}); // 替换uni-app自带的生命周期
}
if (onShow.length > 0) {
uniAppHook.onShow.isHijack = true;
uniAppHook.onShow.fun = onShow.splice(onShow.length - 1, 1, (arg) => {
uniAppHook.onShow.args = arg;
if (uniAppHook.pageReady) { // 因为还有app切前台后台的操作
callAppHook.call(this, uniAppHook.onShow.fun, arg);
}
}); // 替换替换 都替换
}
};
/**
* 把指定页面的生命钩子函数保存并替换
* this 为当前 page 对象
*/
export const proxyIndexHook = function (Router) {
const { needHooks, waitHooks } = uniAppHook;
const options = this.$options;
uniAppHook.indexVue = options;
for (let i = 0; i < needHooks.length; i += 1) {
const key = needHooks[i];
if (options[key] != null) { // 只劫持开发者声明的生命周期
const { length } = options[key];
// eslint-disable-next-line
const whObject= waitHooks[key]={};
whObject.fun = options[key].splice(length - 1, 1, noop); // 把实际的页面生命钩子函数缓存起来,替换原有的生命钩子
whObject.isHijack = true;
}
}
// eslint-disable-next-line
triggerLifeCycle.call(this, Router); // 接着 主动我们触发导航守卫
};
/**
* 触发全局beforeHooks 生命钩子
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const beforeHooks = function (_from, _to) {
return new Promise(async (resolve) => {
const beforeHooksFun = this.lifeCycle.beforeHooks[0];
if (beforeHooksFun == null) {
return resolve();
}
await beforeHooksFun.call(this, _to, _from, resolve);
});
};
/**
* 触发全局afterEachHooks 生命钩子
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const afterEachHooks = function (_from, _to) {
const afterHooks = this.lifeCycle.afterHooks[0];
if (afterHooks != null && afterHooks.constructor === Function) {
afterHooks.call(this, _to, _from);
}
};
/**
* 触发全局 beforeEnter 生命钩子
* @param {Object} finalRoute // 当前格式化后的路由参数
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const beforeEnterHooks = function (finalRoute, _from, _to) {
return new Promise(async (resolve) => {
const { beforeEnter } = finalRoute.route;
if (beforeEnter == null || beforeEnter.constructor !== Function) { // 当前这个beforeEnter不存在 或者类型错误
return resolve();
}
await beforeEnter.call(this, _to, _from, resolve);
});
};
/**
* 触发返回事件公共方法
* @param {Object} page 用getPages获取到的页面栈对象
* @param {Object} options 当前vue页面对象
* @param {Object} backLayerC 需要返回页面的层级
*
* this 为当前 Router 对象
*/
const backCallHook = function (page, options, backLayerC = 1) {
const route = APPGetPageRoute([page]);
const NAVTYPE = 'RouterBack';
// eslint-disable-next-line
transitionTo.call(this, { path: route.path, query: route.query }, NAVTYPE, (finalRoute, fnType) => {
if (fnType != NAVTYPE) { // 返回时的api如果有next到其他页面 那么必须带上NAVTYPE 不相同则表示需要跳转到其他页面
return uniPushTo(finalRoute, fnType);
}
if (startBack) { // 如果当前处于正在返回的状态
return warn('当前处于正在返回的状态,请稍后再试!');
}
startBack = true; // 标记开始返回
options.onBackPress = [noop]; // 改回uni-app可执行的状态
setTimeout(() => {
this.back(backLayerC, undefined, true); // 越过加锁验证
startBack = false; // 返回结束
});
});
};
/**
* 处理返回按钮的生命钩子
* @param {Object} options 当前 vue 组件对象下的$options对象
* @param {Array} args 当前页面是点击头部返回还是底部返回
*
* this 为当前 Router 对象
*/
export const beforeBackHooks = async function (options, args) {
const isNext = await getPageOnBeforeBack(args); // 执行onBeforeBack
if (isNext === false) { // onBeforeBack 返回了true 阻止了跳转
Global.LockStatus = false; // 也需要解锁
return false;
}
const page = getPages(-3); // 上一个页面对象
backCallHook.call(this, page, options);
};
/**
* 处理back api的生命钩子
* @param {Object} options 当前 vue 组件对象下的$options对象
* @param {Array} args 当前页面是点击头部返回还是底部返回
*
* this 为当前 Router 对象
*/
export const backApiCallHook = async function (options, args) {
await getPageOnBeforeBack(args);
const { backLayerC } = Global;
const pages = getPages();
let page = null;
if (backLayerC > pages.length - 1 || backLayerC == pages.length - 1) { // 返回的首页 我们需要显示tabbar拦截
// eslint-disable-next-line
page = pages[0];
} else {
page = pages[pages.length - 2];
}
backCallHook.call(this, page, options, backLayerC);
};
/**
* v1.5.4+
* beforeRouteLeave 生命周期
* @param {Object} to 将要去的那个页面 to对象
* @param {Object} from 从那个页面触发的 from对象
* @param {Boolean} leaveHook:? 是否为 beforeRouteLeave 触发的next 到别处 如果是则不再触发 beforeRouteLeave 生命钩子
* this 为当前 Router 对象
*/
const beforeRouteLeaveHooks = function (from, to, leaveHook) {
return new Promise((resolve) => {
if (leaveHook) { // 我们知道这个是来自页面beforeRouteLeave next到其他地方,所有不必再执行啦
warn('beforeRouteLeave next到其他地方,无须再执行!');
return resolve();
}
if (from.path == to.path) { // 进入首页的时候不触发
return resolve();
}
const currentPage = getPages(-2); // 获取到全部的页面对象
const callThis = getPageVmOrMp(currentPage); // 获取到页面的 $vm 对象 及 page页面的this对象
const { beforeRouteLeave } = callThis.$options; // 查看当前是否有开发者声明
if (beforeRouteLeave == null) {
warn('当前页面下无 beforeRouteLeave 钩子声明,无须执行!');
return resolve();
}
if (beforeRouteLeave != null && beforeRouteLeave.constructor !== Function) {
warn('beforeRouteLeave 生命钩子声明错误,必须是一个函数!');
return resolve();
}
beforeRouteLeave.call(callThis, to, from, resolve); // 执行生命钩子
});
};
/**
* 验证当前 next() 管道函数是否支持下一步
*
* @param {Object} Intercept 拦截到的新路由规则
* @param {Object} fnType 跳转页面的类型方法 原始的
* @param {Object} navCB 回调函数 原始的
* @param {Boolean} leaveHookCall:? 是否为 beforeRouteLeave 触发的next 做拦截判断
* this 为当前 Router 对象
*
*/
const isNext = function (Intercept, fnType, navCB, leaveHookCall = false) {
return new Promise((resolve, reject) => {
if (Intercept == null) { // 什么也不做 直接执行下一个钩子
return resolve();
}
if (Intercept === false) { // 路由中断
Global.LockStatus = false; // 解锁跳转状态
return reject('路由终止');
}
if (Intercept.constructor === String) { // 说明 开发者直接传的path 并且没有指定 NAVTYPE 那么采用原来的navType
reject('next到其他页面');
// eslint-disable-next-line
return transitionTo.call(this, Intercept, fnType, navCB,leaveHookCall);
}
if (Intercept.constructor === Object) { // 有一系列的配置 包括页面切换动画什么的
reject('next到其他页面');
// eslint-disable-next-line
return transitionTo.call(this, Intercept, Intercept.NAVTYPE || fnType, navCB,leaveHookCall);
}
});
};
/**
* 核心方法 处理一系列的跳转配置
* @param {Object} rule 当前跳转规则
* @param {Object} fnType 跳转页面的类型方法
* @param {Object} navCB:? 回调函数
* @param {Boolean} leaveHook:? 是否为 beforeRouteLeave 触发的next 到别处 如果是则不再触发 beforeRouteLeave 生命钩子
*
* this 为当前 Router 对象
*/
export const transitionTo = async function (rule, fnType, navCB, leaveHook = false) {
await this.lifeCycle.routerbeforeHooks[0].call(this); // 触发内部跳转前的生命周期
const finalRoute = ruleToUniNavInfo(rule, this.CONFIG.routes); // 获得到最终的 route 对象
const _from = formatFrom(this.CONFIG.routes); // 先根据跳转类型获取 from 数据
const _to = formatTo(finalRoute); // 再根据跳转类型获取 to 数据
try {
const leaveResult = await beforeRouteLeaveHooks.call(this, _from, _to, leaveHook); // 执行页面中的 beforeRouteLeave 生命周期 v1.5.4+
await isNext.call(this, leaveResult, fnType, navCB, true); // 验证当前是否继续 可能需要递归 那么 我们把参数传递过去
const beforeResult = await beforeHooks.call(this, _from, _to); // 执行 beforeEach 生命周期
await isNext.call(this, beforeResult, fnType, navCB); // 验证当前是否继续 可能需要递归 那么 我们把参数传递过去
const enterResult = await beforeEnterHooks.call(this, finalRoute, _from, _to); // 接着执行 beforeEnter 生命周期
await isNext.call(this, enterResult, fnType, navCB); // 再次验证 如果生命钩子多的话应该写成递归或者循环
} catch (e) {
warn(e); // 打印开发者操作的日志
return false;
}
if (navCB) {
navCB.call(this, finalRoute, fnType); // 执行当前回调生命周期
}
afterEachHooks.call(this, _from, _to);
await this.lifeCycle.routerAfterHooks[0].call(this); // 触发内部跳转前的生命周期
};
/**
* 主动触发导航守卫
* @param {Object} Router 当前路由对象
*
* this 当前vue页面组件对象
*/
export const triggerLifeCycle = function (Router) {
const topPage = getCurrentPages()[0];
if (topPage == null) {
return warn('打扰了,当前一个页面也没有 这不是官方的bug是什么??');
}
const { query, page } = getPageVmOrMp(topPage, false);
transitionTo.call(Router, { path: page.route, query }, 'push', async (finalRoute, fnType) => {
let variation = [];
if (`/${page.route}` == finalRoute.route.path) { // 在首页不动的情况下
uniAppHook.pageReady = true; // 标致着路由已经就绪 可能准备起飞
await callwaitHooks.call(this, true);
} else { // 需要跳转
variation = await callwaitHooks.call(this, false); // 只触发app.vue中的生命周期
await uniPushTo(finalRoute, fnType);
}
plus.nativeObj.View.getViewById('router-loadding').close();
callVariationHooks(variation);
uniAppHook.pageReady = true; // 标致着路由已经就绪 可能准备起飞
});
};
/**
* 处理tabbar点击拦截事件
* @param {Object} path 当前需要跳转的tab页面路径
*
* this 为当前 Router 对象
*/
export const beforeTabHooks = function (path) {
transitionTo.call(this, { path: `/${path}`, query: {} }, 'pushTab', (finalRoute, fnType) => {
uniPushTo(finalRoute, fnType);
});
};
import {
proxyLaunchHook, beforeBackHooks, beforeTabHooks, backApiCallHook,
} from './hooks';
import { Global, uniAppHook } from '../helpers/config';
import { assertCanBack } from './util';
import { warn } from '../helpers/warn';
/**
* 重写掉uni-app的 uni.getLocation 和 uni.chooseLocation APi
* @param {Object} Router 当前路由对象
*/
export const rewriteUniFun = function (Router) {
const oldSwitchTab = uni.switchTab; // 缓存 跳转到 tabBar 页面
uni.switchTab = function ({ url, ...args }, normal = false) {
if (normal === true || uniAppHook.pageReady === false) { // 调用原始的uni-app api
oldSwitchTab({
url,
...args,
});
} else {
if (uniAppHook.pageReady) { // 只有在路由守卫等 处理完所有操作后才能触发
const { path } = Router.$Route; // 获取当前路径
if (path == url) { // 路径相同不执行
return warn(`当前跳转路径:${url} 已在本页面无须跳转`);
}
beforeTabHooks.call(Router, url.substring(1)); // 不要 /
} else {
warn('路由守卫正在忙碌中 不允许执行 ‘uni.switchTab’');
}
}
};
};
/**
* 对当前app做一个动画页面 用来过渡首次next 等待时间过长的尴尬
* @param {Object} Router 当前路由对象
*/
export const registerLoddingPage = function (Router) {
const { loddingPageHook, loddingPageStyle } = Router.CONFIG.APP; // 获取app所有配置
const view = new plus.nativeObj.View('router-loadding', {
top: '0px',
left: '0px',
height: '100%',
width: '100%',
...loddingPageStyle.call(Router),
});
loddingPageHook.call(Router, view); // 触发等待页面生命周期
};
/**
* 移除当前 页面上 非router 声明的 onBackPress 事件
* @param {Object} page 当前 vue 组件对象
* @param {Object} options 当前page对象的 $options
* 修复 https://github.com/SilurianYang/uni-simple-router/issues/106
*/
export const removeBackPressEvent = function (page, options) {
const isBack = assertCanBack(page);
if (isBack) { // 可返回
options.onBackPress = [options.onBackPress[0]]; // 路由混入的都干掉
}
};
/**
* 判断当前页面是否需要拦截返回
*
* @param {Object} page 当前 vue 组件对象
* @param {Object} options 当前 vue 组件对象下的$options对象
* @param {Array} args 当前页面是点击头部返回还是底部返回
* 修复 https://github.com/SilurianYang/uni-simple-router/issues/66
*
* this 为当前 Router 对象
*/
export const pageIsHeadBack = function (page, options, args) {
if (args[0].from == 'navigateBack') { // 调用api返回
if (Global.LockStatus) { // 正在跳转的时候 返回按键按的太快啦
warn('当前页面正在处于跳转状态,请稍后再进行跳转....');
return true;
}
Global.LockStatus = true; // 设置为锁住状态
backApiCallHook.call(this, options, args);
return true;
}
const isBack = assertCanBack(page);
if (isBack) { // 可返回
if (Global.LockStatus) { // 正在跳转的时候 返回按键按的太快啦
warn('当前页面正在处于跳转状态,请稍后再进行跳转....');
return true;
}
Global.LockStatus = true; // 设置为锁住状态
beforeBackHooks.call(this, options, args);
return true;
}
return false;
};
/**
* 开始初始化app端路由配置
*
* @param {Object} Router
*
* this 为当前 page 对象
*/
export const appInit = function (Router) {
proxyLaunchHook.call(this);
const { holdTabbar } = Router.CONFIG.APP;
if (holdTabbar) { // 开启tab拦截时
rewriteUniFun(Router);
}
registerLoddingPage(Router);
};
import { methods, baseConfig, Global } from '../helpers/config';
import { noop, formatURLQuery } from '../helpers/util';
let stop = null;
/**
* @param {Object} finalRoute 格式化后的路由跳转规则
* @param {Object} NAVTYPE 需要调用的跳转方法
*/
const uniPushTo = function (finalRoute, NAVTYPE) {
return new Promise((resolve) => {
const query = formatURLQuery(`?${finalRoute.uniRoute.query}`);
const { APP } = baseConfig;
const { url } = finalRoute.uniRoute;
stop = setTimeout(() => {
resolve(url);
resolve = noop; // 执行完了就没了 确保不会被下一次执行
Global.LockStatus = false; // 跳转完成解锁状态
}, APP.switchPageOutTime);
uni[methods[NAVTYPE]]({
url: url + query,
...finalRoute.route.animation,
complete: () => {
clearTimeout(stop);
resolve(url);
resolve = noop; // 执行完了就没了 确保不会被下一次执行
Global.LockStatus = false; // 跳转完成解锁状态
},
}, true); // 这里传递true 主要是兼容重写 uni.switchTab
});
};
export default uniPushTo;
import { err } from '../helpers/warn';
import { copyObject, parseQuery } from '../helpers/util';
import { Global, route as mergeRoute } from '../helpers/config';
/**
* 触发指定生命钩子
* @param {Array} funList //需要执行的方法列表
* @param {Object} args //触发生命钩子传递的参数
*/
export const callAppHook = function (funList = [], args) {
for (let i = 0; i < funList.length; i += 1) {
funList[i].call(this, args);
}
};
/**
* @param {Number} index //需要获取的页面下标 -2:表示获取最后一个即当前页面 -1:表示全部 -3:当前页面的前一个页面
* @param {Boolean} all //是否获取全部的页面
*/
export const getPages = function (index = -1, all) {
const pages = getCurrentPages(all);
if (index === -1) {
return pages;
}
if (index === -2) {
return pages[pages.length - 1];
}
if (index === -3) {
return pages[pages.length - 2];
}
return pages[index];
};
/**
* 验证当前页面是否为nvue页面
* @param {Object} page 当前页面对象
*/
export const isNvuePage = function (page) {
const cstr = page.constructor.name;
const pageType = {
s: true,
z: false,
};
return pageType[cstr];
};
/**
* @param {Object} page //当前顶级页面对象
* @param {Object} vim:? //是否获取 $vm 对象还是 $mp 对象
*/
export const getPageVmOrMp = function (page, vim = true) {
if (vim) {
return page.$vm;
}
if (page.$vm.$mp) {
return page.$vm.$mp;
}
if (isNvuePage(page)) { // nvue 页面
return {
page,
query: page.__displayReporter.query,
};
}
};
/**
* 获取 to 的配置参数
* @param {Object} rule 当前跳转的规则
*/
export const formatTo = function (finalRoute) {
const route = copyObject(finalRoute.route);
const { rule } = finalRoute;
route.query = rule.query || rule.params || {};
return route;
};
/**
* 通过一个未知的路径或者名称 在路由表中查找指定路由表 并返回
* @param {string} type //path 或者 name
* @param {Object} routes //当前对象的所有路由表
*/
export const pathOrNameToRoute = function (type, routes = Global.Router.CONFIG.routes) {
const routesKeys = Object.keys(routes);
for (let i = 0; i < routesKeys.length; i += 1) {
const key = routesKeys[i];
const item = routes[key];
if (item.path === `/${type}`) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
if (item.path === type) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
if (item.name == type) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
}
err(`当前 '${type}' 在路由表中没有找到匹配的 name 或者 path`);
};
/**
* 统一格式话 路由传递的参数 看看是编码还是非编码 做相应的对策
*
* @param {Object} query 当前的路由参数
* @param {Boolean} getter 是从页面获取 route 对象下的参数 还是编码后传输
*/
export const getFormatQuery = function (query = {}) {
if (Global.Router.CONFIG.encodeURI) {
try {
query = JSON.parse(decodeURIComponent(query.query || encodeURIComponent('{}')));
} catch (e) {
query = JSON.parse(query.query);
}
}
return query;
};
/**
* 获取 from 的配置参数 from 页面永远都是站在当前页面忘其它地方走 所以都是最后一个页面
*
* @param {Object} routes //当前对象的所有路由表
*/
export const formatFrom = function (routes) {
const topPage = getPages(-2);
const { page, query } = getPageVmOrMp(topPage, false);
const route = pathOrNameToRoute(page.route, routes); // 获取到当前路由表下的 route
route.query = getFormatQuery(query); // 不管是编码传输还是非编码 最后都得在 to/from 中换成json对象
return route;
};
/**
*
* 把用户的跳转路由规则格式化成uni-app可用的路由跳转规则
*
* @param {Object} rule //当前用户跳转的路由规则
* @param {Object} routes //当前simple-router 下的路由表
*/
export const ruleToUniNavInfo = function (rule, routes) {
if (rule == null) {
return err('当前跳转规则为空,请检查跳转代码');
}
// eslint-disable-next-line
let [navType, route, query, animation] = ['path', null, {}, {}];
if (rule.constructor === String) { // 是字符串类型 那当前就是路径啦
route = pathOrNameToRoute(rule, routes); // 直接把 rule 当 path 传递 完事
} else if (rule.constructor === Object) { // 对象类型 可以是 path 或者 name
route = pathOrNameToRoute(rule.path || (navType = 'name', rule.name), routes); // 两则必有其一 报错自己处理
query = rule.query || rule.params || {};
animation = rule.animation || {};
} else {
return err('传的什么乱七八糟的类型?路由跳转规则只认字符串 \'path\' , 对象 \'path\' , 对象 \'name\' ');
}
animation = { ...Global.Router.CONFIG.APP.animation, ...route.animation || {}, ...animation }; // 合并多种方式声明的动画效果
route.animation = animation; // 这才是最终的页面切换效果
// 路径处理完后 开始格式化参数
const uniRoute = parseQuery(route.path, query); // uni-app 需要的跳转规则
return {
rule,
route,
uniRoute,
};
};
/**
* 获取当前页面下的 Route 信息
*
* @param {Object} pages 获取页面对象集合
* @param {Object} Vim 用户传递的当前页面对象
*/
export const APPGetPageRoute = function (pages, Vim) {
let [query, path] = [{}, ''];
const page = pages[pages.length - 1]; // 获取到当前页面
if (pages.length > 0) {
query = getFormatQuery(page.options, true);
path = page.route;
} else if (Vim != null) {
query = getFormatQuery(Vim.$mp.page.options, true);
path = page.route;
}
const route = pathOrNameToRoute(path);
route.query = query;
return route;
};
/**
* 获取当前页面下的 onBeforeBack 生命周期并执行
*
* @param {Object} args 当前返回页面时uni-app传递的参数
*/
export const getPageOnBeforeBack = function (args) {
return new Promise(async (resolve) => {
const currPage = getPages(-2); // 获取到当前页面
const { onBeforeBack } = currPage.$vm.$options;
if (onBeforeBack != null && onBeforeBack.constructor === Function) {
const isNext = await onBeforeBack.call(currPage.$vm, args);
if (isNext === true) {
return resolve(false);
}
}
return resolve(true);
});
};
/**
* 断言当前页面是否可返回上一级
* @param {Object} page 当前页面webview对象
*/
export const assertCanBack = function (page) {
const pageStyle = page.$getAppWebview().getStyle();
if (pageStyle.titleNView != null && pageStyle.titleNView.autoBackButton) { // 只有处理有带返回按钮的页面
return true;
}
// 两种情况 1.真的是顶级页面时 2.自定义头部
const { $page } = page;
if ($page && $page.meta.isQuit === false) { // 自定义头部 不是顶级页面
return true;
}
return false; // 不可返回 真的是顶级页面时 返回就直接退出app了
};
import { methods, Global } from '../helpers/config';
import { formatURLQuery } from '../helpers/util';
/**
* @param {Object} finalRoute 格式化后的路由跳转规则
* @param {Object} NAVTYPE 需要调用的跳转方法
*/
const appletsUniPushTo = function (finalRoute, NAVTYPE) {
return new Promise((resolve) => {
const query = formatURLQuery(`?${finalRoute.uniRoute.query}`);
const { url } = finalRoute.uniRoute;
uni[methods[NAVTYPE]]({
url: url + query,
complete: () => {
resolve(url);
Global.LockStatus = false; // 跳转完成解锁状态
},
});
});
};
export default appletsUniPushTo;
import { uniAppHook, Global } from '../helpers/config';
import {
callAppHook, getPageVmOrMp, ruleToUniNavInfo, formatTo, formatFrom, getPages,
} from './util';
import appletsUniPushTo from './appletsNav';
import { noop } from '../helpers/util';
import { warn } from '../helpers/warn';
/**
*
* @param {String} key
* @param {Function} hook 需要执行及还原的生命周期函数
*/
const toutiaoIndexHookCall = function (key, hook) {
const { indexVue } = uniAppHook;
const indeHooks = indexVue[key];
indeHooks.splice(indeHooks.length - 1, 1, hook);
};
/**
* 还原并执行所有 拦截下来的生命周期 app.vue 及 index 下的生命周期
* @param {Boolean} callHome // 是否触发首页的生命周期
*
* this 为当前 page 对象
*/
const callwaitHooks = function (callHome) {
return new Promise(async (resolve) => {
const variation = []; // 存储一下在uni-app上的变异生命钩子 奇葩的要死
const {
appVue, onLaunch, onShow, waitHooks, variationFuns, indexCallHooks,
} = uniAppHook;
const app = appVue.$options;
await onLaunch.fun[onLaunch.fun.length - 1].call(appVue, onLaunch.args); // 确保只执行最后一个 并且强化异步操作
onShow.fun[onShow.fun.length - 1].call(appVue, onShow.args); // onshow 不保证异步 直接确保执行最后一个
if (callHome) { // 触发首页生命周期
// eslint-disable-next-line
for (const key in waitHooks) {
if (indexCallHooks.includes(key)) { // 只有在被包含的情况下才执行
callAppHook.call(this, waitHooks[key].fun);
}
}
}
if (onLaunch.isHijack) { // 还原 onLaunch生命钩子
app.onLaunch.splice(app.onLaunch.length - 1, 1, onLaunch.fun[0]);
}
if (onShow.isHijack) { // 继续还原 onShow
app.onShow.splice(app.onShow.length - 1, 1, onShow.fun[0]);
}
// eslint-disable-next-line
for (const key in waitHooks) { // 还原 首页下的生命钩子
const item = waitHooks[key];
if (item.isHijack) {
if (variationFuns.includes(key)) { // 变异方法
variation.push({ key, fun: item.fun[0] });
} else {
toutiaoIndexHookCall(key, item.fun[0]);
}
}
}
resolve(variation);
});
};
/**
* 还原剩下的奇葩生命钩子
* @param {Object} variation 当前uni-app中的一些变异方法 奇葩生命钩子
*/
const callVariationHooks = function (variation) {
for (let i = 0; i < variation.length; i += 1) {
const { key, fun } = variation[i];
toutiaoIndexHookCall(key, fun);
}
};
/**
* 主要是对app.vue下onLaunch和onShow生命周期进行劫持
*
* this 为当前 page 对象
*/
export const proxyLaunchHook = function () {
const {
onLaunch,
onShow,
} = this.$options;
uniAppHook.appVue = this; // 缓存 当前app.vue组件对象
if (onLaunch.length > 1) { // 确保有写 onLaunch 可能有其他混入 那也办法
uniAppHook.onLaunch.isHijack = true;
uniAppHook.onLaunch.fun = onLaunch.splice(onLaunch.length - 1, 1, (arg) => {
uniAppHook.onLaunch.args = arg;
}); // 替换uni-app自带的生命周期
}
if (onShow.length > 0) {
uniAppHook.onShow.isHijack = true;
uniAppHook.onShow.fun = onShow.splice(onShow.length - 1, 1, (arg) => {
uniAppHook.onShow.args = arg;
if (uniAppHook.pageReady) { // 因为还有app切前台后台的操作
callAppHook.call(this, uniAppHook.onShow.fun, arg);
}
}); // 替换替换 都替换
}
};
/**
* 触发全局beforeHooks 生命钩子
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const beforeHooks = function (_from, _to) {
return new Promise(async (resolve) => {
const beforeHooksFun = this.lifeCycle.beforeHooks[0];
if (beforeHooksFun == null) {
return resolve();
}
await beforeHooksFun.call(this, _to, _from, resolve);
});
};
/**
* 触发全局afterEachHooks 生命钩子
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const afterEachHooks = function (_from, _to) {
const afterHooks = this.lifeCycle.afterHooks[0];
if (afterHooks != null && afterHooks.constructor === Function) {
afterHooks.call(this, _to, _from);
}
};
/**
* 触发全局 beforeEnter 生命钩子
* @param {Object} finalRoute // 当前格式化后的路由参数
* @param {Object} _from // from 参数
* @param {Object} _to // to 参数
*
* this 为当前 Router 对象
*/
const beforeEnterHooks = function (finalRoute, _from, _to) {
return new Promise(async (resolve) => {
const { beforeEnter } = finalRoute.route;
if (beforeEnter == null || beforeEnter.constructor !== Function) { // 当前这个beforeEnter不存在 或者类型错误
return resolve();
}
await beforeEnter.call(this, _to, _from, resolve);
});
};
/**
* v1.5.4+
* beforeRouteLeave 生命周期
* @param {Object} to 将要去的那个页面 to对象
* @param {Object} from 从那个页面触发的 from对象
* @param {Boolean} leaveHook:? 是否为 beforeRouteLeave 触发的next 到别处 如果是则不再触发 beforeRouteLeave 生命钩子
* this 为当前 Router 对象
*/
const beforeRouteLeaveHooks = function (from, to, leaveHook) {
return new Promise(async (resolve) => {
if (leaveHook) { // 我们知道这个是来自页面beforeRouteLeave next到其他地方,所有不必再执行啦
warn('beforeRouteLeave next到其他地方,无须再执行!');
return resolve();
}
if (from.path == to.path) { // 进入首页的时候不触发
return resolve();
}
const currentPage = getPages(-2); // 获取到全部的页面对象
const callThis = getPageVmOrMp(currentPage); // 获取到页面的 $vm 对象 及 page页面的this对象
const { beforeRouteLeave } = callThis.$options; // 查看当前是否有开发者声明
if (beforeRouteLeave == null) {
warn('当前页面下无 beforeRouteLeave 钩子声明,无须执行!');
return resolve();
}
if (beforeRouteLeave != null && beforeRouteLeave.constructor !== Function) {
warn('beforeRouteLeave 生命钩子声明错误,必须是一个函数!');
return resolve();
}
await beforeRouteLeave.call(callThis, to, from, resolve); // 执行生命钩子
});
};
/**
* 核心方法 处理一系列的跳转配置
* @param {Object} rule 当前跳转规则
* @param {Object} fnType 跳转页面的类型方法
* @param {Object} navCB:? 回调函数
* @param {Boolean} leaveHook:? 是否为 beforeRouteLeave 触发的next 到别处 如果是则不再触发 beforeRouteLeave 生命钩子
* this 为当前 Router 对象
*
*/
export const appletsTransitionTo = async function (rule, fnType, navCB, leaveHook = false) {
await this.lifeCycle.routerbeforeHooks[0].call(this); // 触发内部跳转前的生命周期
const finalRoute = ruleToUniNavInfo(rule, this.CONFIG.routes); // 获得到最终的 route 对象
const _from = formatFrom(this.CONFIG.routes); // 先根据跳转类型获取 from 数据
const _to = formatTo(finalRoute); // 再根据跳转类型获取 to 数据
try {
const leaveResult = await beforeRouteLeaveHooks.call(this, _from, _to, leaveHook); // 执行页面中的 beforeRouteLeave 生命周期 v1.5.4+
// eslint-disable-next-line
await isNext.call(this, leaveResult, fnType, navCB,true); // 验证当前是否继续 可能需要递归 那么 我们把参数传递过去
const beforeResult = await beforeHooks.call(this, _from, _to); // 执行 beforeEach 生命周期
// eslint-disable-next-line
await isNext.call(this, beforeResult, fnType, navCB); // 验证当前是否继续 可能需要递归 那么 我们把参数传递过去
const enterResult = await beforeEnterHooks.call(this, finalRoute, _from, _to); // 接着执行 beforeEnter 生命周期
// eslint-disable-next-line
await isNext.call(this, enterResult, fnType, navCB); // 再次验证 如果生命钩子多的话应该写成递归或者循环
} catch (e) {
warn(e); // 打印开发者操作的日志
return false;
}
if (navCB) {
navCB.call(this, finalRoute, fnType); // 执行当前回调生命周期
}
afterEachHooks.call(this, _from, _to);
await this.lifeCycle.routerAfterHooks[0].call(this); // 触发内部跳转前的生命周期
};
/**
* 触发全局 返回事件
* @param {Number} backLayer 需要返回的页面层级
* @param {Function} next 正真的回调函数
*
* this 为当前 Router 对象
*/
export const backCallHook = function (backLayer, next) {
const pages = getPages(); // 获取到全部的页面对象
const toPage = pages.reverse()[backLayer];
if (toPage == null) { // 没有匹配到的时候
return warn('亲爱的开发者,你确定页面栈中有这么多历史记录给你返回?');
}
const { query, page } = getPageVmOrMp(toPage, false);
const beforeFntype = 'RouterBack';
appletsTransitionTo.call(this, { path: page.route, query }, beforeFntype, (finalRoute, fnType) => {
const toPath = finalRoute.uniRoute.url;
if (`/${page.route}` == toPath || page.route == toPath) { // 直接调用返回api
next();
} else { // 有拦截到其他页面时
if (fnType == beforeFntype) {
return warn('调用返回api被拦截到其他页面需要指定合理的 ‘NAVTYPE’ ');
}
appletsUniPushTo(finalRoute, fnType);
}
});
};
/**
* 主动触发导航守卫
* @param {Object} Router 当前路由对象
*
*/
export const triggerLifeCycle = function (Router) {
const topPage = getCurrentPages()[0];
if (topPage == null) {
return warn('打扰了,当前一个页面也没有 这不是官方的bug是什么??');
}
const { query, page } = getPageVmOrMp(topPage, false);
appletsTransitionTo.call(Router, { path: page.route, query }, 'push', async (finalRoute, fnType) => {
let variation = [];
if (`/${page.route}` == finalRoute.route.path || page.route == finalRoute.route.path) { // 在首页不动的情况下
uniAppHook.pageReady = true; // 标致着路由已经就绪 可能准备起飞
await callwaitHooks.call(this, true);
} else { // 需要跳转
variation = await callwaitHooks.call(this, false); // 只触发app.vue中的生命周期
await appletsUniPushTo(finalRoute, fnType);
}
uniAppHook.pageReady = true; // 标致着路由已经就绪 可能准备起飞
callVariationHooks(variation);
});
};
/**
* 把指定页面的生命钩子函数保存并替换
* this 为当前 page 对象
*/
export const appletsProxyIndexHook = function (Router) {
if (process.env.VUE_APP_PLATFORM == 'mp-toutiao') { // 头条小程序首页生命周期由我们手动触发,缓存this
uniAppHook.toutiaoIndexThis = this;
}
const { needHooks, waitHooks } = uniAppHook;
const options = this.$options;
uniAppHook.indexVue = options;
for (let i = 0; i < needHooks.length; i += 1) {
const key = needHooks[i];
if (options[key] != null) { // 只劫持开发者声明的生命周期
const { length } = options[key];
// eslint-disable-next-line
const whObject= waitHooks[key]={};
whObject.fun = options[key].splice(length - 1, 1, noop); // 把实际的页面生命钩子函数缓存起来,替换原有的生命钩子
whObject.isHijack = true;
}
}
triggerLifeCycle.call(this, Router); // 接着 主动我们触发导航守卫
};
/**
* 验证当前 next() 管道函数是否支持下一步
*
* @param {Object} Intercept 拦截到的新路由规则
* @param {Object} fnType 跳转页面的类型方法 原始的
* @param {Object} navCB 回调函数 原始的
* @param {Boolean} leaveHookCall:? 是否为 beforeRouteLeave 触发的next 做拦截判断
* this 为当前 Router 对象
*
*/
const isNext = function (Intercept, fnType, navCB, leaveHookCall = false) {
return new Promise((resolve, reject) => {
if (Intercept == null) { // 什么也不做 直接执行下一个钩子
return resolve();
}
if (Intercept === false) { // 路由中断 我们需要把防抖设置为false
Global.LockStatus = false; // 解锁跳转状态
return reject('路由终止');
}
if (Intercept.constructor === String) { // 说明 开发者直接传的path 并且没有指定 NAVTYPE 那么采用原来的navType
reject('next到其他页面');
return appletsTransitionTo.call(this, Intercept, fnType, navCB, leaveHookCall);
}
if (Intercept.constructor === Object) { // 有一系列的配置 包括页面切换动画什么的
reject('next到其他页面');
return appletsTransitionTo.call(this, Intercept, Intercept.NAVTYPE || fnType, navCB, leaveHookCall);
}
});
};
import { proxyLaunchHook } from './hooks';
/**
* 开始初始化app端路由配置
*
* @param {Object} Router 当前Router对象
*
* this 为当前 page 对象
*/
const appletsInit = function () {
proxyLaunchHook.call(this);
};
export default appletsInit;
import { Global, route as mergeRoute } from '../helpers/config';
import { copyObject, parseQuery } from '../helpers/util';
import { err } from '../helpers/warn';
import { baiduApple, touTiao } from '../helpers/compile';
/**
* 触发指定生命钩子
* @param {Array} funList //需要执行的方法列表
* @param {Object} args //触发生命钩子传递的参数
*/
export const callAppHook = function (funList, args) {
for (let i = 0; i < funList.length; i += 1) {
funList[i].call(this, args);
}
};
/**
* @param {Object} page //当前顶级页面对象
* @param {Object} vim:? //是否获取 $vm 对象还是 $mp 对象
*/
export const getPageVmOrMp = function (page, vim = true) {
if (vim) {
return page.$vm;
}
const { $mp } = page.$vm;
baiduApple(() => { // 百度小程序新增一个route属性
$mp.page.route = $mp.page.is;
});
touTiao(() => { // 头条小程序新增一个route属性
$mp.page.route = $mp.page.is;
});
return $mp;
};
/**
* 统一格式话 路由传递的参数 看看是编码还是非编码 做相应的对策
*
* @param {Object} query 当前的路由参数
* @param {Boolean} getter 是从页面获取 route 对象下的参数 还是编码后传输
*/
export const getFormatQuery = function (query = {}, getter = false) {
if (Global.Router.CONFIG.encodeURI) {
if (getter) {
try { // 除去微信小程序都不需要 decodeURIComponent
query = JSON.parse(decodeURIComponent(query.query) || '{}');
} catch (e) { // 其他小程序
query = JSON.parse(query.query || '{}');
}
} else {
try {
query = JSON.parse(decodeURIComponent(query.query || encodeURIComponent('{}')));
} catch (e) {
query = JSON.parse(query.query);
}
}
}
return query;
};
/**
* @param {Number} index //需要获取的页面下标 -2:表示获取最后一个即当前页面 -1:表示全部 -3:当前页面的前一个页面
* @param {Boolean} all //是否获取全部的页面
*/
export const getPages = function (index = -1, all) {
const pages = getCurrentPages(all);
if (index === -1) {
return pages;
}
if (index === -2) {
return pages[pages.length - 1];
}
if (index === -3) {
return pages[pages.length - 2];
}
return pages[index];
};
/**
* 通过一个未知的路径或者名称 在路由表中查找指定路由表 并返回
* @param {string} type //path 或者 name
* @param {Object} routes //当前对象的所有路由表
*/
export const pathOrNameToRoute = function (type, routes = Global.Router.CONFIG.routes) {
const routesKeys = Object.keys(routes);
for (let i = 0; i < routesKeys.length; i += 1) {
const key = routesKeys[i];
const item = routes[key];
if (item.path === `/${type}`) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
if (item.path === type) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
if (item.name == type) {
return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
}
}
err(`当前 '${type}' 在路由表中没有找到匹配的 name 或者 path`);
};
/**
* 获取 to 的配置参数
* @param {Object} rule 当前跳转的规则
*/
export const formatTo = function (finalRoute) {
const route = copyObject(finalRoute.route);
const { rule } = finalRoute;
route.query = rule.query || rule.params || {};
return route;
};
/**
* 获取 from 的配置参数 from 页面永远都是站在当前页面忘其它地方走 所以都是最后一个页面
*
* @param {Object} routes //当前对象的所有路由表
*/
export const formatFrom = function (routes) {
const topPage = getPages(-2);
const { page, query } = getPageVmOrMp(topPage, false);
const route = pathOrNameToRoute(page.route, routes); // 获取到当前路由表下的 route
route.query = getFormatQuery(query); // 不管是编码传输还是非编码 最后都得在 to/from 中换成json对象
return route;
};
/**
*
* 把用户的跳转路由规则格式化成uni-app可用的路由跳转规则
*
* @param {Object} rule //当前用户跳转的路由规则
* @param {Object} routes //当前simple-router 下的路由表
*/
export const ruleToUniNavInfo = function (rule, routes) {
if (rule == null) {
return err('当前跳转规则为空,请检查跳转代码');
}
// eslint-disable-next-line
let [navType, route, query] = ['path', null, {}];
if (rule.constructor === String) { // 是字符串类型 那当前就是路径啦
route = pathOrNameToRoute(rule, routes); // 直接把 rule 当 path 传递 完事
} else if (rule.constructor === Object) { // 对象类型 可以是 path 或者 name
route = pathOrNameToRoute(rule.path || (navType = 'name', rule.name), routes); // 两则必有其一 报错自己处理
query = rule.query || rule.params || {};
} else {
return err('传的什么乱七八糟的类型?路由跳转规则只认字符串 \'path\' , 对象 \'path\' , 对象 \'name\' ');
}
// 路径处理完后 开始格式化参数
const uniRoute = parseQuery(route.path, query); // uni-app 需要的跳转规则
return {
rule,
route,
uniRoute,
};
};
/**
* 获取当前页面下的 Route 信息
*
* @param {Object} pages 获取页面对象集合
* @param {Object} Vim 用户传递的当前页面对象
*/
export const AppletsPageRoute = function (pages, Vim) {
let [query, path] = [{}, ''];
const page = pages[pages.length - 1]; // 获取到当前页面
if (pages.length > 0) {
const uniQuery = getPageVmOrMp(page, false).query;
query = getFormatQuery(uniQuery, true);
path = page.route;
} else if (Vim != null) {
query = getFormatQuery(Vim.$mp.page.options, true);
path = page.route;
}
const route = pathOrNameToRoute(path);
route.query = query;
return route;
};
const render = function (node) {
if (typeof node == 'string') { // 是一个文本节点
return document.createTextNode(node);
}
if (node instanceof HTMLElement) {
return node;
}
// eslint-disable-next-line
return createElement(node);
};
/**
* 根据标签及属性创建一个dom
*/
const createElement = function ({
tag,
attrs,
children,
} = {}) {
const $el = document.createElement(tag);
// eslint-disable-next-line
for (const [k, v] of Object.entries(attrs)) {
$el.setAttribute(k, v);
}
// eslint-disable-next-line
for (const item of children) {
$el.appendChild(render(item));
}
return $el;
};
const html = createElement({
tag: 'div',
attrs: {
id: 'router-loadding',
},
children: [
createElement({
tag: 'div',
attrs: {
class: 'loadding',
},
children: [],
}),
],
});
/* eslint-disable */
const style = createElement({
tag: 'style',
attrs: {
id: 'HHYANG_style',
},
children: [
`
body{padding:0;margin:0}#router-loadding{position:fixed;width:100%;height:3px;transition:all .05s;top:0;z-index:9999999999999999;}#router-loadding .loadding{position:fixed;top:0;height:3px;background-color:#47b14b;width:0;box-shadow:0 0 15px #4CAF50;transition:all .8s;border-top-right-radius:3px;border-bottom-right-radius:3px}
`,
],
});
const script = createElement({
tag: 'script',
attrs: {
id: 'HHYANG_script',
},
children: [
`
var HHYANG_El=document.querySelector("#router-loadding .loadding"),HHYANG_Pel=document.querySelector("#router-loadding"),w=0,stop=null,WH=window.innerWidth,loop=function(){w=w>=WH-35?w+parseInt(5*Math.random()):w+parseInt(35*Math.random());HHYANG_El.style.cssText="width:"+w+"px";w>=WH&&clearInterval(stop)};window.startLodding=function(a){a=void 0===a?500:a;HHYANG_Pel.style.cssText="display: block;";HHYANG_El.style.cssText="transition: all 0.8s;";w=0;clearInterval(stop);stop=setInterval(function(){loop()},a)};window.stopLodding=function(a){a=void 0===a?200:a;clearInterval(stop);HHYANG_El.style.cssText="width:"+WH+"px;transition: all "+a/1E3+"s;";HHYANG_Pel.style.cssText="opacity: 0;transition: all "+a/1E3+"s;";setTimeout(function(){HHYANG_Pel.style.cssText="display: none;";HHYANG_El.style.cssText="width:0px";w=0},a)};
`,
],
});
export const DOM = {
style,
html,
script,
};
/* eslint-enable */
<template>
<view @click="gotoPage()"><slot></slot></view>
</template>
<script>
const navType = {
push: 'push',
replace: 'replace',
replaceAll: 'replaceAll',
pushTab: 'pushTab'
};
export default {
props: {
to: {
type: [String, Object],
},
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) {
text = text.replace(/\'/g, '');
text = text.replace(/(\w+)(?=:)/g, function(val) {
return `"${val}"`;
});
text = text.replace(/:\s*([^,{}\s"]+)/g, function(val) {
const arr = val.split(':');
return `:"${arr[1].trim()}"`;
});
try {
text = JSON.parse(text);
} catch (e) {}
}
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>
<style></style>
export const H5 = function (fn) {
// #ifdef H5
fn();
// #endif
};
export const APP = function (fn) {
// #ifdef APP-PLUS
fn();
// #endif
};
export const applets = function (fn) {
// #ifdef MP
fn();
// #endif
};
export const notH5 = function (fn) {
// #ifndef H5
fn();
// #endif
};
export const baiduApple = function (fn) {
// #ifdef MP-BAIDU
fn();
// #endif
};
export const touTiao = function (fn) {
// #ifdef MP-TOUTIAO
fn();
// #endif
};
export const mp = function (fn) {
// #ifdef MP
fn();
// #endif
};
export const baseConfig = {
h5: {
rewriteFun: true, // 是否对uni-app reLaunch/navigateBack 两个方法重写 处理uni刷新直接返回到首页和触发路由守卫
paramsToQuery: false, // h5端上通过params传参时规则是vue-router 刷新会丢失 开启此开关将变成?连接的方式
loading: true, // 是否显示加载动画
hinderTab: false, // 是否拦截uni-app自带底部菜单 TODO
vueRouterDev: false, // 完全使用采用vue-router的开发模式
useUniConfig: true, // 是否采用在pages.json下的所有页面配置信息,false时需开发者自行设置页面
keepUniIntercept: false, // 保留uni-app使用vue-router的拦截器
vueNext: false, // 在next管道函数中是否获取vueRouter next的原本参数
replaceStyle: false, // 是否对resetStyle函数中返回的style节点进行全部替换,否则为追加
resetStyle: () => JSON.parse('{}'), // 自定义加载样式函数 可返回一个包涵 html、style、script 的对象来重置Router内置的加载动画
mode: 'hash',
base: '/',
linkActiveClass: 'router-link-active',
linkExactActiveClass: 'router-link-exact-active',
scrollBehavior: (to, from, savedPostion) => savedPostion,
fallback: true,
},
APP: {
holdTabbar: true, // 是否开启底部菜单拦截
loddingPageStyle: () => JSON.parse('{"backgroundColor":"#FFF"}'), // 当前等待页面的样式 必须返回一个json
loddingPageHook: (view) => { plus.navigator.closeSplashscreen(); view.show(); }, // 刚刚打开页面处于等待状态,会触发此事件
animation: { animationType: 'pop-in', animationDuration: 300 }, // 页面切换动画
switchPageOutTime: 1000, // 最高能忍耐的页面切换时间 达到此时间 不管切换有没有完成都会显示页面出来 这对启动页帮助很大
},
debugger: false, // 是否处于开发阶段 设置为true则打印日志
encodeURI: true, // 是否对url传递的参数进行编码
routerBeforeEach: () => {}, // router 前置路由函数 每次触发跳转前先会触发此函数
routerAfterEach: () => {}, // router 后置路由函数 每次触发跳转后会触发此函数
routes: [],
};
export const methods = {
push: 'navigateTo',
replace: 'redirectTo',
replaceAll: 'reLaunch',
pushTab: 'switchTab',
back: 'navigateBack',
};
export const H5FnTypeToggle = {
push: 'push',
replace: 'replace',
replaceAll: 'replace',
pushTab: 'replace',
};
export const lifeCycle = {
beforeHooks: [],
afterHooks: [],
routerHooks: [],
routerbeforeHooks: [], // 内部跳转前生命周期
routerAfterHooks: [], // 内部跳转后生命周期
};
export const Global = { // 缓存一些必要的对象,作为全局可以访问的参数
$parseQuery: null, // url query 帮助类实例
Router: {},
vueRouter: {},
addedRoutes: [], // 用于缓存用户动态添加的路由
RouterReadyPromise: () => {},
H5RouterReady: null, // 当前router是否就绪
backLayerC: 1, // 返回api调用时开发者传递的 delta
LockStatus: false, // 当前是否正在进行跳转 正在跳转调用api是不给跳转的
};
export const uniAppHook = {
indexVue: {}, // 首页 组件对象
toutiaoIndexThis: {}, // 头条小程序Index this对象
appVue: {}, // 同getApp()获取到的对象一毛一样的 其实就是app.vue组件
onLaunch: { fun: [], args: {}, isHijack: false }, // 这两个是app.vue
onShow: { fun: [], args: {}, isHijack: false },
variationFuns: ['onReady', 'onUnload'], // 一些uni-app的变异方法 需要处理下
waitHooks: {}, // 首页等待中的生命钩子 一些需要等待的Hooks,就是在页面没有进来之前一些提前触发的生命钩子 主要是用户已经声明好的
indexCallHooks: ['onLoad', 'onReady', 'created', 'onShow'], // 在首页首次启动时需要触发的生命周期
needHooks: ['onLoad', 'onReady', 'onShow', 'created', 'onHide', 'onUnload', 'onResize'], // 首页需要拦截的生命钩子
pageReady: false,
onLaunched: false, // 否触发onLaunch事件
};
export const appletsConfig = { // 小程序端的一些路由所需配置
onLaunchEd: false, // 当前小程序端是否触发onLaunch事件
};
export const route = function (object = {}) {
return {
...object,
params: {},
query: {},
};
};
import { uniAppHook } from './config';
import H5init from '../vueRouter/init';
import { appInit, removeBackPressEvent, pageIsHeadBack } from '../appRouter/init';
import appletsInit from '../appletsRouter/init';
import { appPlatform } from './util';
import { proxyIndexHook } from '../appRouter/hooks';
import { appletsProxyIndexHook } from '../appletsRouter/hooks';
/**
* 获取一些需要在各个平台混入的事件
* @param {Object} Router 当前原始路由对象
*/
const getMixins = function (Router) {
return {
H5: {
beforeCreate() {
if (this.$options.router) {
H5init(Router.$root, this.$options.router, this);
}
},
},
APP: {
onLaunch() {
uniAppHook.onLaunched = true; // 标志已经触发了 onLaunch 事件
appInit.call(this, Router.$root);
},
onLoad() {
// 第一个页面 拦截所有生命周期
if (uniAppHook.onLaunched && !uniAppHook.pageReady) {
uniAppHook.onLaunched = false;
proxyIndexHook.call(this, Router.$root);
}
removeBackPressEvent(this.$mp.page, this.$options); // 移除页面的onBackPress事件
},
onBackPress(...args) {
return pageIsHeadBack.call(Router.$root, this.$mp.page, this.$options, args);
},
},
APPLETS: {
onLaunch() {
uniAppHook.onLaunched = true; // 标志已经触发了 onLaunch 事件
appletsInit.call(this, Router.$root);
},
onLoad() {
if (uniAppHook.onLaunched && !uniAppHook.pageReady) { // 必须是第一个页面
uniAppHook.onLaunched = false;
appletsProxyIndexHook.call(this, Router.$root);
}
},
},
};
};
const initMixins = function (Vue, Router) {
Vue.mixin({
...getMixins(Router)[appPlatform(true)],
});
};
export default initMixins;
import { appPlatform } from './util';
import { methods, H5FnTypeToggle, Global } from './config';
import { transitionTo } from '../appRouter/hooks';
import { appletsTransitionTo, backCallHook } from '../appletsRouter/hooks';
import uniPushTo from '../appRouter/uniNav';
import appletsUniPushTo from '../appletsRouter/appletsNav';
import { err, warn } from './warn';
import H5PushTo from '../vueRouter/routerNav';
import * as compile from './compile';
/**
* 返回api 触发的公共函数
* @param {Object/String} rule 当前跳转规则
* @param {String} fnType 跳转页面的类型方法
*
* this 为当前 Router 实例
*/
const isBcakNav = function ({
backLayer,
delta,
H5PATCH,
}) {
compile.H5(() => {
H5PATCH.on('historyBack', {
backLayer,
delta,
});
});
compile.APP(() => {
Global.backLayerC = backLayer; // 告诉路由需要返回几层
uni.navigateBack({
delta: backLayer,
complete: () => {
Global.LockStatus = false; // 跳转完成解锁状态
},
});
});
compile.mp(() => {
backCallHook.call(this, backLayer, () => {
uni.navigateBack({
delta: backLayer,
});
});
});
};
/**
* 非 返回api 触发的公共函数
* @param {Object/String} rule 当前跳转规则
* @param {String} fnType 跳转页面的类型方法
*
* this 为当前 Router 实例
*/
const notBackNav = function (rule, fnType) {
if (rule == null) {
return err('跳转规则为空,不允许这样操作');
}
if (rule.constructor === String) { // 单独 path 的情况 允许?拼接参数
const ruleArray = rule.split('?');
if (ruleArray.length > 1) {
rule = {
path: ruleArray[0],
query: Global.$parseQuery.parse(ruleArray[1]),
};
}
}
switch (appPlatform(true)) {
case 'H5':
return H5PushTo.call(this, H5FnTypeToggle[fnType], rule, methods[fnType]);
case 'APP':
Global.LockStatus = true; // 设置为锁住状态
return transitionTo.call(this, rule, fnType, uniPushTo);
case 'APPLETS':
Global.LockStatus = true; // 设置为锁住状态
return appletsTransitionTo.call(this, rule, fnType, appletsUniPushTo);
default:
err('糟糕!!!还有其他的执行环境???没听说过啊。一脸懵逼???加QQ群问问:769241495');
break;
}
};
/**
* 处理正在跳转的公共api
* @param {Object/String} rule 当前跳转规则
* @param {String} fnType 跳转页面的类型方法
* @param {Boolean} isBack 是否通过 back() api 调用的 默认为false
* @param {Boolean} enforce 是否强制越过跳转加锁检查 默认false 目前只有back() api 传递了
*
* this 为当前 Router 实例
*/
const navjump = function (rule, fnType, isBack = false, enforce = false) {
if (Global.LockStatus && !enforce) { // 正在跳转的状态下 给出提示正在跳转
return warn('当前页面正在处于跳转状态,请稍后再进行跳转....');
}
if (isBack) { // 是返回api触发的
return isBcakNav.call(this, rule, fnType);
}
return notBackNav.call(this, rule, fnType);
};
export default navjump;
import { Global } from './config';
import { warn, err } from './warn';
const nodeURL = require('query-string');
class ParseQuery {
get queryName() {
return nodeURL;
}
/**
* 判断当前这个对象是否为深度对象
* @param {Object} obj
*/
isDepthObject(obj) {
const str = JSON.stringify(obj);
return str.match(/}/g).length > 1;
}
/**
* 从URL中提取查询字符串
* @param {String} url
*/
extract(url) {
return nodeURL.extract(url);
}
/**
* 把一个 key=value&key1=value 的字符串转成对象
* @param {string} strQuery key=value&key1=value 类型的字符串
*/
parse(strQuery) {
return nodeURL.parse(strQuery);
}
/**
* 把一个对象转成 key=value&key1=value 类型的字符串
* @param {Object} ObjQuery 符合js标注的对象
* @param {Boolean} intact 是否在转成的字符串前添加?号
*/
stringify(ObjQuery, intact = true) {
const strQuery = nodeURL.stringify(ObjQuery);
if (intact) {
return `?${strQuery}`;
}
return strQuery;
}
/**
* 把一个对象或者 key=value&key1=value 类型的数据加密成 query=encodeURIComponent(value)
* @param {Object|String} query 符合js标注的对象 或者 key=value&key1=value 字符串
* @param {Boolean} intact 是否在转成的字符串前添加?号
*/
encode(query, intact = true) {
let [strQuery, formatQuery] = ['', ''];
if (query == null) {
warn('加密参数没有传递,你知道?', true);
return '';
}
if (query.constructor === String) { // 字符串 尝试 转成 对象
strQuery = JSON.stringify(this.parse(query));
} else if (query.constructor === Object) { // 直接转成字符串对象即可
if (Object.keys(query).length === 0) {
warn('当前参数不满足加密规范!');
return '';
}
strQuery = JSON.stringify(query);
}
if (intact) {
formatQuery = '?';
}
formatQuery += `query=${encodeURIComponent(strQuery)}`;
return formatQuery;
}
/**
* 把一个已经加密好的字符串 query=encodeURIComponent(value) 解密成 对象
* @param {string} strQuery 已经加密好的字符串 query=encodeURIComponent(value)
*/
decode(strQuery) {
if (strQuery == null) {
warn('解密参数没有传递,你知道?', true);
return {};
}
let jsonQuery = strQuery;
if (strQuery.constructor === Object) { // 如果是对象 看能不能满足要求
jsonQuery = strQuery.query;
if (jsonQuery == null) {
warn('当前解密参数不满足编码规则');
return {};
}
jsonQuery = `query=${jsonQuery}`;
}
let decode = {};
// query 长这个样 query=encodeURIComponent(value)
const decodeStr = decodeURIComponent(jsonQuery);
const { query } = this.parse(decodeStr); // 转成 json 获取到正真的json字符串
if (query == null) {
warn('当前解密参数不满足编码规则');
} else {
try {
decode = JSON.parse(query);
} catch (error) {
warn('当前解密参数不满足编码规则');
}
}
return decode;
}
queryGet(query) {
const { encodeURI } = Global.Router.CONFIG; // 获取到路由配置
let [decode, historyObj, strQuery] = [query, query, ''];
switch (encodeURI) {
case true: { // 加密模式
decode = this.decode(query);
strQuery = this.encode(decode);
historyObj = {
query: encodeURIComponent(JSON.stringify(decode)),
};
break;
}
case false: { // 不加密模式
strQuery = this.stringify(query);
break;
}
default: {
err('未知参数模式,请检查 \'encodeURI\'', true);
}
}
return { strQuery, historyObj, decode };
}
/**
* 对需要传递的参数进行加密解密
* @param {Object|String} query get为false 必须为 Object 类型
* @param {String} get 是取值 还是通过api传值
*/
transfer(query = {}) {
const { encodeURI } = Global.Router.CONFIG; // 获取到路由配置
switch (encodeURI) {
case true: {
// 加密模式
return this.encode(query, false);
}
case false: {
// 不加密模式
return this.stringify(query);
}
default: {
err('未知参数模式,请检查 \'encodeURI\' ', true);
}
}
}
}
export default ParseQuery;
import { route, baseConfig, Global } from './config';
import { builtIn } from '../vueRouter/base';
import { err, log, warn } from './warn';
/**
* 当前是不是H5运行环境
*/
export const isH5 = function () {
return typeof window !== 'undefined' && typeof document !== 'undefined';
};
/**
* 判断当前变量是否为Object
* @param {Object} strObj
*/
export const isObject = function (strObj) {
return strObj.toString() === '[object Object]' && strObj.constructor === Object;
};
/**
* 获取当前运行平台
* @param {Boolean} applets 默认false true时所有小程序平台统一返回 APPLETS
*/
export const appPlatform = function (applets = false) {
let platform = '';
// #ifdef APP-PLUS-NVUE
platform = 'APPNVUE';
// #endif
// #ifdef APP-PLUS
platform = 'APP';
// #endif
// #ifdef H5
platform = 'H5';
// #endif
// #ifdef MP-ALIPAY
platform = 'ALIPAY';
// #endif
// #ifdef MP-BAIDU
platform = 'BAIDU';
// #endif
// #ifdef MP-QQ
platform = 'QQ';
// #endif
// #ifdef MP-WEIXIN
platform = 'WEIXIN';
// #endif
// #ifdef MP-TOUTIAO
platform = 'TOUTIAO';
// #endif
if (applets) {
// #ifdef MP
platform = 'APPLETS';
// #endif
}
return platform;
};
/**
* 定义一个空方法 如果最后一个参数为true则打印所有参数
* @param {...any} args
*/
export const noop = function (...args) {
if (args[args.length - 1] === true) {
log(args);
}
};
/**
* 格式化基础配置信息 通过new Router传递过来的参数
*/
export const formatConfig = function (userConfig) {
if (!userConfig.routes || userConfig.routes.constructor !== Array) {
return err(`路由参数 'routes' 必须传递 \r\n\r\n${JSON.stringify(userConfig)}`);
}
if (userConfig.h5 != null && userConfig.h5.constructor !== Object) {
return err(`h5参数传递错误,应该是一个 'Object' 类型 示例:\r\n\r\n${JSON.stringify(baseConfig.h5)}`);
}
const config = Object.create(null);
const baseConfigKeys = Object.keys(baseConfig);
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], ...builtIn];
} else {
config[key] = userConfig[key];
}
} else {
config[key] = baseConfig[key];
}
}
return config;
};
export const filter = function (str) {
str += '';
str = str.replace(/%/g, '%25');
str = str.replace(/\+/g, '%2B');
str = str.replace(/ /g, '%20');
str = str.replace(/\//g, '%2F');
str = str.replace(/\?/g, '%3F');
str = str.replace(/&/g, '%26');
str = str.replace(/=/g, '%3D');
str = str.replace(/#/g, '%23');
return str;
};
/**
* 使用encodeURI:true的情况 需要进行编码后再传递,解码等等 可以传递深度对象并会在路径后面加入一个query=
*
* @param {String} routerName //路径名称
* @param {JSON} query //需要格式化参数
* @param {Boolean} Encode //是获取还是编码后传递
*/
export const parseQueryN = function (routerName, query, Encode) {
if (Encode) {
return {
url: routerName,
query: JSON.parse(decodeURIComponent(query.replace(/^query=/, ''))),
};
}
return {
url: routerName,
query: `query=${encodeURIComponent(JSON.stringify(query))}`,
};
};
/**
* 使用encodeURI:false的情况 直接格式化为普通的queryURl参数形式传递即可 扁平深度对象
*
* @param {String} routerName //路径名称
* @param {JSON} query //需要格式化参数
* @param {Boolean} Encode //是获取还是编码后传递
*/
export const parseQueryD = function (routerName, query, Encode) {
if (Encode) {
const obj = {};
const reg = /([^=&\s]+)[=\s]*([^&\s]*)/g;
while (reg.exec(query)) {
obj[RegExp.$1] = RegExp.$2;
}
return {
url: routerName,
query: obj,
};
}
const encodeArr = [];
const queryKeys = Object.keys(query);
for (let i = 0; i < queryKeys.length; i += 1) {
const attr = queryKeys[i];
let encodeStr = '';
if (query[attr].constructor == Object) {
encodeStr = parseQueryD(routerName, query[attr], Encode).query;
encodeArr.push(encodeStr);
} else {
encodeStr = filter(query[attr]);
encodeArr.push(`${attr}=${encodeStr}`);
}
}
return {
url: routerName,
query: encodeArr.join('&'),
};
};
/**
* @param {String} routerName //路径名称
* @param {JSON} query //需要格式化参数
* @param {Boolean} Encode //是获取还是编码后传递
*/
export const parseQuery = function (routerName, query, Encode = false) {
if (Global.Router.CONFIG.encodeURI) {
return parseQueryN(routerName, query, Encode);
}
return parseQueryD(routerName, query, Encode);
};
export const exactRule = function (cloneRule, routes, ruleKey, getRule = false) {
const params = {};
let i = 0;
// eslint-disable-next-line
while (true) {
const item = routes[i];
if (item == null) {
if (!getRule) {
err(`路由表中未查找到 '${ruleKey}' 为 '${cloneRule[ruleKey]}'`);
}
return {
path: '',
name: '',
};
}
if (item[ruleKey] != null && item[ruleKey] === cloneRule[ruleKey]) {
if (!getRule) {
params.url = item.path;
params.rule = item;
if (isH5()) { // 如果是h5 则使用优先使用自定义路径名称
params.url = item.aliasPath || item.path;
}
return params;
}
return item;
}
i += 1;
}
};
export const resolveRule = function (router, rule, query = {}, ruleKey = 'path') {
const ruleInfo = route(
exactRule({
...rule,
},
router.CONFIG.routes,
ruleKey,
router),
);
return {
...ruleInfo,
query,
};
};
/**
* 把一些不必要的参数进行格式化掉,完成url的美观
* @param {String} URLQuery URL中传递的参数
*/
export const formatURLQuery = function (URLQuery) {
switch (URLQuery.trim()) {
case 'query=%7B%7D':
case '%7B%7D':
case '?query=%7B%7D':
case '?':
case '?[object Object]':
case '?query={}':
URLQuery = '';
break;
default:
warn('url已经很完美啦,不需要格式化!');
break;
}
return URLQuery;
};
/**
* 拷贝对象
* @param {Object} object
*/
export const copyObject = function (object) {
return JSON.parse(JSON.stringify(object));
};
import { Global } from './config';
const isLog = function (type, errText, enforce) {
if (!enforce) {
const dev = Global.Router.CONFIG.debugger;
const isObject = dev.toString() === '[object Object]';
if (dev === false) {
return false;
} if (dev === false) {
return false;
} if (isObject) {
if (dev[type] === false) {
return false;
}
}
}
/* eslint no-console:"off" */
console[type](errText);
};
export const err = function (errInfo, enforce = false) {
isLog('error', errInfo, enforce);
};
export const warn = function (errInfo, enforce = false) {
isLog('warn', errInfo, enforce);
};
export const log = function (errInfo, enforce = false) {
isLog('log', errInfo, enforce);
};
export const warnLock = function (errInfo) {
console.warn(errInfo);
};
import { isH5, formatConfig, appPlatform } from './helpers/util';
import navjump from './helpers/navJump';
import { H5GetPageRoute } from './vueRouter/util';
import { APPGetPageRoute } from './appRouter/util';
import { AppletsPageRoute } from './appletsRouter/util';
import { lifeCycle, Global } from './helpers/config';
import { warn, err } from './helpers/warn';
import { registerRouterHooks, registerHook } from './lifeCycle/hooks';
import { vueMount } from './vueRouter/base';
import appletsMount from './patch/applets-patch';
import appMount from './patch/app-patch';
import initMixins from './helpers/mixins';
import ParseQuery from './helpers/urlQuery';
// #ifdef H5
import H5 from './patch/h5-patch';
// #endif
let H5PATCH = null;
// #ifdef H5
H5PATCH = new H5(isH5());
// #endif
const parseQuery = new ParseQuery();
Global.H5RouterReady = new Promise((resolve) => Global.RouterReadyPromise = resolve);
class Router {
constructor(arg) {
Router.$root = this;
Global.Router = this; // 全局缓存一个对象,不必使用时都传递
Global.$parseQuery = parseQuery;
this.CONFIG = formatConfig(arg);
this.lifeCycle = lifeCycle;
registerRouterHooks.call(this); // 注册全局Router生命钩子
if (appPlatform() === 'H5') {
H5PATCH.setLoadingStatus(this.CONFIG.h5);
}
}
get $Route() {
return this.getPageRoute();
}
/**
* 获取 url 参数帮助类实例
*/
get $parseQuery() {
return Global.$parseQuery;
}
/**
* 获取当前是否处于正在跳转的状态
* H5 状态下始终为false
*/
get $lockStatus() {
return Global.LockStatus;
}
/**
* 动态设置拦截状态
*/
set $lockStatus(status) {
warn('你确定要这么做?你知道后果?', true);
Global.LockStatus = status;
}
/** 动态的导航到一个新 URL 保留浏览历史
* navigateTo
* @param {Object} rule
*/
push(rule) {
navjump.call(this, rule, 'push');
}
/** 动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。
* redirectTo
* @param {Object} rule
*/
replace(rule) {
navjump.call(this, rule, 'replace');
}
/** 动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面
* reLaunch
* @param {Object} rule
*/
replaceAll(rule) {
navjump.call(this, rule, 'replaceAll');
}
/** 动态的导航到一个新 url 关闭所有页面,打开到应用内的某个tab
* @param {Object} rule
*/
pushTab(rule) {
navjump.call(this, rule, 'pushTab');
}
/**
* 返回到指定层级页面上
* @param {Number} backLayer 需要返回的页面层级 默认 1
* @param {Object} delta 暂时无用
* @param {enforce} 是否强制越过跳转加锁检查 默认 false
*/
back(backLayer = 1, delta, enforce = false) {
if (backLayer.constructor != Number) {
return err(
`返回层级参数必须是一个Number类型且必须大于1:${backLayer}`,
);
}
navjump.call(this, {
backLayer, delta, H5PATCH,
}, 'back', true, enforce);
}
/**
* 获取当前页面下的 Route 信息
*
* @param {Object} Vim 当前开发者可以传递一个 vue 组件对象 来获取当前下的 Route 信息
*/
getPageRoute(Vim) {
const pages = getCurrentPages();
switch (appPlatform(true)) {
case 'H5':
return H5GetPageRoute.call(this, pages, Vim);
case 'APP':
return APPGetPageRoute(pages, Vim);
case 'APPLETS':
return AppletsPageRoute(pages, Vim);
default:
break;
}
}
beforeEach(fn) {
return registerHook(this.lifeCycle.beforeHooks, fn);
}
afterEach(fn) {
return registerHook(this.lifeCycle.afterHooks, fn);
}
}
Router.install = function (Vue) {
initMixins(Vue, Router);
Object.defineProperty(Vue.prototype, '$Router', {
get() {
return Router.$root;
},
});
Object.defineProperty(Vue.prototype, '$Route', {
get() {
return Router.$root.getPageRoute(this);
},
});
};
export default Router;
/**
*
* @param {VueComponent } Vim vue实例对象
* @param {dom} el dom节点选择器
*/
export const RouterMount = function (Vim, el) {
switch (appPlatform(true)) {
case 'APP':
appMount(Vim, el);
break;
case 'APPLETS':
appletsMount(Vim, el);
break;
case 'H5':
vueMount.push({ Vim, el });
break;
default:
warn('糟糕!!!还有其他的执行环境???没听说过啊。一脸懵逼???加QQ群问问:769241495');
break;
}
};
import { appPlatform, isH5 } from '../helpers/util';
// #ifdef H5
import H5 from '../patch/h5-patch';
const H5PATCH = new H5(isH5());
// #endif
export const registerHook = function (list, fn) {
list.push(fn);
return () => {
const i = list.indexOf(fn);
if (i > -1) list.splice(i, 1);
};
};
/**
* 注册全局Router生命钩子
*/
export const registerRouterHooks = function () {
registerHook(this.lifeCycle.routerbeforeHooks, function () {
return new Promise(async (resolve) => {
this.CONFIG.routerBeforeEach(); // 触发暴露给开发者的生命钩子
if (appPlatform(true) === 'H5') {
H5PATCH.on('toogle', 'startLodding');
}
return resolve(true);
});
});
registerHook(this.lifeCycle.routerAfterHooks, function (res = {}) {
if (res.H5Intercept !== true) {
this.CONFIG.routerAfterEach(); // 触发暴露给开发者的生命钩子
}
if (appPlatform(true) === 'H5') {
H5PATCH.on('toogle', 'stopLodding');
}
return true;
});
};
{
"name": "uni-simple-router",
"version": "1.5.5",
"description": "> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造",
"main": "index.js",
"directories": {
"example": "examples"
},
"scripts": {
"postinstall": "node -e \"console.log('\\x1B[32m \\x1B[1m','\\n 欢迎下载 uni-simple-router ↓↓↓↓ \\n\\n 注意事项:\\n 1: 编译为app端如果开启V3,请关闭fast启动模式 \\n 2: 多看文档,特别是‘快速上手’栏目。文档地址:http://hhyang.cn/ \\n 3: 不要再问路由表是否可以不配置两遍。问就是文档有!\\n 4: 有啥问题解决不了的加群:769241495 \\n 5: 任何时候你都可以在github上提出你的想法及问题,相信我很快会得到回应 \\n\\n showTime:\\n 1:开源不易,需要鼓励。去给 uni-simple-router 项目 点个 star 吧 \\n')\""
},
"dependencies": {
"query-string": "^6.12.1"
},
"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",
"types": "./types/index.d.ts"
}
\ No newline at end of file
/**
* 截止 1.3.5 版本 不做任何操作
* @param {element} el dom节点
*/
const appMount = function (Vim) {
Vim.$mount();
};
export default appMount;
/**
* 截止 1.3.5 版本 不做任何操作
* @param {element} el dom节点
*/
const appletsMount = function (Vim) {
Vim.$mount();
};
export default appletsMount;
// #ifdef H5
import { DOM } from '../component/h5-dom';
import init from '../vueRouter/init';
// #endif
import { warn } from '../helpers/warn';
class Patch {
constructor(H5) {
this.H5 = H5;
this.isLoading = true;
this.loadingCount = 0; // 在APP.vue中进行跳转时,DOMContentLoaded过慢。使用索引来判断
}
on(fun, args, callback) {
if (this.H5) {
return this[fun](args);
}
if (callback) {
callback();
}
}
/**
*把vueRouter的生命周期代理过来
* @param {Object} Router
* @param {Object} vueRouter
* @param {VueComponent} vueVim
*/
// eslint-disable-next-line
registerHook(Router, vueRouter, vueVim) {
init(Router, vueRouter, vueVim);
}
/**
* H5 专属 history.back API
* @param {Number} backLayer 需要返回的层级必须是正整数
* 2020年1月14日14:39:38 修复 https://github.com/SilurianYang/uni-simple-router/issues/73
*/
// eslint-disable-next-line
historyBack({ backLayer, delta = { from: 'navigateBack' } } = {}) {
const pages = getCurrentPages();
const page = pages[pages.length - 1];
const { onBackPress } = page.$options;
if (onBackPress != null && onBackPress.constructor === Array) {
const callFun = onBackPress[onBackPress.length - 1];
const isNext = callFun.call(page, delta);
if (isNext) {
return true;
}
}
// eslint-disable-next-line
history.go(-backLayer);
}
/**
* 把加载动画添加到dom下面,为什么一定要先添加,后移除。保证动画的连续性
*/
appendHTML({
style,
html,
script,
}) {
window.addEventListener('DOMContentLoaded', () => {
const body = document.querySelector('body');
body.appendChild(style);
body.appendChild(html);
body.appendChild(script);
this.toogle('startLodding', true);
});
}
/**
* 页面是否加载完毕触发对应事件
*/
toogle(toogle, DOMContentLoaded = false) {
if (DOMContentLoaded && this.loadingCount !== 0) {
this.loadingCount += 1;
return false;
}
try {
this.loadingCount += 1;
if (this.isLoading) {
window[toogle]();
}
} catch (error) {
warn('你使用了 addRoutes API 提前进行了生命周期 并触发了startLodding');
}
}
async setLoadingStatus({
loading,
replaceStyle,
resetStyle,
}) {
this.isLoading = loading;
if (loading) { // 确认需要加载样式 开始插入节点
const userStyle = resetStyle();
const userStyleKeys = Object.keys(userStyle);
for (let i = 0; i < userStyleKeys.length; i += 1) {
const key = userStyleKeys[i];
let html = userStyle[key];
if (key === 'style' && !replaceStyle) { // 开发者设置为追加style
html = DOM[key].innerHTML + html;
}
DOM[key].innerHTML = html;
}
this.appendHTML(DOM);
}
}
}
export default Patch;
import {Component,PluginFunction,Location,Route,Animation,H5,APP,RouteConfig,RouterOptions} from './options'
/**
* 路由挂载点
* @param {VueComponent } Vim vue实例对象
* @param {dom} el dom节点选择器
*/
declare const RouterMount: (Vim: any, el: string | Element) => void;
declare class Router {
constructor(options:RouterOptions)
/**
* 当前的 Route
*/
get $Route():Route;
/**
* 获取 url 参数帮助类实例
*/
get $parseQuery():object;
/**
* 获取当前是否处于正在跳转的状态
* H5 状态下始终为false
*/
get $lockStatus():boolean;
/**
* 动态设置拦截状态
*/
set $lockStatus(status:boolean);
/**动态的导航到一个新 URL 保留浏览历史
* navigateTo
* @param {Object} rule
*/
push(rule: Location | string): void;
/**动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。
* redirectTo
* @param {Object} rule
*/
replace(rule:Location | string):void;
/**动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面
* reLaunch
* @param {Object} rule
*/
replaceAll(rule:Location | string):void;
/**动态的导航到一个新 url 关闭所有页面,打开到应用内的某个tab
* @param {Object} rule
*/
pushTab(rule:Location | string) :void;
/**
* 返回到指定层级页面上
*/
back(backLayer?:number,delta?:Object):void
/**
* 获取当前页面下的 Route 信息
* @param {Object} Vim 当前开发者可以传递一个 vue 组件对象 来获取当前下的 Route 信息
*/
getPageRoute(Vim?:Component) : Route
/**
* 注册的全局前置生命周期
* @param hooks 注册的全局前置生命周期函数
*/
beforeEach(hooks:Function) : Function
/**
* 注册的全局后置生命周期
* @param hooks 注册的全局后置生命周期函数
*/
afterEach(hooks:Function) : Function
static install:PluginFunction<never>
}
declare module "vue/types/vue" {
interface Vue {
$Router: Router;
$Route: Route;
}
}
export default Router;
export {
RouterMount,
Location,
Route,
Animation,
H5,
APP,
RouteConfig,
RouterOptions
}
\ No newline at end of file
import Vue, { ComponentOptions,PluginFunction, AsyncComponent } from "vue";
type Component = ComponentOptions<Vue> | typeof Vue | AsyncComponent;
type Dictionary<T> = { [key: string]: T };
type Position = { x: number; y: number };
type PositionResult = Position | { selector: string; offset?: Position } | void;
type NAVTYPE= 'push' | 'replace' | 'replaceAll' | 'pushTab'
interface Location {
name?: string;
path?: string;
query?: Dictionary<string | (string | null)[] | null | undefined>;
params?: Dictionary<string>;
NAVTYPE?: NAVTYPE;
}
interface Route {
path: string;
name?: string;
params?: any;
query?: any;
beforeEnter?:(to:Route, from:Route, next:Function) => void;
meta?: any; //其他格外参数
}
interface Animation{
animationType?:string;
animationDuration?:number;
}
interface H5{
rewriteFun?:boolean; //是否对uni-app reLaunch/navigateBack 两个方法重写 处理uni刷新直接返回到首页和触发路由守卫
paramsToQuery?: boolean; //h5端上通过params传参时规则是vue-router 刷新会丢失 开启此开关将变成?连接的方式
loading?: boolean; //是否显示加载动画
hinderTab?: boolean; //是否拦截uni-app自带底部菜单 TODO
vueRouterDev?: boolean; //完全使用采用vue-router的开发模式
useUniConfig?: boolean; //是否采用在pages.json下的所有页面配置信息,false时需开发者自行设置页面
keepUniIntercept?: boolean; //保留uni-app使用vue-router的拦截器
vueNext?: boolean; //在next管道函数中是否获取vueRouter next的原本参数
replaceStyle?: boolean; //是否对resetStyle函数中返回的style节点进行全部替换,否则为追加
resetStyle?: () => Object; //自定义加载样式函数 可返回一个包涵 html、style、script 的对象来重置Router内置的加载动画
mode?: string;
base?: string;
linkActiveClass?: string;
linkExactActiveClass?: string;
scrollBehavior?: (to:Route, from:Route, savedPostion:Position|void) => PositionResult | Promise<PositionResult>,
fallback?: boolean,
}
interface APP{
holdTabbar?:boolean; //是否开启底部菜单拦截
rewriteFun?:boolean; //是否对uni-app 下的chooseLocation/openLocation 两个方法重写 目的是隐藏和显示拦截tabbar
loddingPageStyle?:()=>Object; //当前等待页面的样式 必须返回一个json
loddingPageHook?:()=>void; //刚刚打开页面处于等待状态,会触发此事件
holdTabbarStyle?:()=>Object;
animation?:Animation; //页面切换动画
switchPageOutTime?:number, //最高能忍耐的页面切换时间 达到此时间 不管切换有没有完成都会显示页面出来 这对启动页帮助很大
}
interface RouteConfig {
path: string; //pages.json中的path 必须加上 '/' 开头
component?: Component; //H5端可用
name?: string; // 命名路由
components?: { [name: string]: Component }; // 命名视图组件,H5端可用
redirect?: string | Location | Function; //H5端可用
props?: boolean | Object | Function; //H5端可用
aliasPath?:string; //h5端 设置一个别名路径来替换 uni-app的默认路径
alias?: string | Array<string>; //H5端可用
children?: Array<RouteConfig>; // 嵌套路由,H5端可用
beforeEnter?: (to: Route, from: Route, next: Function) => void; //路由元守卫
meta?: any; //其他格外参数
}
interface RouterOptions{
h5?:H5;
APP?:APP;
debugger?: boolean; //是否处于开发阶段 设置为true则打印日志
encodeURI?: boolean; //是否对url传递的参数进行编码
routerBeforeEach?: () => Object; //router 前置路由函数 每次触发跳转前先会触发此函数
routerAfterEach?: () => Object; //router 后置路由函数 每次触发跳转后会触发此函数
routes?: RouteConfig[];
}
export {
PluginFunction,
Component,
Location,
Route,
Animation,
H5,
APP,
RouteConfig,
RouterOptions
}
\ No newline at end of file
export const builtIn = [{
path: '/preview-image',
name: 'previewImage',
component: {
render: () => {},
},
}, {
path: '/choose-location',
name: 'chooseLocation',
component: {
render: () => {},
},
}, {
path: '/open-location',
name: 'openLocation',
component: {
render: () => {},
},
}]; // uni-app内置路由
export const vuelifeHooks = { // vueRouter的原始生命周期
beforeHooks: [],
afterHooks: [],
};
export const vueMount = [];// 使用内部对象保留实例化下的appVue,并使用Router进行挂载触发第一次路由钩子
import { warn, err } from '../helpers/warn';
import {
diffRouter, vueDevRouteProxy, getRouterNextInfo, formatUserRule, nameToRute, encodeURLQuery, strPathToObjPath, getPages,
} from './util';
import { formatURLQuery } from '../helpers/util';
import { vuelifeHooks, vueMount } from './base';
import { lifeCycle, Global } from '../helpers/config';
let beforeEachCount = 0;
let afterEachCount = 0;
let resolveLaunch = null;
let beforeEnterDep = [];// 记录当前是否有重复的页面进入 避免重复触发
const beforeEachLaunch = new Promise((resolve) => resolveLaunch = resolve);
/**
* 把vue实例进行挂载到dom下
* @param {Router} Router uni-simple-router实例对象
*/
export const appMount = function () {
if (vueMount.length == 0) {
return err('检测到您未进行dom模型挂载操作,请调用api\r\n\r\n RouterMount(Vim: any, el: any): void');
}
const {
Vim,
el,
} = vueMount[0];
let formatEl = el;
if (el == null) {
formatEl = '#app'; // 这是uni-app在h5中的官方节点
}
try {
Vim.$mount(formatEl);
} catch (error) {
warn(`挂载vue节点时错误啦${error}`);
}
};
/**
* 格式化 next传递过来的参数 作为vue-router可用的
* @param {Object} to//即将跳转到的路由页面
* @param {*} Intercept
* @param {Funtion} next//路由连接管道
* @param {Router} Router//路由对象
*/
export const forMatNext = function (to, Intercept, next, Router) {
const { CONFIG, selfRoutes } = Router;
if (CONFIG.h5.vueRouterDev) { // 完全使用vue-router开发的时候 vueRouterDev:true 不用做啥直接略过
next(Intercept);
return Intercept;
}
if (typeof Intercept === 'object') { // 只有是对象类型的时候 我们才进行格式化
const navType = Reflect.get(Intercept, 'NAVTYPE');
delete Intercept.NAVTYPE;
if (navType == 'push') {
Intercept.replace = false;
Intercept.type = 'navigateTo';
} else {
Intercept.replace = true; // uni-app导航api所谓的NAVTYPE取值在h5都是replace:true
Intercept.type = 'reLaunch';
}
const name = Reflect.get(Intercept, 'name'); // 统一格式化path
Intercept.query = Intercept.params || Intercept.query;
delete Intercept.name;
delete Intercept.params;
if (Intercept.query == null) {
Intercept.query = {};
}
if (name != null) {
const { aliasPath, path } = nameToRute(name, selfRoutes);
Intercept.path = aliasPath || path;
} else { // 当设置别名时可以是别名跳转也可以path跳转
Intercept.path = Reflect.get(Intercept, 'path');
const rute = formatUserRule(Intercept.path, selfRoutes, CONFIG);
if (rute == null) {
return false;
}
Intercept.path = rute;
}
if (CONFIG.encodeURI) { // 如果设置的编码传递则进行编码后传递
const query = encodeURIComponent(JSON.stringify(Intercept.query));
const formatQuery = formatURLQuery(query);
Intercept.query = {};
if (formatQuery != '') {
Intercept.query.query = formatQuery;
}
}
} else if (Intercept != null && Intercept.constructor === String) {
Intercept = formatUserRule(Intercept, selfRoutes, CONFIG);
}
let objPath = Intercept;
if (Intercept != null && Intercept.constructor !== Boolean) {
objPath = strPathToObjPath(Intercept);
if (objPath != null) {
const type = Reflect.get(objPath, 'type');
if (type == null) { // 当next()是一个路径时
objPath.type = 'navigateTo';
}
}
} else if (Intercept === false) {
Router.lifeCycle.routerAfterHooks[0].call(Router, { H5Intercept: true });
}
next(objPath);// 统一格式化为对象的方式传递
return Intercept;
};
/**
* v1.5.4+
* beforeRouteLeave 生命周期
* @param {Object} to 将要去的那个页面 vue-router to对象
* @param {Object} from 从那个页面触发的 vue-router from对象
* @param {Object} next vue-router beforeEach next管道函数
* @param {Object} Router Router路由对象
*/
const beforeRouteLeaveHooks = function (to, from, next, Router) {
return new Promise((resolve) => {
const { currentRoute } = Router.$route;
if (currentRoute.path == to.path) { // 如果是同一个页面直接返回 不执行页面中的Leave事件
return resolve();
}
const page = getPages(); // 获取到当前的页面对象
if (page == null || page._HHYANGbeforeRouteLeaveCalled) {
warn('当前环境下无须执行 beforeRouteLeave。 原因:1.page等于null 2.真的的无须执行');
return resolve();
}
const beforeRouteLeaveArray = page.$options.beforeRouteLeave; // 获取到页面下的 beforeRouteLeave 路由守卫
if (beforeRouteLeaveArray == null) { // 当前页面没有预设 beforeRouteLeave 啥都不做
return resolve();
}
const { toRoute, fromRoute } = getRouterNextInfo(to, from, Router);
const beforeRouteLeave = beforeRouteLeaveArray[0]; // 不管怎么样 只执行第一个钩子 其他都不管
beforeRouteLeave.call(page, toRoute, fromRoute, (Intercept) => { // 开始执行生命周期
if (Intercept == null) { // 放行状态 直接返回
return resolve();
}
page._HHYANGbeforeRouteLeaveCalled = true; // 标记一下当前已经做过 beforeRouteLeave 啦
forMatNext(to, Intercept, next, Router); // 直接交给vue-router 处理
});
});
};
/**
* 修复首页beforeEnter执行两次的问题 https://github.com/SilurianYang/uni-simple-router/issues/67
*
* beforeEnter 生命周期
* @param {Object} to
* @param {Object} from
* @param {Object} next
* @param {Object} userHooks
* @param {Object} Router
*/
export const beforeEnterHooks = function (to, from, next, userHooks, Router) {
return new Promise(async (resolve) => {
// 修复 (#67)
if (beforeEnterDep.includes(to.path)) {
next();
return resolve();
}
beforeEnterDep = [to.path];
if (Reflect.get(Router, 'H5RouterReady')) {
const res = await new Promise(async (resolveNext) => {
const {
toRoute,
fromRoute,
} = getRouterNextInfo(to, from, Router);
await userHooks(toRoute, fromRoute, resolveNext);
});
forMatNext(to, res, next, Router);
} else {
next();
}
resolve();
});
};
/**
* vueAfter 生命周期
* @param {Object} to
* @param {Object} from
* @param {Object} next
* @param {Object} Router
*/
export const afterHooks = async function (to, from, next, Router) {
vuelifeHooks.afterHooks[0](to, from);
if (lifeCycle.afterHooks[0]) {
if (afterEachCount === 0) {
await beforeEachLaunch;
appMount(Router);
}
const {
toRoute,
fromRoute,
} = getRouterNextInfo(to, from, Router);
lifeCycle.afterHooks[0](toRoute, fromRoute);
} else if (afterEachCount === 0) {
appMount(Router);
}
afterEachCount += 1;
Router.lifeCycle.routerAfterHooks[0].call(Router);
};
/**
* vueBefore 生命周期
* @param {Object} to 将要去的那个页面 vue-router to对象
* @param {Object} from 从那个页面触发的 vue-router from对象
* @param {Object} next vue-router beforeEach next管道函数
* @param {Object} H5Config
*/
export const beforeHooks = function (to, from, next, Router) {
return new Promise(async (resolve) => {
await Router.lifeCycle.routerbeforeHooks[0].call(Router); // 触发Router内置前置生命周期
await beforeRouteLeaveHooks(to, from, next, Router); // 执行1.5.4+ beforeRouteLeave生命钩子
const H5 = Router.CONFIG.h5;
vuelifeHooks.beforeHooks[0](to, from, async (Intercept) => {
if (Intercept != null && H5.keepUniIntercept === true && H5.vueRouterDev === false) {
next(Intercept);
warn('uni-app 内部强制触发跳转拦截');
beforeEachCount += 1;
return resolve();
}
// 顺序问题 没有触发uni-app里面的方法 修复[#44](https://github.com/SilurianYang/uni-simple-router/issues/44)
if (!lifeCycle.beforeHooks[0]) {
next();
beforeEachCount += 1;
resolveLaunch();
return resolve();
}
const res = await new Promise(async (resolveNext) => {
const {
toRoute,
fromRoute,
} = getRouterNextInfo(to, from, Router);
await lifeCycle.beforeHooks[0](toRoute, fromRoute, resolveNext);
});
const beforeIntercept = forMatNext(to, res, next, Router);
if (beforeEachCount == 0 && beforeIntercept == null && to.meta.isTabBar) { // 首次触发beforeEach,并且首页没有进行跳转的情况下才触发beforeEnter 主要是keep-alive
const {
selfRoutes,
} = Router;
const beforeEnter = Reflect.get(selfRoutes[`/${to.meta.pagePath}`], 'beforeEnter');
if (beforeEnter) {
await beforeEnterHooks(to, from, next, beforeEnter, Router);
}
}
beforeEachCount += 1;
resolveLaunch();
resolve();
});
});
};
/**
* 通过自动调用router api来完成触发生命周期
* 修复 history 模式下报错的问题 https://github.com/SilurianYang/uni-simple-router/issues/38
* 修复 history 模式下刷新页面参数丢失的问题 https://github.com/SilurianYang/uni-simple-router/issues/45
* 修复 history 模式下首次打开页面url错误时不走 path:* 的匹配项 https://github.com/SilurianYang/uni-simple-router/issues/58
*
* @param {Object} Router //当前simple-router 对象
* @param {Object} vueRouter vue-router对象
*/
export const triggerLifeCycle = function (Router, vueRouter) {
const { CONFIG } = Router;
const currRoute = vueRouter.currentRoute;
if (vueRouter.mode === 'hash') {
const {
query,
path,
} = currRoute;
const URLQuery = encodeURLQuery(CONFIG, query, 'hash');
vueRouter.replace(`${path}${URLQuery}`);
} else {
const {
toRoute,
} = getRouterNextInfo(currRoute, currRoute, Router);
const URLQuery = encodeURLQuery(CONFIG, currRoute.query, 'history');
vueRouter.replace({
path: toRoute.aliasPath || toRoute.path || currRoute.path,
query: URLQuery,
type: 'redirectTo',
});
}
};
/** 注册自定义的路由到vue-router中 前提是必须使用vueRouter开发模式
* @param {Object} Router
* @param {Object} vueRouter
* @param {Boolean} vueRouterDev
*/
export const registerRouter = function (Router, vueRouter, vueRouterDev) {
let routeMap = [];
if (!vueRouterDev) { // 则进行对比两个路由表 主要工作是做路径的优化
routeMap = diffRouter(Router, vueRouter, Router.CONFIG.h5.useUniConfig);
} else { // 完全使用vue-router开发时直接采用开发者的路由表
routeMap = vueDevRouteProxy(Router.CONFIG.routes, Router);
}
const createRouter = () => new vueRouter.constructor({
base: vueRouter.options.base,
mode: vueRouter.options.mode,
routes: routeMap,
});
const router = createRouter();
vueRouter.matcher = router.matcher;
Global.vueRouter = vueRouter; // 把当前vueRouter缓存到全局对象中
Global.RouterReadyPromise(); // router已经准备就绪 调用promise.resolve();
Router.H5RouterReady = true; // 并挂载到Router对象下
// 注册完成所有的钩子及相关参数,手动触发Router的生命周期
setTimeout(() => {
triggerLifeCycle(Router, vueRouter);
});
};
/**
* 实现一个继承的 数组类 代理掉 vue-router 生命钩子的数据
*/
class MyArray extends Array {
constructor(Router, vueOldHooks, hookFun) {
super();
this.Router = Router;
this.vueOldHooks = vueOldHooks;
this.hookFun = hookFun;
}
push(v) {
this.vueOldHooks.splice(0, 1, v);// 把vue-router路由生命钩子保存起来
this[this.length] = (to, from, next) => {
this.hookFun(to, from, next, this.Router);
};
}
}
export default MyArray;
import { afterHooks, beforeHooks, registerRouter } from './concat';
import { fromatRoutes } from './util';
import { err, warn } from '../helpers/warn';
import { proxyEachHooks } from './proxy/proxy';
/**
* 重写掉H5端 uni-app原始存在的bug
*
* @param {Object} Router
*/
const rewriteUniFun = function (Router) {
if (Router.CONFIG.h5.rewriteFun === false) { // 不需要重写
return false;
}
uni.reLaunch = function ({
url,
}) {
if (url === '/') {
warn('H5端 uni.reLaunch(\'/\')时 默认被重写了! 你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch(\'/\'?xxx)');
// eslint-disable-next-line
if (history.length > 1) { // 只有在有历史记录的时候才返回 不然直接返回首页
return Router.back();
}
return Router.replaceAll('/');
}
const path = url.match(/^[^?]+|(\/)/)[0];
try {
const query = {};
url.replace(/([^?&]+)=([^?&]+)/g, (s, v, k) => {
query[v] = decodeURIComponent(k);
return `${k}=${v}`;
});
Router.replaceAll({
path,
query,
});
} catch (e) {
err(`${url}解析失败了.... 试试 this.$Router.replaceAll() 吧`);
}
};
uni.navigateBack = function (delta) {
let backLayer = delta;
if (delta.constructor === Object) { // 这种可能就只是uni-app自带的返回按钮,还有种可能就是开发者另类传递的
backLayer = 1;
}
Router.back(backLayer, delta);
};
};
/**
* 拦截并注册vueRouter中的生命钩子,路由表解析
* @param {Object} Router
* @param {vueRouter} vueRouter
*/
const init = function (Router, vueRouter) {
const CONFIG = Router.CONFIG.h5;
vueRouter.afterHooks = proxyEachHooks(Router, 'afterHooks', afterHooks);
vueRouter.beforeHooks = proxyEachHooks(Router, 'beforeHooks', beforeHooks);
const objVueRoutes = fromatRoutes(vueRouter.options.routes, false, {}); // 返回一个格式化好的routes 键值对的形式
const objSelfRoutes = fromatRoutes(Router.CONFIG.routes, true, CONFIG);
Router.vueRoutes = objVueRoutes; // 挂载vue-routes到当前的路由下
Router.selfRoutes = {
...Router.selfRoutes || {},
...objSelfRoutes,
}; // 挂载self-routes到当前路由下
Router.$route = vueRouter; // 挂载vue-router到$route
rewriteUniFun(Router); // 重新掉uniapp上的一些有异常的方法
registerRouter(Router, vueRouter, CONFIG.vueRouterDev);
};
export default init;
import { beforeEnterHooks } from '../concat';
import { vuelifeHooks } from '../base';
import MyArray from '../extends/myArray';
/**
* 通过 Object.defineProperty 代理一个对象主要是拦截beforeEnter 生命钩子
* @param {Router} Router 路由实例对象
* @param {Object} BeProxy 需要代理的路由表
*/
export const proxyBeforeEnter = function (Router, BeProxy) {
const proxyDc = Object.create(null);// 创建没有继承的属性
const BeProxyKeys = Object.keys(BeProxy);
for (let i = 0; i < BeProxyKeys.length; i += 1) {
const key = BeProxyKeys[i];
Object.defineProperty(proxyDc, key, {
enumerable: true,
configurable: true,
get() {
const value = BeProxy[key];
if (key == 'beforeEnter' && value !== undefined) {
return (to, from, next) => {
beforeEnterHooks(to, from, next, value, Router);
};
}
return value;
},
set(v) {
BeProxy[key] = v;
},
});
}
return proxyDc;
};
/**
* 在uni-app没有注入生命周期时先直接代理相关生命周期数组
* @param {Object} Router
* @param {Object} key
* @param {Funtion} hookFun
*/
export const proxyEachHooks = function (Router, key, hookFun) {
const vueOldHooks = vuelifeHooks[key];
return new MyArray(Router, vueOldHooks, hookFun);
};
import { err } from '../helpers/warn';
import { formatUserRule, strPathToObjPath } from './util';
/**
* @param {Object} replace vue-router的跳转方式
* @param {Object} rule 需要跳转到的路由匹配规则
* @param {Object} type 对应的官方跳转模式
*
* this 为当前 Router 实例
*/
const H5PushTo = function (replace, rule, type) {
if (this.$route == null) {
return err('h5端路由为就绪,请检查调用代码');
}
rule = formatUserRule(rule, this.selfRoutes, this.CONFIG);
const objPath = strPathToObjPath(rule);
objPath.type = type;
this.$route[replace](objPath);
};
export default H5PushTo;
import { warn, err } from '../helpers/warn';
import { isObject, resolveRule, copyObject } from '../helpers/util';
import { proxyBeforeEnter } from './proxy/proxy';
import { Global } from '../helpers/config';
const pagesConfigReg = /props:\s*\(.*\)\s*(\([\s\S]*\))\s*},/;
const pagesConfigRegCli = /props:\s*Object\.assign\s*(\([\s\S]*\))\s*},/; // 脚手架项目
const defRoutersReg = /props:\s*{([\s\S]+)}\s*},/;
/**
* 解析验证当前的 component 选项是否配置正确 只有vueRouterDev:false 才会调用此方法
* @param {Function|Object} component
* @param {Object} item
* @param {Boolean} useUniConfig
*/
export const resolveRender = function ({
component,
components,
}, item, useUniConfig) {
if (components != null) {
warn(`vueRouterDev:false时 路由表配置中 ‘components’ 无效,\r\n\r\n ${JSON.stringify(item)}`);
}
if (useUniConfig == true) { // 采用uni-pages.json中的配置时component可以为空
return false;
}
if (item.path == '*') { // 唯独这个情况在vue-router中可以不用component
return true;
}
if (component == null) {
return err(`vueRouterDev:false时 路由表中 ‘component’ 选项不能为空:\r\n\r\n ${JSON.stringify(item)}`);
}
if (component.constructor === Function) {
item.component = {
render: component,
};
} else if (component.constructor === Object) {
if (component.render == null || component.render.constructor !== Function) {
err(`vueRouterDev:false时 路由表配置中 ‘render’ 函数缺失或类型不正确:\r\n\r\n ${JSON.stringify(item)}`);
}
} else {
err(
`vueRouterDev:false时 路由表配置中 ‘component’ 选项仅支持 Function、Object 类型。并确保 Object 类型时传递了 ‘render’ 函数 :\r\n\r\n ${JSON.stringify(item)}`,
);
}
};
/**
* 递归解析 H5配置中有存在嵌套对象的情况,优先以path为key存储。没有则找aliasPath作为key
* @param {Object} objRoutes
* @param {Array} children
* @param {Boolean} useUniConfig 是否使用pages.json下的页面配置
*/
export const resloveChildrenPath = function (objRoutes, children, useUniConfig) {
for (let i = 0; i < children.length; i += 1) {
const item = children[i];
resolveRender(item, item, useUniConfig);
if (item.path != null) {
objRoutes[item.path] = {
...item,
...{
_ROUTERPATH: true, // 使用page.json中的path为路径
},
};
} else {
objRoutes[item.aliasPath] = {
...item,
...{
_ROUTERPATH: false,
},
};
}
if (item.children && item.children.constructor === Array) {
resloveChildrenPath(objRoutes, item.children, useUniConfig);
}
}
};
/**
* 格式化原始路由表
* @param {Object} routes 路由表
* @param {Boolean} userRoute 是否为用户自己配置的路由表
* @param {Boolean} H5CONFIG
*/
export const fromatRoutes = function (routes, userRoute, {
vueRouterDev,
useUniConfig,
}) {
if (userRoute && vueRouterDev) { // 如果是用户的路由表并且 完全采用vueRouter开发 则不作处理直接返回
return routes;
}
const objRoutes = {};
for (let i = 0; i < routes.length; i += 1) {
const item = routes[i];
const path = item.path === '/' ? item.alias : item.path;
if (userRoute) {
if (item.children && item.children.constructor === Array) {
resloveChildrenPath(objRoutes, item.children, useUniConfig);
}
resolveRender(item, item, useUniConfig); // 是否使用pages.json下的页面配置
}
objRoutes[path] = {
...item,
...{
_PAGEPATH: path.substring(1),
},
};
}
return objRoutes;
};
/**
* 解析vueRouter中 component 下 render函数中的配置信息
* @param {String} FunStr
*/
export const getFuntionConfig = function (FunStr) {
let matchText = FunStr.match(pagesConfigReg);
let prefix = '';
if (matchText == null) { // 是uni-app自带的默认路由及配置 也可能是脚手架项目
matchText = FunStr.match(pagesConfigRegCli);
if (matchText == null) { // 确认不是脚手架项目
try {
// eslint-disable-next-line
matchText = FunStr.match(defRoutersReg)[1];
// eslint-disable-next-line
matchText = eval(`Object.assign({${matchText}})`);
prefix = 'system-';
} catch (error) {
err(`读取uni-app页面构建方法配置错误 \r\n\r\n ${error}`);
}
} else {
// eslint-disable-next-line
matchText = eval(`Object.assign${matchText[1]}`);
}
} else {
// eslint-disable-next-line
matchText = eval(`Object.assign${matchText[1]}`);
}
return {
config: matchText,
prefix,
FunStr,
};
};
/**
* 通过一个未知的路径名称 在路由表中查找指定路由表 并返回
* @param {String} path //不管是aliasPath名的路径还是path名的路径
* @param {Object} routes//当前对象的所有路由表
*/
export const pathToRute = function (path, routes) {
let PATHKEY = '';
let rute = {};
const routeKeys = Object.keys(routes);
for (let i = 0; i < routeKeys.length; i += 1) {
const key = routeKeys[i];
const item = routes[key];
rute = item;
if (item.aliasPath == path) { // path参数是优先采用aliasPath为值得 所以可以先判断是否与aliasPath相同
PATHKEY = 'aliasPath';
break;
}
// eslint-disable-next-line
if (`/${item._PAGEPATH}` == path) { // 路径相同
PATHKEY = 'path';
break;
}
}
return {
PATHKEY: {
[PATHKEY]: path,
},
rute,
};
};
/**
* 通过一个路径name 在路由表中查找指定路由表 并返回
* @param {String} name//实例化路由时传递的路径表中所匹配的对应路由name
* @param {Object} routes//当前对象的所有路由表
*/
export const nameToRute = function (name, routes) {
const routesKeys = Object.keys(routes);
for (let i = 0; i < routesKeys.length; i += 1) {
const key = routesKeys[i];
const item = routes[key];
if (item.name == name) {
return item;
}
}
err(`路由表中没有找到 name为:'${name}' 的路由`);
};
/**
* 根据用户传入的路由规则 格式化成正确的路由规则
* @param {Object} rule 用户需要跳转的路由规则
* @param {Object} selfRoutes simple-router下的所有routes对象
* @param {Object} CONFIG 当前路由下的所有配置信息
*/
export const formatUserRule = function (rule, selfRoutes, CONFIG) {
let type = '';
const ruleQuery = (type = 'query', rule.query || (type = 'params', rule.params)) || (type = '', {});
let rute = {}; // 默认在router中的配置
if (type == '' && rule.name != null) { // 那就是可能没有穿任何值咯
type = 'params';
}
if (type != 'params') {
const route = pathToRute(rule.path || rule, selfRoutes);
if (Object.keys(route.PATHKEY)[0] == '') {
err(`'${route.PATHKEY['']}' 路径在路由表中未找到`);
return null;
}
rute = route.rute;
if (rule.path) {
rule.path = rute.path;
}
}
if (type != '') { // 当然是对象啦 这个主要是首页H5PushTo调用时的
if (type == 'params' && CONFIG.h5.paramsToQuery) { // 如果是name规则并且设置了转query,那么就转path跳转了
const {
aliasPath,
path,
} = nameToRute(rule.name, selfRoutes);
delete rule.name;
delete rule.params;
rule.path = aliasPath || path;
type = 'query';
}
const query = Global.$parseQuery.transfer(ruleQuery);
if (CONFIG.encodeURI) {
if (query != '') {
rule[type] = {
query: query.replace(/^query=/, ''),
};
}
} else {
rule[type] = ruleQuery;
}
} else { // 纯字符串,那就只有是path啦
rule = rute.path;
}
return rule;
};
/**
* 根据是否获取非vue-Router next管道参数,来进行格式化
*
* @param {Object} to
* @param {Object} from
* @param {Router} Router //router当前实例对象
*/
export const getRouterNextInfo = function (to, from, Router) {
let [toRoute, fromRoute] = [to, from];
const H5 = Router.CONFIG.h5;
if (H5.vueNext === false && H5.vueRouterDev === false) { // 不采用vue-router中的to和from,需要格式化成Router中$Route获取的一样一样的
let [toPath, fromPath] = [{}, {}];
toPath[to.meta.PATHKEY] = to.meta.PATHKEY === 'path' ? `/${to.meta.pagePath}` : `${to.path}`;
fromPath[from.meta.PATHKEY] = from.meta.PATHKEY === 'path' ? `/${from.meta.pagePath}` : `${from.path}`;
if (to.meta.PATHKEY == null) { // 未使用uni-pages.json中的配置、通过addRoutes时 meta.PATHKEY 可能未undefined
toPath = pathToRute(to.path, Router.selfRoutes).PATHKEY;
}
if (from.meta.PATHKEY == null) {
fromPath = pathToRute(from.path, Router.selfRoutes).PATHKEY;
}
const isEmptyTo = Object.keys(to.query).length != 0 ? copyObject(to.query) : copyObject(to.params);
const isEmptyFrom = Object.keys(from.query).length != 0 ? copyObject(from.query) : copyObject(from.params);
/* eslint-disable */
delete isEmptyTo.__id__; // 删除uni-app下的内置属性
delete isEmptyFrom.__id__;
/* eslint-enable */
const toQuery = Global.$parseQuery.queryGet(isEmptyTo).decode;
const fromQuery = Global.$parseQuery.queryGet(isEmptyFrom).decode;
toRoute = resolveRule(Router, toPath, toQuery, Object.keys(toPath)[0]);
fromRoute = resolveRule(Router, fromPath, fromQuery, Object.keys(fromPath)[0]);
} else {
if (fromRoute.name == null && toRoute.name != null) { // 这种情况是因为uni-app在使用vue-router时搞了骚操作。
fromRoute = {
...fromRoute,
...{
name: toRoute.name,
},
}; // 这个情况一般出现在首次加载页面
}
}
return {
toRoute,
fromRoute,
};
};
export const vueDevRouteProxy = function (routes, Router) {
const proxyRoutes = [];
for (let i = 0; i < routes.length; i += 1) {
const item = routes[i];
const childrenRoutes = Reflect.get(item, 'children');
if (childrenRoutes != null) {
const childrenProxy = vueDevRouteProxy(childrenRoutes, Router);
item.children = childrenProxy;
}
const ProxyRoute = proxyBeforeEnter(Router, item);
proxyRoutes.push(ProxyRoute);
}
return proxyRoutes;
};
/**
* 组装成编码后的路由query传递信息
* @param {Object} CONFIG simple-router 对象配置
* @param {Object} query 传递的参数
* @param {Object} mode 路由模式
*/
export const encodeURLQuery = function (CONFIG, query, mode) {
if (Object.keys(query).length == 0) { // 没有传值的时候 我们啥都不管
return '';
}
if (CONFIG.h5.vueRouterDev === false) { // 没有采取完全模式开发时 才转换
const { strQuery, historyObj } = Global.$parseQuery.queryGet(query);
if (mode === 'history') {
return historyObj;
}
return strQuery;
} // 完全彩种 vue-router 开发的时候 我们不用管
if (mode === 'history') { // 此模式下 需要的就是对象
return query;
}
return Global.$parseQuery.stringify(query); // hash转成字符串拼接
};
/**
* 把一个未知的路由跳转规则进行格式化为 hash、history 可用的,主要表现在 history模式下直接传入path会报错__id__错误的问题
* @param {*} path 需要判断修改的路径规则
*/
export const strPathToObjPath = function (path) {
if (path == null) { // 我们也不用管啦,这个情况是路由守卫中传递的
return path;
}
if (isObject(path)) { // 是对象我们不用管
return path;
}
return { // 这种情况就是只有path时,直接返回path对象了
path,
};
};
/**
* 通过 getCurrentPages() api 获取指定页面的 page 对象 默认是获取当前页面page对象
* @param {Number} index //需要获取的页面索引
* @param {Boolean} all //是否获取全部的页面
*/
export const getPages = function (index = 0, all) {
const pages = getCurrentPages(all);
return pages.reverse()[index];
};
/**
* 获取当前页面下的 Route 信息
*
* @param {Object} pages 获取页面对象集合
* @param {Object} Vim 用户传递的当前页面对象
*/
export const H5GetPageRoute = function (pages, Vim) {
if (pages.length > 0) { // 直接取当前页面的对象
const currentRoute = pages[pages.length - 1].$route;
return getRouterNextInfo(currentRoute, currentRoute, this).toRoute;
} if (Vim && Vim.$route) {
return getRouterNextInfo(Vim.$route, Vim.$route, this).toRoute;
}
return {};
};
/**
* 在useUniConfig:true 的情况下重新拼装路由表 useUniConfig:false 不需要读取page.json中的数据 直接使用component作为页面组件
* @param {Router} Router//unis-simple-router 路由对象
* @param {vueRouter} vueRouter//vue-router对象
* @param {Boolean} useUniConfig//是否采用uni-page.json中的配置选项
* @param {Array} routes//需要循环的routes表
*/
export const diffRouter = function (Router, vueRouter, useUniConfig, routes) {
const newRouterMap = [];
if (useUniConfig) { // 使用pages.json的样式配置 只是单纯的把url路径改成用户自定义的 保留uni的所以的配置及生命周期、缓存
const Routes = routes || vueRouter.options.routes;
const cloneSelfRoutes = copyObject(Router.selfRoutes); // copy一个对象随便搞xxoo
Routes.forEach(((item) => {
const path = item.path === '/' ? item.alias : item.path;
const vueRoute = (Router.vueRoutes[path] || Router.vueRoutes[item.path]) || Router.selfRoutes[path];
const CselfRoute = Router.selfRoutes[path];
delete cloneSelfRoutes[path]; // 移除已经添加到容器中的路由,用于最后做对比 是否page.json中没有,而实例化时传递了
if (CselfRoute == null) {
return err(
`读取 ‘pages.json’ 中页面配置错误。实例化时传递的路由表中未找到路径为:${path} \r\n\r\n 可以尝试把 ‘useUniConfig’ 设置为 ‘false’。或者配置正确的路径。如果你是动态添加的则不用理会`,
);
}
let pageConfigJson = {
config: {},
};
if (vueRoute.component) {
pageConfigJson = getFuntionConfig(vueRoute.component.render.toString());
CselfRoute.component = {
render: (h) => vueRoute.component.render(h),
};
}
delete CselfRoute.components; // useUniConfig:true 时不允许携带components
delete CselfRoute.children; // useUniConfig:true 时不允许携带children
CselfRoute.meta = {
...pageConfigJson.config,
...item.meta || {},
PATHKEY: CselfRoute.aliasPath ? 'aliasPath' : 'path',
pagePath: CselfRoute.path.substring(1),
};
CselfRoute.path = CselfRoute.aliasPath || (item.path === '/' ? item.path : CselfRoute.path);
item.alias = item.path === '/' ? item.alias : CselfRoute.path; // 重新给vueRouter赋值一个新的路径,欺骗uni-app源码判断
const ProxyRoute = proxyBeforeEnter(Router, CselfRoute);
newRouterMap.push(ProxyRoute);
}));
if (Object.keys(cloneSelfRoutes).length > 0) { // 确实page.json中没有,而实例化时传递了
const testG = cloneSelfRoutes['*']; // 全局通配符,他是个例外'通配符'可以被添加
if (testG && routes == null) {
const ProxyRoute = proxyBeforeEnter(Router, Router.selfRoutes['*']);
newRouterMap.push(ProxyRoute);
}
if (routes == null) { // 非动态添加时才打印警告
const cloneSelfRoutesKeys = Object.keys(cloneSelfRoutes);
for (let i = 0; i < cloneSelfRoutesKeys.length; i += 1) {
const key = cloneSelfRoutesKeys[i];
if (key !== '*') { // 通配符不警告
warn(`实例化时传递的routes参数:\r\n\r\n ${JSON.stringify(cloneSelfRoutes[key])} \r\n\r\n 在pages.json中未找到。自定排除掉,不会添加到路由中`);
}
}
}
}
} else { // 不使用任何的uni配置完全使用 完全使用component作为页面使用
const Routes = routes || Router.selfRoutes;
const RoutesKeys = Object.keys(Routes);
for (let i = 0; i < RoutesKeys.length; i += 1) {
const key = RoutesKeys[i];
const item = Routes[key];
// eslint-disable-next-line
if (item._ROUTERPATH != null) { // 不寻找children下的路径,只取第一层
continue;
}
delete item.components;
delete item.children;
item.path = item.aliasPath || item.path; // 优先获取别名为路径
if (item.path !== '*') {
item.component = item.component.render || item.component; // render可能是用户使用addRoutes api进行动态添加的
}
item.meta = {
...item.meta || {},
PATHKEY: item.aliasPath ? 'aliasPath' : 'path',
pagePath: item.path.substring(1),
};
const ProxyRoute = proxyBeforeEnter(Router, item);
newRouterMap.push(ProxyRoute);
}
}
return newRouterMap;
};
插件市场安装的用户 你需要在你项目目录下执行 `npm init -y && npm install query-string -D`
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
import Vue from 'vue'
import Vuex from 'vuex'
import api from "@/api/api"
import MinCache from'@/common/util/MinCache.js'
import { ACCESS_TOKEN,USER_NAME,USER_INFO } from "@/common/util/constants"
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: '',
userid:'',
username: '',
realname: '',
welcome: '',
avatar: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, { username, realname, welcome }) => {
state.username = username
state.realname = realname
state.welcome = welcome
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
}
},
actions: {
// 登录
mLogin({ commit }, userInfo) {
console.log("mLogin",userInfo)
return new Promise((resolve, reject) => {
api.login(userInfo).then(response => {
if(response.statusCode ==200){
const result = response.data.data
const userInfo = result
uni.setStorageSync(ACCESS_TOKEN,result.token);
uni.setStorageSync(USER_INFO,userInfo);
commit('SET_TOKEN', result.token)
commit('SET_AVATAR', userInfo.avatar)
commit('SET_NAME', { username: userInfo.username,realname: userInfo.realname})
resolve(response)
}else{
resolve(response)
}
}).catch(error => {
console.log("catch===>response",response)
reject(error)
})
})
},
//手机号登录
PhoneLogin({ commit }, userInfo) {
return new Promise((resolve, reject) => {
api.phoneNoLogin(userInfo).then(response => {
if(response.code =='200'){
const result = response.result
const userInfo = result.userInfo
commit('SET_TOKEN', result.token)
commit('SET_NAME', { username: userInfo.username,realname: userInfo.realname})
commit('SET_AVATAR', userInfo.avatar)
resolve(response)
}else{
reject(response)
}
}).catch(error => {
reject(error)
})
})
},
// 登出
Logout({ commit, state }) {
return new Promise((resolve) => {
let logoutToken = state.token;
commit('SET_TOKEN', '')
uni.removeStorageSync(ACCESS_TOKEN)
api.logout(logoutToken).then(() => {
resolve()
}).catch(() => {
resolve()
})
})
},
},
getters:{
token: state => state.token,
username: state => {state.userid=uni.getStorageSync(USER_INFO).username; return state.username},
nickname: state => {state.userid=uni.getStorageSync(USER_INFO).realname; return state.user.realname},
avatar: state => {state.userid=uni.getStorageSync(USER_INFO).avatar; return state.user.avatar},
userid:state => {state.userid=uni.getStorageSync(USER_INFO).id; return state.userid},
}
})
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<!-- 正式发布的时候使用,开发期间不启用。↓ -->
<!-- <script src="/h5/touch-emulator.js"></script>
<script>
TouchEmulator();
if (document.documentElement.clientWidth > 1024) {
window.location.href = '/h5/pcguide.html#'+location.pathname+location.search;
}
</script>
<style>
::-webkit-scrollbar{
display: none;
}
</style>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?";// 百度统计key
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script> -->
<!-- 正式发布的时候使用,开发期间不启用。↑ -->
<!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 -->
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<!-- uni 的 SDK,必须引用。 -->
<script type="text/javascript" src="//js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px'
})
</script>
<link rel="stylesheet" href="<%= BASE_URL %>static/index.css" />
</head>
<body>
<!-- 该文件为 H5 平台的模板 HTML,并非应用入口。 -->
<!-- 请勿在此文件编写页面代码或直接运行此文件。 -->
<!-- 详见文档:https://uniapp.dcloud.io/collocation/manifest?id=h5-template -->
<noscript>
<strong>Please enable JavaScript to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="<%= BASE_URL %>static/js/vconsole.min.js"></script>
<script>
/*BAIDU_STAT*/
new VConsole();
</script>
</body>
</html>
/* 页面左右间距 */
$page-row-spacing: 30upx;
$page-color-base: #f8f8f8;
$page-color-light: #f8f6fc;
$base-color: #fa436a;
/* 文字尺寸 */
$font-sm: 24upx;
$font-base: 28upx;
$font-lg: 32upx;
/*文字颜色*/
$font-color-dark: #303133;
$font-color-base: #606266;
$font-color-light: #909399;
$font-color-disabled: #C0C4CC;
$font-color-spec: #4399fc;
/* 边框颜色 */
$border-color-dark: #DCDFE6;
$border-color-base: #E4E7ED;
$border-color-light: #EBEEF5;
/* 图片加载中颜色 */
$image-bg-color: #eee;
/* 行为相关颜色 */
$uni-color-primary:#fa436a;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment