new
|
|
@ -70,8 +70,10 @@
|
|||
"@vue/shared": "^3.0.0",
|
||||
"core-js": "^3.6.5",
|
||||
"flyio": "^0.6.2",
|
||||
"uview-ui": "^1.8.8",
|
||||
"vue": "^2.6.11",
|
||||
"vuex": "^3.2.0"
|
||||
"vuex": "^3.2.0",
|
||||
"vuex-persistedstate": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.3.2",
|
||||
|
|
@ -93,7 +95,11 @@
|
|||
"jest": "^25.4.0",
|
||||
"mini-types": "*",
|
||||
"miniprogram-api-typings": "*",
|
||||
"node-sass": "^4.14.1",
|
||||
"postcss-comment": "^2.0.0",
|
||||
"sass-loader": "^10.1.1",
|
||||
"stylus": "^0.54.8",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"browserslist": [
|
||||
|
|
|
|||
135
src/App.vue
|
|
@ -12,6 +12,139 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss">
|
||||
@import "uview-ui/index.scss";
|
||||
/*每个页面公共css */
|
||||
.bg-page{
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
background-color: #eeeeef;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.mt24{
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.mt20{
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
.mr20{
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.mr30{
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
.pdlr18{
|
||||
padding-left: 18rpx;
|
||||
padding-right: 18rpx;
|
||||
}
|
||||
.pdl40{
|
||||
padding-left: 40rpx;
|
||||
}
|
||||
.pdlr12{
|
||||
padding-left: 12rpx;
|
||||
padding-right: 12rpx;
|
||||
}
|
||||
.flex-column{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.clamp {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
.clamp-2 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.cu-btn{
|
||||
height: 60rpx;
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
position: relative;
|
||||
border: 0rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
padding: 0 30rpx;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
overflow: visible;
|
||||
margin-left: initial;
|
||||
transform: translate(0rpx, 0rpx);
|
||||
margin-right: initial;
|
||||
}
|
||||
.cu-btn.round{
|
||||
border-radius: 1000rpx;
|
||||
border: none;
|
||||
}
|
||||
.cu-btn::after {
|
||||
display: none;
|
||||
}
|
||||
.cu-btn[class*="bg-"]::after {
|
||||
display: none;
|
||||
}
|
||||
.cu-btn.round[class*="line"]::after {
|
||||
border-radius: 1000rpx;
|
||||
}
|
||||
.cu-btn.button-hover {
|
||||
transform: translate(1rpx, 1rpx);
|
||||
}
|
||||
.cu-btn[class*="line"] {
|
||||
background-color: transparent;
|
||||
}
|
||||
.handle-btn .u-btn.u-btn--warning--disabled{
|
||||
color: #ffffff !important;
|
||||
border-color: #C0C0C0 !important;
|
||||
background-color: #C0C0C0 !important;
|
||||
|
||||
}
|
||||
.cu-btn[class*="line"]::after {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 1rpx solid currentColor;
|
||||
transform: scale(0.5);
|
||||
transform-origin: 0 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12rpx;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
.safe-area-inset-bottom{
|
||||
padding-bottom: 0;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.input-placeholder,.textarea-placeholder{
|
||||
color: #c3c3c3;
|
||||
}
|
||||
.list_arrowR::after{
|
||||
content: '';
|
||||
width: 15rpx;
|
||||
height: 25rpx;
|
||||
position: absolute;
|
||||
right: 10rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: url('./static/img/my_arrow_right.png') no-repeat center;
|
||||
background-size: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
import Request from './luch-request/index.js'
|
||||
import jwt from './jwt.js'
|
||||
import {toast} from '@/com/utils.js'
|
||||
//测试地址
|
||||
const baseApi = 'http://36.133.205.221:81';
|
||||
|
||||
const http = new Request();
|
||||
|
||||
http.setConfig((config) => { /* 设置全局配置 */
|
||||
config.baseURL = baseApi
|
||||
config.header = {
|
||||
...config.header,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
config.custom = {
|
||||
auth: true, // 是否传token
|
||||
// loading: false // 是否使用loading
|
||||
}
|
||||
config.imeout = 30000
|
||||
|
||||
return config
|
||||
})
|
||||
/* 请求之前拦截器 */
|
||||
http.interceptors.request.use((config, cancel) => {
|
||||
if (config.custom.auth) {
|
||||
// 需要权限认证的路由 需携带自定义参数 {custom: {auth: true}}
|
||||
config.header.Authorization = 'Bearer '+jwt.getAccessToken();
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
/* 请求之后拦截器 */
|
||||
let isRefreshing = false;//多次锁
|
||||
|
||||
http.interceptors.response.use((response) => { /* 请求之后拦截器*/
|
||||
const {code} = response.data
|
||||
console.log(response)
|
||||
if(code ==4024){
|
||||
toast(response.data.msg)
|
||||
}else if(code ==401){
|
||||
toast('请关闭小程序,重新进入')
|
||||
} else{
|
||||
|
||||
}
|
||||
return response
|
||||
}, (err) => { // 请求错误
|
||||
const {code} = err.data
|
||||
console.log(code)
|
||||
if(code == 401){//过期未登录
|
||||
const config = err.config
|
||||
if(!isRefreshing){
|
||||
isRefreshing = true
|
||||
|
||||
}else{
|
||||
|
||||
}
|
||||
}else {
|
||||
|
||||
}
|
||||
console.log(err,'======')
|
||||
return Promise.reject(err)
|
||||
})
|
||||
const getFullUrl = (url,params,header) => {
|
||||
return http.post(url, params,{...header});
|
||||
};
|
||||
export {
|
||||
http,
|
||||
getFullUrl
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import store from '@/store/index.js'
|
||||
const tokenKey = 'user_access_token'; //键值
|
||||
// token
|
||||
const getAccessToken = function() {
|
||||
let token = store.state.user_access_token ? store.state.user_access_token : uni.getStorageSync(tokenKey);
|
||||
try {
|
||||
token = token?token:''
|
||||
} catch (e) {}
|
||||
return token;
|
||||
}
|
||||
const setAccessToken = (access_token) => {
|
||||
try {
|
||||
uni.setStorageSync(tokenKey, access_token);
|
||||
store.commit('USERACCESSTOKEN',access_token);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const clearAccessToken = function() {
|
||||
try {
|
||||
uni.removeStorageSync(tokenKey);
|
||||
store.commit(tokenKey,'');
|
||||
} catch (e) {}
|
||||
}
|
||||
//用户key
|
||||
const getUserKey = function() {
|
||||
let userKey = store.state.user_key ? store.state.user_key : uni.getStorageSync('user_key');
|
||||
try {
|
||||
userKey = userKey?userKey:''
|
||||
} catch (e) {}
|
||||
return userKey;
|
||||
}
|
||||
const setUserKey = (user_key) => {
|
||||
try {
|
||||
uni.setStorageSync('user_key', user_key);
|
||||
store.commit('USERKEY',user_key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const clearUserKey = function() {
|
||||
try {
|
||||
uni.removeStorageSync('user_key');
|
||||
store.commit('USERKEY','');
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAccessToken,
|
||||
setAccessToken,
|
||||
clearAccessToken,
|
||||
getUserKey,
|
||||
setUserKey,
|
||||
clearUserKey
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import buildURL from '../helpers/buildURL'
|
||||
import buildFullPath from '../core/buildFullPath'
|
||||
import settle from '../core/settle'
|
||||
import { isUndefined } from "../utils"
|
||||
|
||||
/**
|
||||
* 返回可选值存在的配置
|
||||
* @param {Array} keys - 可选值数组
|
||||
* @param {Object} config2 - 配置
|
||||
* @return {{}} - 存在的配置项
|
||||
*/
|
||||
const mergeKeys = (keys, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
export default (config) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params)
|
||||
const _config = {
|
||||
url: fullPath,
|
||||
header: config.header,
|
||||
complete: (response) => {
|
||||
config.fullPath = fullPath
|
||||
response.config = config
|
||||
try {
|
||||
// 对可能字符串不是json 的情况容错
|
||||
if (typeof response.data === 'string') {
|
||||
response.data = JSON.parse(response.data)
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {
|
||||
}
|
||||
settle(resolve, reject, response)
|
||||
}
|
||||
}
|
||||
let requestTask
|
||||
if (config.method === 'UPLOAD') {
|
||||
delete _config.header['content-type']
|
||||
delete _config.header['Content-Type']
|
||||
let otherConfig = {
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType: config.fileType,
|
||||
// #endif
|
||||
filePath: config.filePath,
|
||||
name: config.name
|
||||
}
|
||||
const optionalKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData'
|
||||
]
|
||||
requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
|
||||
} else if (config.method === 'DOWNLOAD') {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (!isUndefined(config['timeout'])) {
|
||||
_config['timeout'] = config['timeout']
|
||||
}
|
||||
// #endif
|
||||
requestTask = uni.downloadFile(_config)
|
||||
} else {
|
||||
const optionalKeys = [
|
||||
'data',
|
||||
'method',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.request({..._config,...mergeKeys(optionalKeys, config)})
|
||||
}
|
||||
if (config.getTask) {
|
||||
config.getTask(requestTask, config)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
'use strict'
|
||||
|
||||
|
||||
function InterceptorManager() {
|
||||
this.handlers = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new interceptor to the stack
|
||||
*
|
||||
* @param {Function} fulfilled The function to handle `then` for a `Promise`
|
||||
* @param {Function} rejected The function to handle `reject` for a `Promise`
|
||||
*
|
||||
* @return {Number} An ID used to remove interceptor later
|
||||
*/
|
||||
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
|
||||
this.handlers.push({
|
||||
fulfilled: fulfilled,
|
||||
rejected: rejected
|
||||
})
|
||||
return this.handlers.length - 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an interceptor from the stack
|
||||
*
|
||||
* @param {Number} id The ID that was returned by `use`
|
||||
*/
|
||||
InterceptorManager.prototype.eject = function eject(id) {
|
||||
if (this.handlers[id]) {
|
||||
this.handlers[id] = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all the registered interceptors
|
||||
*
|
||||
* This method is particularly useful for skipping over any
|
||||
* interceptors that may have become `null` calling `eject`.
|
||||
*
|
||||
* @param {Function} fn The function to call for each interceptor
|
||||
*/
|
||||
InterceptorManager.prototype.forEach = function forEach(fn) {
|
||||
this.handlers.forEach(h => {
|
||||
if (h !== null) {
|
||||
fn(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default InterceptorManager
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
/**
|
||||
* @Class Request
|
||||
* @description luch-request http请求插件
|
||||
* @version 3.0.5
|
||||
* @Author lu-ch
|
||||
* @Date 2021-01-06
|
||||
* @Email webwork.s@qq.com
|
||||
* 文档: https://www.quanzhan.co/luch-request/
|
||||
* github: https://github.com/lei-mu/luch-request
|
||||
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
|
||||
* HBuilderX: beat-3.0.4 alpha-3.0.4
|
||||
*/
|
||||
|
||||
|
||||
import dispatchRequest from './dispatchRequest'
|
||||
import InterceptorManager from './InterceptorManager'
|
||||
import mergeConfig from './mergeConfig'
|
||||
import defaults from './defaults'
|
||||
import { isPlainObject } from '../utils'
|
||||
|
||||
export default class Request {
|
||||
/**
|
||||
* @param {Object} arg - 全局配置
|
||||
* @param {String} arg.baseURL - 全局根路径
|
||||
* @param {Object} arg.header - 全局header
|
||||
* @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
|
||||
* @param {String} arg.dataType = [json] - 全局默认的dataType
|
||||
* @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。App和支付宝小程序不支持
|
||||
* @param {Object} arg.custom - 全局默认的自定义参数
|
||||
* @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
|
||||
* @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
|
||||
* @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
|
||||
* @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
|
||||
* @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
|
||||
*/
|
||||
constructor(arg = {}) {
|
||||
if (!isPlainObject(arg)) {
|
||||
arg = {}
|
||||
console.warn('设置全局参数必须接收一个Object')
|
||||
}
|
||||
this.config = {...defaults, ...arg}
|
||||
this.interceptors = {
|
||||
request: new InterceptorManager(),
|
||||
response: new InterceptorManager()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Request~setConfigCallback} f - 设置全局默认配置
|
||||
*/
|
||||
setConfig(f) {
|
||||
this.config = f(this.config)
|
||||
}
|
||||
|
||||
middleware(config) {
|
||||
config = mergeConfig(this.config, config)
|
||||
let chain = [dispatchRequest, undefined]
|
||||
let promise = Promise.resolve(config)
|
||||
|
||||
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
|
||||
chain.unshift(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
|
||||
chain.push(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
while (chain.length) {
|
||||
promise = promise.then(chain.shift(), chain.shift())
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Object} config - 请求配置项
|
||||
* @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>}
|
||||
*/
|
||||
request(config = {}) {
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get(url, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
method: 'GET',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
post(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'POST',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #ifndef MP-ALIPAY
|
||||
put(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'PUT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
delete(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'DELETE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
connect(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'CONNECT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN || MP-BAIDU
|
||||
head(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'HEAD',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
options(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'OPTIONS',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
trace(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'TRACE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
upload(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'UPLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
download(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'DOWNLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setConfig回调
|
||||
* @return {Object} - 返回操作后的config
|
||||
* @callback Request~setConfigCallback
|
||||
* @param {Object} config - 全局默认config
|
||||
*/
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
'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
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 默认的全局配置
|
||||
*/
|
||||
|
||||
|
||||
export default {
|
||||
baseURL: '',
|
||||
header: {},
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
responseType: 'text',
|
||||
// #endif
|
||||
custom: {},
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
timeout: 60000,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
sslVerify: true,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
withCredentials: false,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
firstIpv4: false,
|
||||
// #endif
|
||||
validateStatus: function validateStatus(status) {
|
||||
return status >= 200 && status < 300
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import adapter from '../adapters/index'
|
||||
|
||||
|
||||
export default (config) => {
|
||||
return adapter(config)
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import {deepMerge, isUndefined} from '../utils'
|
||||
|
||||
/**
|
||||
* 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
|
||||
* @param {Array} keys - 配置项
|
||||
* @param {Object} globalsConfig - 当前的全局配置
|
||||
* @param {Object} config2 - 局部配置
|
||||
* @return {{}}
|
||||
*/
|
||||
const mergeKeys = (keys, globalsConfig, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
} else if (!isUndefined(globalsConfig[prop])) {
|
||||
config[prop] = globalsConfig[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param globalsConfig - 当前实例的全局配置
|
||||
* @param config2 - 当前的局部配置
|
||||
* @return - 合并后的配置
|
||||
*/
|
||||
export default (globalsConfig, config2 = {}) => {
|
||||
const method = config2.method || globalsConfig.method || 'GET'
|
||||
let config = {
|
||||
baseURL: globalsConfig.baseURL || '',
|
||||
method: method,
|
||||
url: config2.url || '',
|
||||
params: config2.params || {},
|
||||
custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
|
||||
header: deepMerge(globalsConfig.header || {}, config2.header || {})
|
||||
}
|
||||
const defaultToConfig2Keys = ['getTask', 'validateStatus']
|
||||
config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
|
||||
|
||||
// eslint-disable-next-line no-empty
|
||||
if (method === 'DOWNLOAD') {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (!isUndefined(config2.timeout)) {
|
||||
config['timeout'] = config2['timeout']
|
||||
} else if (!isUndefined(globalsConfig.timeout)) {
|
||||
config['timeout'] = globalsConfig['timeout']
|
||||
}
|
||||
// #endif
|
||||
} else if (method === 'UPLOAD') {
|
||||
delete config.header['content-type']
|
||||
delete config.header['Content-Type']
|
||||
const uploadKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'fileType',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
'filePath',
|
||||
'name',
|
||||
// #ifdef H5 || APP-PLUS
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData',
|
||||
]
|
||||
uploadKeys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
|
||||
config['timeout'] = globalsConfig['timeout']
|
||||
}
|
||||
// #endif
|
||||
} else {
|
||||
const defaultsKeys = [
|
||||
'data',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
]
|
||||
config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Resolve or reject a Promise based on response status.
|
||||
*
|
||||
* @param {Function} resolve A function that resolves the promise.
|
||||
* @param {Function} reject A function that rejects the promise.
|
||||
* @param {object} response The response.
|
||||
*/
|
||||
export default function settle(resolve, reject, response) {
|
||||
const validateStatus = response.config.validateStatus
|
||||
const status = response.statusCode
|
||||
if (status && (!validateStatus || validateStatus(status))) {
|
||||
resolve(response)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
'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
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
'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
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
'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)
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
type AnyObject = Record<string | number | symbol, any>
|
||||
type HttpPromise<T> = Promise<HttpResponse<T>>;
|
||||
type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask
|
||||
export interface RequestTask {
|
||||
abort: () => void;
|
||||
offHeadersReceived: () => void;
|
||||
onHeadersReceived: () => void;
|
||||
}
|
||||
export interface HttpRequestConfig<T = Tasks> {
|
||||
/** 请求基地址 */
|
||||
baseURL?: string;
|
||||
/** 请求服务器接口地址 */
|
||||
url?: string;
|
||||
|
||||
/** 请求查询参数,自动拼接为查询字符串 */
|
||||
params?: AnyObject;
|
||||
/** 请求体参数 */
|
||||
data?: AnyObject;
|
||||
|
||||
/** 文件对应的 key */
|
||||
name?: string;
|
||||
/** HTTP 请求中其他额外的 form data */
|
||||
formData?: AnyObject;
|
||||
/** 要上传文件资源的路径。 */
|
||||
filePath?: string;
|
||||
/** 需要上传的文件列表。使用 files 时,filePath 和 name 不生效,App、H5( 2.6.15+) */
|
||||
files?: Array<{
|
||||
name?: string;
|
||||
file?: File;
|
||||
uri: string;
|
||||
}>;
|
||||
/** 要上传的文件对象,仅H5(2.6.15+)支持 */
|
||||
file?: File;
|
||||
|
||||
/** 请求头信息 */
|
||||
header?: AnyObject;
|
||||
/** 请求方式 */
|
||||
method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD";
|
||||
/** 如果设为 json,会尝试对返回的数据做一次 JSON.parse */
|
||||
dataType?: string;
|
||||
/** 设置响应的数据类型,App和支付宝小程序不支持 */
|
||||
responseType?: "text" | "arraybuffer";
|
||||
/** 自定义参数 */
|
||||
custom?: AnyObject;
|
||||
/** 超时时间,仅微信小程序(2.10.0)、支付宝小程序支持 */
|
||||
timeout?: number;
|
||||
/** DNS解析时优先使用ipv4,仅 App-Android 支持 (HBuilderX 2.8.0+) */
|
||||
firstIpv4?: boolean;
|
||||
/** 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) */
|
||||
sslVerify?: boolean;
|
||||
/** 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) */
|
||||
withCredentials?: boolean;
|
||||
|
||||
/** 返回当前请求的task, options。请勿在此处修改options。 */
|
||||
getTask?: (task: T, options: HttpRequestConfig<T>) => void;
|
||||
/** 全局自定义验证器 */
|
||||
validateStatus?: (statusCode: number) => boolean | void;
|
||||
}
|
||||
export interface HttpResponse<T = any> {
|
||||
config: HttpRequestConfig;
|
||||
statusCode: number;
|
||||
cookies: Array<string>;
|
||||
data: T;
|
||||
errMsg: string;
|
||||
header: AnyObject;
|
||||
}
|
||||
export interface HttpUploadResponse<T = any> {
|
||||
config: HttpRequestConfig;
|
||||
statusCode: number;
|
||||
data: T;
|
||||
errMsg: string;
|
||||
}
|
||||
export interface HttpDownloadResponse extends HttpResponse {
|
||||
tempFilePath: string;
|
||||
}
|
||||
export interface HttpError {
|
||||
config: HttpRequestConfig;
|
||||
statusCode?: number;
|
||||
cookies?: Array<string>;
|
||||
data?: any;
|
||||
errMsg: string;
|
||||
header?: AnyObject;
|
||||
}
|
||||
export interface HttpInterceptorManager<V, E = V> {
|
||||
use(
|
||||
onFulfilled?: (config: V) => Promise<V> | V,
|
||||
onRejected?: (config: E) => Promise<E> | E
|
||||
): void;
|
||||
eject(id: number): void;
|
||||
}
|
||||
export abstract class HttpRequestAbstract {
|
||||
constructor(config?: HttpRequestConfig);
|
||||
config: HttpRequestConfig;
|
||||
interceptors: {
|
||||
request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>;
|
||||
response: HttpInterceptorManager<HttpResponse, HttpError>;
|
||||
}
|
||||
middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>;
|
||||
request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>;
|
||||
delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
|
||||
download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>;
|
||||
|
||||
setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
|
||||
}
|
||||
|
||||
declare class HttpRequest extends HttpRequestAbstract { }
|
||||
export default HttpRequest;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import Request from './core/Request'
|
||||
export default Request
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
'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'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为真正的对象{} new Object
|
||||
* @param {any} obj - 检测的对象
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPlainObject(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function equal to merge with the difference being that no reference
|
||||
* to original objects is kept.
|
||||
*
|
||||
* @see merge
|
||||
* @param {Object} obj1 Object to merge
|
||||
* @returns {Object} Result of all merge properties
|
||||
*/
|
||||
export function deepMerge(/* obj1, obj2, obj3, ... */) {
|
||||
let result = {}
|
||||
function assignValue(val, key) {
|
||||
if (typeof result[key] === 'object' && typeof val === 'object') {
|
||||
result[key] = deepMerge(result[key], val)
|
||||
} else if (typeof val === 'object') {
|
||||
result[key] = deepMerge({}, val)
|
||||
} else {
|
||||
result[key] = val
|
||||
}
|
||||
}
|
||||
for (let i = 0, l = arguments.length; i < l; i++) {
|
||||
forEach(arguments[i], assignValue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function isUndefined (val) {
|
||||
return typeof val === 'undefined'
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export const SHJGTMPLID = 'Xejag3ttwOw_xLvXsrMULjnoNcm5bJIyu-ACnshUnKY';//审核结果
|
||||
|
||||
export const SFTZTMPLID = 'slzGT4a8GDQUjmd4uHrZmHYD8ta55KrXe9RTOrL0qRc';//收费通知
|
||||
|
|
@ -0,0 +1,462 @@
|
|||
|
||||
/**
|
||||
* 显示加载动画
|
||||
* @export
|
||||
* @param {string} [title="加载中..."]
|
||||
* @param {boolean} [mask=true]
|
||||
*/
|
||||
export function showLoading(title = "加载中...", mask = true) {
|
||||
uni.showLoading({
|
||||
title,
|
||||
mask
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 关闭加载动画
|
||||
* @export
|
||||
*/
|
||||
export function hideLoading() {
|
||||
uni.hideLoading()
|
||||
}
|
||||
/**
|
||||
* 轻提示框
|
||||
* @export
|
||||
* @param {*} title
|
||||
* @param {*} duration
|
||||
*/
|
||||
export function toast(title = "", icon = "none", duration = 2000, cb) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: icon,
|
||||
mask: false,
|
||||
duration,
|
||||
success: function() {
|
||||
cb && cb()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态设置当前页面的标题
|
||||
* @export
|
||||
*/
|
||||
export function setNavigationBarTitle(title = '') {
|
||||
uni.setNavigationBarTitle({
|
||||
title
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片预览
|
||||
* @export
|
||||
* @param {*} current
|
||||
* @param {*} [urls=[]]
|
||||
*/
|
||||
export function previewImage(current, urls = [],callback= () => {}) {
|
||||
uni.previewImage({
|
||||
current, // 当前显示图片的http链接
|
||||
urls ,// 需要预览的图片http链接列表,
|
||||
complete: function(e){
|
||||
callback(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 从本地相册选择图片或使用相机拍照
|
||||
* @export
|
||||
* @param {string} [sourceType=['album', 'camera']]
|
||||
* @param {*} cb
|
||||
*/
|
||||
export function chooseImage(count = 9, success = () => {}, err = () => {}) {
|
||||
uni.chooseImage({
|
||||
count,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success(res) {
|
||||
// tempFilePath可以作为img标签的src属性显示图片
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
success(tempFilePaths)
|
||||
},
|
||||
fail() {
|
||||
err()
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 从本地相册选择图片或使用相机拍照
|
||||
* @export
|
||||
* @param {string} [sourceType=['album', 'camera']]
|
||||
* @param {*} cb
|
||||
*/
|
||||
export function chooseVideo(success = () => {},err = () => {},sourceType = ['album', 'camera']) {
|
||||
uni.chooseVideo({
|
||||
sourceType: sourceType,
|
||||
success(res) {
|
||||
// tempFilePath可以作为img标签的src属性显示图片
|
||||
console.log(res);
|
||||
const tempFilePath = res.tempFilePath;
|
||||
success(tempFilePath,res)
|
||||
},
|
||||
fail() {
|
||||
err()
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 图片预览跟视频
|
||||
* @export
|
||||
* @param {*} current
|
||||
* @param {*} [urls=[]]
|
||||
*/
|
||||
export function previewMedia(current, sources = [],callback= () => {}) {
|
||||
uni.previewMedia({
|
||||
current, // 当前显示index
|
||||
sources ,// 需要预览的http链接列表,
|
||||
complete: function(e){
|
||||
callback(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 压缩图片接口,可选压缩质量
|
||||
* @export
|
||||
* @param {*} src
|
||||
* @param {*} [success=()=> {}]
|
||||
* @param {*} [err=()=> {}]
|
||||
*/
|
||||
export function compressImage(src, quality = 80, cb = () => {}, err = () => {}) {
|
||||
console.log(src, '|');
|
||||
uni.compressImage({
|
||||
src: src,
|
||||
quality: quality,
|
||||
success: res => {
|
||||
console.log(res.tempFilePath)
|
||||
cb(res.tempFilePath)
|
||||
},
|
||||
fail(e) {
|
||||
console.log("失败")
|
||||
err(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* setStorage 的同步版本
|
||||
* @export
|
||||
* @param {*} key
|
||||
* @param {*} val
|
||||
*/
|
||||
export function setStorageSync(key, val) {
|
||||
try {
|
||||
uni.setStorageSync(key, val)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
export function setStorage(key, val) {
|
||||
try {
|
||||
uni.setStorage({
|
||||
key:key,
|
||||
data:val
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* getStorage 的同步版本
|
||||
* @export
|
||||
* @param {*} key
|
||||
* @returns
|
||||
*/
|
||||
export function getStorageSync(key) {
|
||||
try {
|
||||
return uni.getStorageSync(key)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* removeStorage 的同步版本
|
||||
* @export
|
||||
* @param {*} key
|
||||
*/
|
||||
export function removeStorageSync(key) {
|
||||
try {
|
||||
uni.removeStorageSync(key)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clearStorage 的同步版本
|
||||
* @export
|
||||
*/
|
||||
export function clearStorageSync() {
|
||||
try {
|
||||
uni.clearStorageSync()
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 显示小红点
|
||||
* @export
|
||||
* @param {*} index
|
||||
*/
|
||||
export function showTabBarRedDot(index) {
|
||||
uni.showTabBarRedDot({
|
||||
index
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏小红点
|
||||
* @export
|
||||
* @param {*} index
|
||||
*/
|
||||
export function hideTabBarRedDot(index) {
|
||||
uni.hideTabBarRedDot({
|
||||
index
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回上一页
|
||||
* @export
|
||||
* @param
|
||||
*/
|
||||
export function navigateBack() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
success() {},
|
||||
fail() {
|
||||
var pages = getCurrentPages();
|
||||
var page = pages[pages.length - 2];
|
||||
if(page){
|
||||
uni.switchTab({
|
||||
url: page.route
|
||||
});
|
||||
}else{
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function formatDate(time, fmt) {
|
||||
if (!time) {
|
||||
return ''
|
||||
}
|
||||
let _date = new Date(time);
|
||||
let o = {
|
||||
'M+': _date.getMonth() + 1, // 月份
|
||||
'd+': _date.getDate(), // 日
|
||||
'h+': _date.getHours(), // 小时
|
||||
'm+': _date.getMinutes(), // 分
|
||||
's+': _date.getSeconds(), // 秒
|
||||
'q+': Math.floor((_date.getMonth() + 3) / 3), // 季度
|
||||
'S': _date.getMilliseconds() // 毫秒
|
||||
};
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (_date.getFullYear() + '').substr(4 - RegExp.$1.length));
|
||||
}
|
||||
for (let 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 isPhoneNumber(val){
|
||||
let rt = /^1\d{10}$/
|
||||
if(rt.test(val)){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function arrayKeyGroup(array,key='id'){
|
||||
let newArray = [];
|
||||
console.log(key)
|
||||
array.map(item=>{
|
||||
return [item]
|
||||
}).forEach(([{...item}])=>{
|
||||
const flag = newArray.find(([{...o}])=>o[key] === item[key]);
|
||||
if(!flag) {
|
||||
newArray.push([{...item}])
|
||||
} else {
|
||||
newArray.forEach(([{...y}], index)=>{
|
||||
if(y[key] === item[key]) {
|
||||
newArray[index].push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return newArray
|
||||
}
|
||||
|
||||
export function stringHide(string,start,end){
|
||||
let th = ''
|
||||
let xlen = end - start;
|
||||
for(let i =0;i < xlen;i++) {
|
||||
th += '*'
|
||||
}
|
||||
return string.substring(0,start) + th + string.substring(end,string.length)
|
||||
}
|
||||
|
||||
export function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i])
|
||||
const num2 = parseInt(v2[i])
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由跳转
|
||||
*
|
||||
* @param Object target {type, way, url}
|
||||
*/
|
||||
export function Target(target) {
|
||||
if (target.type === 'mini-program') {
|
||||
const way = target.way || 'navigateTo'
|
||||
const params = { url: target.url }
|
||||
switch (way) {
|
||||
case 'navigateTo':
|
||||
uni.navigateTo(params)
|
||||
break;
|
||||
case 'redirectTo':
|
||||
uni.redirectTo(params)
|
||||
break;
|
||||
case 'reLaunch':
|
||||
uni.reLaunch(params)
|
||||
break;
|
||||
case 'switchTab':
|
||||
uni.switchTab(params)
|
||||
break;
|
||||
case 'navigateBack':
|
||||
navigateBack()
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为空
|
||||
export function isEmpty(obj){
|
||||
if(typeof obj == "undefined" || obj == null || obj == ''){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getQueryName(str,name){
|
||||
let query = str.split('?')[1];
|
||||
let vars = query.split("&");
|
||||
for (let i=0;i<vars.length;i++) {
|
||||
let pair = vars[i].split("=");
|
||||
if(pair[0] == name){return pair[1];}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
//指定位置插入字符
|
||||
export function insertStr(soure, start, newStr){
|
||||
return soure.slice(0, start) + newStr + soure.slice(start);
|
||||
}
|
||||
export function getSubscribeMessage(tmplIds,callback= () => {}){
|
||||
let _tmplIds = tmplIds;
|
||||
wx.requestSubscribeMessage({
|
||||
tmplIds: _tmplIds,
|
||||
success: (res)=> {
|
||||
console.log(res,'成功')
|
||||
let acceptnum = 0;
|
||||
for(let vk of _tmplIds){
|
||||
if(res[vk]==='accept'){//同意
|
||||
acceptnum += 1
|
||||
}
|
||||
}
|
||||
if(acceptnum==0){
|
||||
|
||||
}else{
|
||||
|
||||
callback(res)
|
||||
}
|
||||
},
|
||||
fail:(err)=>{
|
||||
if (err.errCode == 20004) {
|
||||
console.log('用户拒绝了',err)
|
||||
}else{
|
||||
callback(res)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function testIdCard(id) {
|
||||
// 1 "验证通过!", 0 //校验不通过 // id为身份证号码
|
||||
var format = /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/;
|
||||
//号码规则校验
|
||||
if(!format.test(id)){
|
||||
return {'status':0,'msg':'身份证号码不合规'};
|
||||
}
|
||||
//区位码校验
|
||||
//出生年月日校验 前正则限制起始年份为1900;
|
||||
var year = id.substr(6,4),//身份证年
|
||||
month = id.substr(10,2),//身份证月
|
||||
date = id.substr(12,2),//身份证日
|
||||
time = Date.parse(month+'-'+date+'-'+year),//身份证日期时间戳date
|
||||
now_time = Date.parse(new Date()),//当前时间戳
|
||||
dates = (new Date(year,month,0)).getDate();//身份证当月天数
|
||||
if(time>now_time||date>dates){
|
||||
return {'status':0,'msg':'出生日期不合规'}
|
||||
}
|
||||
//校验码判断
|
||||
var c = new Array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2); //系数
|
||||
var b = new Array('1','0','X','9','8','7','6','5','4','3','2'); //校验码对照表
|
||||
var id_array = id.split("");
|
||||
var sum = 0;
|
||||
for(var k=0;k<17;k++){
|
||||
sum+=parseInt(id_array[k])*parseInt(c[k]);
|
||||
}
|
||||
if(id_array[17].toUpperCase() != b[sum%11].toUpperCase()){
|
||||
return {'status':0,'msg':'身份证校验码不合规'}
|
||||
}
|
||||
return {'status':1,'msg':'校验通过'}
|
||||
}
|
||||
export function testEmail(email){
|
||||
let regEmail = new RegExp("^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$");
|
||||
return regEmail.test(email)
|
||||
}
|
||||
export function testBank(bank){
|
||||
let reg = /[1-9]\d{12,18}/;
|
||||
return reg.test(bank)
|
||||
}
|
||||
export function testPhone(phone){
|
||||
let reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
|
||||
return reg.test(phone)
|
||||
}
|
||||
|
|
@ -1,12 +1,18 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import './uni.promisify.adaptor'
|
||||
|
||||
import uView from "uview-ui";
|
||||
Vue.use(uView);
|
||||
import {http,getFullUrl} from '@/api/index.js'
|
||||
import store from './store/index.js'
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.prototype.$http = http
|
||||
Vue.prototype.$getFullUrl = getFullUrl
|
||||
App.mpType = 'app'
|
||||
|
||||
const app = new Vue({
|
||||
store,
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
|
|
|
|||
|
|
@ -1,16 +1,66 @@
|
|||
{
|
||||
"easycom": {
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "uni-app"
|
||||
"navigationBarTitleText": "隆昌农业大数据监控平台"
|
||||
}
|
||||
}
|
||||
,{
|
||||
"path" : "pages/login/login",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
}
|
||||
,{
|
||||
"path" : "pages/user/user",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
|
||||
}
|
||||
,{
|
||||
"path" : "pages/user/password-edit",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "修改密码",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "uni-app",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarTitleText": "隆昌农业大数据监控平台",
|
||||
"navigationBarBackgroundColor": "#2a7dc9",
|
||||
"backgroundColor": "#2a7dc9"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#6c6b6b",
|
||||
"selectedColor": "#1296db",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/tab/tab_home.png",
|
||||
"selectedIconPath": "static/tab/tab_home_h.png",
|
||||
"text": "工作台"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/user/user",
|
||||
"iconPath": "static/tab/tab_user.png",
|
||||
"selectedIconPath": "static/tab/tab_user_h.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<image class="logo" src="/static/logo.png"></image>
|
||||
<view>
|
||||
<text class="title">{{title}}</text>
|
||||
</view>
|
||||
<view class="index-page">
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,218 @@
|
|||
<template>
|
||||
<view class="login-page">
|
||||
<view class="img-a">
|
||||
<view class="t-b">
|
||||
隆昌农业大数据监控平台
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="login-view" style="">
|
||||
<view class="t-login">
|
||||
<form class="cl">
|
||||
<view class="t-a">
|
||||
<text class="txt">账号</text>
|
||||
<input type="text" name="username" placeholder="请输入您的账号"
|
||||
v-model="username" />
|
||||
</view>
|
||||
<view class="t-a">
|
||||
<text class="txt">密码</text>
|
||||
<input type="password" name="password" maxlength="18"
|
||||
placeholder="请输入您的密码" v-model="password" />
|
||||
</view>
|
||||
<button @tap="login()" type="button">登 录</button>
|
||||
<!-- <view class="reg" @tap="reg()">注 册</view> -->
|
||||
</form>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {getStorageSync,setStorageSync,setStorage, toast} from '@/com/utils.js'
|
||||
import jwt from '@/api/jwt.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
username: '', //手机号码
|
||||
password: '' //密码
|
||||
};
|
||||
},
|
||||
onLoad() {},
|
||||
methods: {
|
||||
//当前登录按钮操作
|
||||
login() {
|
||||
if (!this.username) {
|
||||
uni.showToast({ title: '请输入您的账号', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.password) {
|
||||
uni.showToast({ title: '请输入您的密码', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
username:this.username,
|
||||
password:this.password
|
||||
};
|
||||
|
||||
this.$http.post('/api/auth/login',params,{
|
||||
custom:{
|
||||
auth:false
|
||||
}
|
||||
}).then(({data})=>{
|
||||
console.log(data);
|
||||
if(data.code==200){
|
||||
let _data = data.data;
|
||||
let _info = _data.info;
|
||||
console.log(_data)
|
||||
jwt.setAccessToken(_data.token)
|
||||
this.$store.dispatch('USER_INFO',_info);
|
||||
uni.switchTab({
|
||||
url:'/pages/index/index'
|
||||
})
|
||||
}
|
||||
|
||||
}).catch(()=>{
|
||||
|
||||
})
|
||||
uni.showToast({ title: '登录成功!', icon: 'none' });
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.login-page{
|
||||
.txt {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.img-a {
|
||||
width: 100%;
|
||||
height: 450rpx;
|
||||
background-image: url(../../static/head.png);
|
||||
background-size: 100%;
|
||||
}
|
||||
.reg {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 50rpx;
|
||||
font-weight: bold;
|
||||
background: #f5f6fa;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.login-view {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin-top: -120rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8% 8% 0% 0;
|
||||
}
|
||||
|
||||
.t-login {
|
||||
width: 600rpx;
|
||||
margin: 0 auto;
|
||||
font-size: 28rpx;
|
||||
padding-top: 80rpx;
|
||||
}
|
||||
|
||||
.t-login button {
|
||||
font-size: 28rpx;
|
||||
background: #2796f2;
|
||||
color: #fff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 50rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.t-login input {
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
margin-bottom: 50rpx;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.t-login .t-a {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.t-b {
|
||||
text-align: left;
|
||||
font-size: 42rpx;
|
||||
color: #ffffff;
|
||||
padding: 130rpx 0 0 70rpx;
|
||||
font-weight: bold;
|
||||
line-height: 70rpx;
|
||||
}
|
||||
|
||||
.t-login .t-c {
|
||||
position: absolute;
|
||||
right: 22rpx;
|
||||
top: 22rpx;
|
||||
background: #5677fc;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
border-radius: 50rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.t-login .t-d {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
margin: 80rpx 0;
|
||||
}
|
||||
|
||||
.t-login .t-e {
|
||||
text-align: center;
|
||||
width: 250rpx;
|
||||
margin: 80rpx auto 0;
|
||||
}
|
||||
|
||||
.t-login .t-g {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.t-login .t-e image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
|
||||
.t-login .t-f {
|
||||
text-align: center;
|
||||
margin: 150rpx 0 0 0;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.t-login .t-f text {
|
||||
margin-left: 20rpx;
|
||||
color: #aaaaaa;
|
||||
font-size: 27rpx;
|
||||
}
|
||||
|
||||
.t-login .uni-input-placeholder {
|
||||
color: #aeaeae;
|
||||
}
|
||||
|
||||
.cl {
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.cl:after {
|
||||
clear: both;
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
content: '\20';
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<view class="password-page">
|
||||
<u-form :model="form" ref="uForm">
|
||||
<u-form-item label="密码:" label-width="100">
|
||||
<u-input v-model="form.password" :type="type" :password-icon="passwordIcon" :clearable="true"/>
|
||||
</u-form-item>
|
||||
<u-form-item label="确认密码:" label-width="150">
|
||||
<u-input v-model="form.password_confirmation" :type="type" :password-icon="passwordIcon" :clearable="true"/>
|
||||
</u-form-item>
|
||||
<view class="btns" style="margin-top: 68rpx;">
|
||||
<u-button type="primary" @click="passwordEditFn()">确定</u-button>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
password: '',
|
||||
password_confirmation: '',
|
||||
},
|
||||
type: 'password',
|
||||
passwordIcon: true,
|
||||
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
methods:{
|
||||
passwordEditFn(){
|
||||
console.log(this.form);
|
||||
if (!this.form.password) {
|
||||
uni.showToast({ title: '请输入新密码', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!this.form.password_confirmation) {
|
||||
uni.showToast({ title: '请输入确认密码', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (this.form.password != this.form.password_confirmation) {
|
||||
uni.showToast({ title: '两次密码不一致', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.$http.put('/api/users/reset-password',this.form).then(({data})=>{
|
||||
console.log(data)
|
||||
if(data.code==200){
|
||||
|
||||
}else{
|
||||
uni.showToast({ title: data.message, icon: 'none' });
|
||||
}
|
||||
}).catch(()=>{
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.password-page{
|
||||
padding: 32rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
<template>
|
||||
<view class="user-page ">
|
||||
<u-navbar :is-back="false" :title="title" :title-color="titleColor"
|
||||
:background="background" :border-bottom="false" :back-icon-color="backIconColor"></u-navbar>
|
||||
<view class="top-section-box">
|
||||
<view class="top-box">
|
||||
<view class="user-box">
|
||||
<view class="user-pic" @click="linkLoginF">
|
||||
<image class="upic" :src="userInfo.avatar?userInfo.avatar:''"></image>
|
||||
</view>
|
||||
<view class="desc-box">
|
||||
<view class="name">{{userInfo.name}}</view>
|
||||
<view class="tel">{{userInfo.phone|hidePhone}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg_linec"></view>
|
||||
</view>
|
||||
<view class="content-box">
|
||||
<view class="pdlr18">
|
||||
<view class="card-box flex-row">
|
||||
<view class="p-list">
|
||||
<view class="txt clamp">{{userInfo.username?userInfo.username:'——'}}</view>
|
||||
<view class="tit">登录名</view>
|
||||
</view>
|
||||
<view class="p-list clamp">
|
||||
<view class="txt">{{userInfo.department?userInfo.department:'——'}}</view>
|
||||
<view class="tit">角色</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav_title">系统管理</view>
|
||||
<view class="nav-box">
|
||||
<view class="nav-list" @click="linnavF('/pages/user/password-edit')">
|
||||
<view class="icon_img">
|
||||
<u-icon name="lock-open" size="46"></u-icon>
|
||||
</view>
|
||||
<view class="item-c">
|
||||
<view class="tname">修改密码</view>
|
||||
<view class="arrow_R"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-list" @click="linnavF('/pages/user/password-edit')">
|
||||
<view class="icon_img">
|
||||
<u-icon name="man-add" size="46"></u-icon>
|
||||
</view>
|
||||
<view class="item-c">
|
||||
<view class="tname">角色管理</view>
|
||||
<view class="arrow_R"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-list" @click="linnavF('/pages/user/password-edit')">
|
||||
<view class="icon_img">
|
||||
<u-icon name="account" size="46"></u-icon>
|
||||
</view>
|
||||
<view class="item-c">
|
||||
<view class="tname">账号管理</view>
|
||||
<view class="arrow_R"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-list" @click="linnavF('/pages/user/password-edit')">
|
||||
<view class="icon_img">
|
||||
<u-icon name="clock" size="46"></u-icon>
|
||||
</view>
|
||||
<view class="item-c">
|
||||
<view class="tname">系统日志</view>
|
||||
<view class="arrow_R"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="nav-list" @click="linnavF('/pages/user/password-edit')">
|
||||
<view class="icon_img">
|
||||
<u-icon name="attach" size="46"></u-icon>
|
||||
</view>
|
||||
<view class="item-c">
|
||||
<view class="tname">友情链接</view>
|
||||
<view class="arrow_R"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 退出 -->
|
||||
<view class="yr-loginout">
|
||||
<u-button type="error" :plain="true" @click="loginOut()">退出系统</u-button>
|
||||
</view>
|
||||
</view>
|
||||
<u-modal v-model="show" :content="content" @confirm="handleLoginOut()" :show-cancel-button="true"></u-modal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters,mapActions} from 'vuex'
|
||||
import {USER_INFO} from '@/store/mutation-types.js'
|
||||
import {showLoading,toast,setStorage,stringHide} from '@/com/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
title:"个人中心",
|
||||
titleColor:"#ffffff",
|
||||
backIconColor:"#ffffff",
|
||||
background:{
|
||||
backgroundColor:"#2a7dc9"
|
||||
},
|
||||
show:false,
|
||||
content:'是否确认退出系统?'
|
||||
};
|
||||
},
|
||||
filters:{
|
||||
hidePhone(val){
|
||||
if(val){
|
||||
return stringHide(val,3,8)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['userInfo'])
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
onShow() {
|
||||
console.log(this.userInfo)
|
||||
this.getUserInfo()
|
||||
},
|
||||
methods:{
|
||||
getUserInfo(){
|
||||
this.$http.get('/api/users/info').then(({data})=>{
|
||||
if(data.code==200){
|
||||
let user = data.data.info;
|
||||
let userInfo = {...this.userInfo,...user};
|
||||
console.log(userInfo,'=====bbb====')
|
||||
this.$store.dispatch('USER_INFO',userInfo);
|
||||
}
|
||||
|
||||
}).catch(err=>{
|
||||
|
||||
})
|
||||
},
|
||||
linnavF(url){
|
||||
uni.navigateTo({
|
||||
url:url
|
||||
})
|
||||
},
|
||||
loginOut(){
|
||||
this.show = true;
|
||||
},
|
||||
//退出
|
||||
handleLoginOut(){
|
||||
this.$http.delete('/api/users/logout').then(({data})=>{
|
||||
if(data.code==200){
|
||||
uni.reLaunch({
|
||||
url:'/pages/login/login'
|
||||
})
|
||||
}
|
||||
}).catch(()=>{
|
||||
uni.reLaunch({
|
||||
url:'/pages/login/login'
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.top-section-box{
|
||||
.top-box{
|
||||
background-color: #2a7dc9;
|
||||
}
|
||||
.user-box{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
.user-pic{
|
||||
flex: 0 0 134rpx;
|
||||
width: 134rpx;
|
||||
height: 134rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
.upic{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.desc-box{
|
||||
flex: 1;
|
||||
width: 0;
|
||||
color: #FFFFFF;
|
||||
padding-left: 24rpx;
|
||||
.name{
|
||||
font-size: 34rpx;
|
||||
}
|
||||
.tel{
|
||||
font-size: 34rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.bg_linec{
|
||||
width: 100%;
|
||||
height: 110rpx;
|
||||
background-color: #2a7dc9;
|
||||
border-radius: 0 0 100% 100%;
|
||||
margin-top: -60rpx;
|
||||
}
|
||||
.content-box{
|
||||
padding: 0 20rpx;
|
||||
.card-box{
|
||||
min-height: 170rpx;
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #FFFFFF;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: -50rpx;
|
||||
border-radius: 12rpx;
|
||||
box-shadow:0 0 20rpx rgba(0,0,0,0.15);
|
||||
justify-content: center;
|
||||
.p-list{
|
||||
margin: 10rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
flex: 1;
|
||||
width: 33%;
|
||||
text-align: center;
|
||||
.tit{
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
.txt{
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav_title{
|
||||
padding: 20rpx 20rpx 0 20rpx;
|
||||
// font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.nav-box{
|
||||
padding-top: 24rpx;
|
||||
background-color: #FFFFFF;
|
||||
padding-left: 20rpx;
|
||||
padding-right: 20rpx;
|
||||
padding-bottom: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.nav-list{
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #FFFFFF;
|
||||
padding-left: 10rpx;
|
||||
position: relative;
|
||||
&::after{
|
||||
content:'';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
transform: scaleY(.5);
|
||||
}
|
||||
.icon_img{
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
margin-right: 20rpx;
|
||||
color: #666;
|
||||
.img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.item-c{
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-right: 36rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
.arrow_R{
|
||||
width: 15rpx;
|
||||
height: 25rpx;
|
||||
background: url(../../static/img/my_arrow_right.png) no-repeat center;
|
||||
background-size: 100%;
|
||||
}
|
||||
}
|
||||
&.noBorder{
|
||||
.item-c{
|
||||
&::after{
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.yr-loginout{
|
||||
margin-top: 140rpx;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
|
@ -0,0 +1,16 @@
|
|||
import * as types from "./mutation-types";
|
||||
import {getStorageSync,setStorageSync,setStorage} from '@/com/utils.js'
|
||||
const actions = {
|
||||
[types.USER_INFO]({commit},userInfo){
|
||||
let _data = {};
|
||||
if(userInfo&&userInfo.id){
|
||||
_data = userInfo;
|
||||
// setStorage('userInfo',userInfo)
|
||||
}else{
|
||||
_data = getStorageSync('userInfo');
|
||||
}
|
||||
commit(types.USER_INFO, _data);
|
||||
},
|
||||
};
|
||||
|
||||
export default actions;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
//用户信息
|
||||
export const userInfo = (state)=> state.userInfo
|
||||
//token
|
||||
export const token = (state)=> state.user_access_token
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import Vue from "vue";
|
||||
import Vuex from "vuex";
|
||||
import actions from "./actions";
|
||||
import * as getters from "./getters";
|
||||
import state from "./state";
|
||||
import mutations from "./mutations";
|
||||
import createPersistedState from 'vuex-persistedstate';
|
||||
Vue.use(Vuex);
|
||||
|
||||
// store
|
||||
const store = new Vuex.Store({
|
||||
getters,
|
||||
state,
|
||||
actions,
|
||||
mutations,
|
||||
plugins: [
|
||||
createPersistedState({
|
||||
// 当state中的值发生变化的时候出发reduce函数
|
||||
reducer(val) {
|
||||
console.log(val,'createPersistedState') // value值为当前state中的所有值对象
|
||||
// return什么,localstorage中的key值为vuex的value值就是什么,而且是实时与state中的值保持同步
|
||||
return {
|
||||
userInfo: val.userInfo
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// ------------------------------------mustions types------------------------------------//
|
||||
//用户信息
|
||||
export const USER_INFO = 'USER_INFO'
|
||||
export const USERACCESSTOKEN = 'USERACCESSTOKEN'
|
||||
export const USERKEY = 'USERKEY'
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import * as types from "./mutation-types";
|
||||
const mutations = {
|
||||
// 设置用户信息
|
||||
[types.USER_INFO](state, userInfo) {
|
||||
state.userInfo = userInfo
|
||||
},
|
||||
[types.USERACCESSTOKEN](state, token) {
|
||||
state.user_access_token = token
|
||||
},
|
||||
[types.USERKEY](state, userkey) {
|
||||
state.user_key = userkey
|
||||
},
|
||||
};
|
||||
export default mutations;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
const state = {
|
||||
userInfo: {},
|
||||
user_access_token: '',
|
||||
user_key:'',
|
||||
};
|
||||
|
||||
export default state;
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
@import 'uview-ui/theme.scss';
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
|
|
|
|||