Browse Source

feat: vue3

refact
xuesinan 4 years ago
parent
commit
12ed2ad63c
  1. 100
      App.vue
  2. 10
      CHANGELOG.md
  3. 81
      apis/tall.js
  4. 7
      apis/wbs.js
  5. 60
      common/js/request.js
  6. 59
      common/js/util.js
  7. 49
      main.js
  8. 106
      package.json
  9. 2
      pages/index/index.vue
  10. 3
      store/db/actions.js
  11. 3
      store/db/getters.js
  12. 12
      store/db/index.js
  13. 3
      store/db/mutations.js
  14. 7
      store/db/state.js
  15. 80
      store/index.js
  16. 3
      store/messages/getters.js
  17. 4
      store/messages/index.js
  18. 85
      store/messages/mutations.js
  19. 8
      store/messages/state.js
  20. 3
      store/project/actions.js
  21. 12
      store/project/getters.js
  22. 12
      store/project/index.js
  23. 43
      store/project/mutations.js
  24. 8
      store/project/state.js
  25. 17
      store/role/actions.js
  26. 13
      store/role/getters.js
  27. 12
      store/role/index.js
  28. 39
      store/role/mutations.js
  29. 8
      store/role/state.js
  30. 154
      store/socket/actions.js
  31. 5
      store/socket/index.js
  32. 26
      store/socket/mutations.js
  33. 7
      store/socket/state.js
  34. 33
      store/task/actions.js
  35. 23
      store/task/getters.js
  36. 12
      store/task/index.js
  37. 238
      store/task/mutations.js
  38. 25
      store/task/state.js
  39. 39
      store/user/actions.js
  40. 28
      store/user/getters.js
  41. 22
      store/user/index.js
  42. 48
      store/user/mutations.js
  43. 10
      store/user/state.js
  44. 62
      utils/cache.js
  45. 190
      utils/cacheAndRequest.js
  46. 118
      utils/request.js
  47. 112
      utils/storage.js
  48. 34
      utils/tall.js
  49. 366
      utils/time.js
  50. 59
      utils/ui.js
  51. 110
      utils/upload.js

100
App.vue

@ -1,31 +1,77 @@
<script>
// import {
// ref,
// computed
// } from 'vue';
// import {
// useStore
// } from 'vuex';
// const store = useStore();
// onLaunch(() => {
// // checkNetwork(); //
// });
// store
// 2g 3g ;
// function checkNetwork() {
// uni.getNetworkType({
// success: ({ networkType }) => {
// this.setNetworkConnected(!(networkType === 'none' || networkType === '2g' || networkType === '3g'));
// },
// });
// //
// uni.onNetworkStatusChange(({ isConnected, networkType }) => {
// this.setNetworkConnected(isConnected && !(networkType === '2g' || networkType === '3g'));
// });
// }
import { ref, computed } from 'vue';
import store from '@/store/index.js';
import util from '@/common/js/util.js'
export default {
setup() {
return {
}
},
async onLaunch(options) {
console.log('options: ', options);
this.checkNetwork(); //
this.getSystemInfo(); //
// - H5APP
/* #ifndef MP-WEIXIN */
if (!store.state.user.token) {
// tokenuserIdtoken
// token userId
if (!options.query || !options.query.u) {
// u (userId)
uni.showToast({title: '缺少用户信息参数', icon: 'none'});
} else {
const data = await store.dispatch('user/getToken', options.query.u);
// const data = await this.getToken(options.query.u);
// this.noPhone(data.phone);
}
}
/* #endif */
},
methods: {
// store
// 2g 3g ;
checkNetwork() {
uni.getNetworkType({
success: ({ networkType }) => {
store.commit('setNetworkConnected', !(networkType === 'none' || networkType === '2g' || networkType === '3g'));
},
});
//
uni.onNetworkStatusChange(({ isConnected, networkType }) => {
store.commit('setNetworkConnected', isConnected && !(networkType === '2g' || networkType === '3g'));
});
},
//
getSystemInfo() {
uni.getSystemInfo({
success: result => {
store.commit('setSystemInfo', result);
},
fail: error => {
console.error('getSystemInfo fail:', error);
},
});
},
/**
* 没有手机号 跳转绑定手机号的界面
* @param {string} phone
*/
async noPhone(phone) {
if (!phone) {
this.$u.route('/pages/phone-bind/phone-bind');
}
},
}
}
</script>
<style lang="scss">

10
CHANGELOG.md

@ -1,6 +1,12 @@
# 1.0.0 (2021-12-31)
# 1.0.0 (2022-01-04)
### 🌟 新功能
范围|描述|commitId
--|--|--
- | Initial commit | 52b8f49
- | first commit | [8dc26de](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/8dc26de)
范围|描述|commitId
--|--|--
- | Initial commit | [52b8f49](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/52b8f49)

81
apis/tall.js

@ -0,0 +1,81 @@
const apiUrl = 'https://test.tall.wiki/gateway'; // 测试
// const apiUrl = 'https://www.tall.wiki/gateway'; // 生产
const tall = `${apiUrl}/tall3/v3.0`;
// 登录
export const login = {
async index(params) {
try {
const data = await uni.$u.http.post(`${tall}/users/signin`, params);
return data;
} catch (error) {
throw new Error(error);
}
},
};
export const getToken = userId => uni.config.globalProperties.$u.get(`${tall}/users/userId`, { userId });
const install = (Vue, vm) => {
vm.$u.api = { ...vm.$u.api } || {};
// 登录
vm.$u.api.signin = params => login.index(params);
// 获取图片验证码
vm.$u.api.getImageCode = () => vm.$u.get(`${tall}/users/code`);
// 获取短信验证码
vm.$u.api.getSmsCode = params => vm.$u.get(`${tall}/users/smscode`, params);
// 根据userId获取token
vm.$u.api.getToken = userId => vm.$u.get(`${tall}/users/userId`, { userId });
// 绑定手机号
vm.$u.api.phoneBind = (phone, smsCode) => vm.$u.http.post(`${tall}/users/binding`, { phone, smsCode });
// 是否合并账号
vm.$u.api.phoneMerge = (phone, isMerge) => vm.$u.http.post(`${tall}/users/merge`, { phone, isMerge });
// 修改用户信息
vm.$u.api.updateUserInfo = params => vm.$u.http.post(`${tall}/users/userInfo`, params);
// 获取项目列表
vm.$u.api.getProjects = (startTime, endTime) => vm.$u.post(`${tall}/project/query`, { startTime, endTime });
// 查询日历是否有小红点
vm.$u.api.findRedPoint = (startTime, endTime) => vm.$u.post(`${tall}/project/day`, { startTime, endTime });
// 设置项目顺序
vm.$u.api.setProjectSort = params => vm.$u.post(`${tall}/project/setProjectSort`, params);
// 设置项目父子结构
vm.$u.api.setProjectRelation = params => vm.$u.post(`${tall}/project/setProjectRelation`, params);
// 删除某个项目
vm.$u.api.delProject = projectId => vm.$u.post(`${tall}/project/deleteProject`, { projectId });
};
export default {
install
};
// export function setupTall(app) {
// app.config.globalProperties.$u.api = { ...app.config.globalProperties.$u.api } || {};
// // 登录
// // app.config.globalProperties.$u.api.signin = params => login.index(params);
// // 获取图片验证码
// // app.config.globalProperties.$u.api.getImageCode = () => app.config.globalProperties.$u.get(`${tall}/users/code`);
// // 获取短信验证码
// // app.config.globalProperties.$u.api.getSmsCode = params => app.config.globalProperties.$u.get(`${tall}/users/smscode`, params);
// // 根据userId获取token
// const getToken = userId => app.config.globalProperties.$u.get(`${tall}/users/userId`, { userId });
// // 绑定手机号
// // app.config.globalProperties.$u.api.phoneBind = (phone, smsCode) => app.config.globalProperties.$u.http.post(`${tall}/users/binding`, { phone, smsCode });
// // 是否合并账号
// // app.config.globalProperties.$u.api.phoneMerge = (phone, isMerge) => app.config.globalProperties.$u.http.post(`${tall}/users/merge`, { phone, isMerge });
// // 修改用户信息
// // app.config.globalProperties.$u.api.updateUserInfo = params => app.config.globalProperties.$u.http.post(`${tall}/users/userInfo`, params);
// // 获取项目列表
// // app.config.globalProperties.$u.api.getProjects = (startTime, endTime) => app.config.globalProperties.$u.post(`${tall}/project/query`, { startTime, endTime });
// // 查询日历是否有小红点
// // app.config.globalProperties.$u.api.findRedPoint = (startTime, endTime) => app.config.globalProperties.$u.post(`${tall}/project/day`, { startTime, endTime });
// // 设置项目顺序
// // app.config.globalProperties.$u.api.setProjectSort = params => app.config.globalProperties.$u.post(`${tall}/project/setProjectSort`, params);
// // 设置项目父子结构
// // app.config.globalProperties.$u.api.setProjectRelation = params => app.config.globalProperties.$u.post(`${tall}/project/setProjectRelation`, params);
// // 删除某个项目
// // app.config.globalProperties.$u.api.delProject = projectId => app.config.globalProperties.$u.post(`${tall}/project/deleteProject`, { projectId });
// }

7
apis/wbs.js

@ -0,0 +1,7 @@
const install = (Vue, vm) => {
vm.$u.api = { ...vm.$u.api } || {};
// 导入wbs
vm.$u.api.import = formData => vm.$t.chooseAndUpload(`${uni.$t.domain}/wbs`, formData);
};
export default { install };

60
common/js/request.js

@ -0,0 +1,60 @@
const install = (Vue, vm) => {
Vue.prototype.$u.http.setConfig({
baseUrl: '',
showLoading: true, // 是否显示请求中的loading
loadingText: '玩命加载中...',
loadingTime: 800,
loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
// 配置请求头信息
header: {
'content-type': 'application/json;charset=UTF-8'
},
});
// 请求拦截部分,如配置,每次请求前都会执行
Vue.prototype.$u.http.interceptor.request = config => {
const token = vm.$store.state.user.token || uni.$t.storage.getStorageSync(uni.$t.app.tokenKey);
if (token) {
config.header.Authorization = `Bearer ${token}`;
}
return config;
};
// 响应拦截,如配置,每次请求结束都会执行本方法
Vue.prototype.$u.http.interceptor.response = res => {
if (res.code === 200) {
// res为服务端返回值,可能有code,result等字段
// 这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到
// 如果配置了originalData为true,请留意这里的返回值
return res.data;
} else if (res.code === 401) {
// 假设201为token失效,这里跳转登录
vm.$u.toast('验证失败,请重新登录');
setTimeout(() => {
// 此为uView的方法,详见路由相关文档
vm.$u.route('/pages/user/login');
}, 1500);
return false;
} else {
// 如果返回false,则会调用Promise的reject回调,
// 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
return false;
}
};
Vue.prototype.$u.post = (url, param = {}, header = {}) => {
return Vue.prototype.$u.http.request({
url,
method: 'POST',
header,
data: {
param
},
});
};
};
export default {
install
};

59
common/js/util.js

@ -0,0 +1,59 @@
export default {
/**
* 显示toast
* @param {string} title 提示内容
* @param {number} duration 显示时间 默认2000
*/
showToast(title, duration = 2000) {
return uni.showToast({
title,
icon: 'none',
duration,
mask: true,
});
},
// 隐藏toast
hideToast() {
return uni.hideToast();
},
/**
* 显示加载雪花
* @param {string} title
*/
showLoading(title = '玩命加载中...') {
return uni.showLoading({
title,
mask: true,
});
},
// 隐藏loading
hideLoading() {
return uni.hideLoading();
},
/**
* 显示modal弹出框
* @param {string} title 标题
* @param {string} content 内容
* @param {boolean} showCancel 是否显示取消按钮 默认true
*/
showModal(title, content, showCancel = true) {
return new Promise(function(resolve, reject) {
uni.showModal({
title,
content,
showCancel,
success: ({
confirm,
cancel
}) => {
confirm && resolve();
cancel && reject();
},
});
});
},
};

49
main.js

@ -1,23 +1,28 @@
import App from './App'
import uView from './uni_modules/vk-uview-ui'; // 引入 uView UI
// #ifndef VUE3
import Vue from 'vue'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
app.use(uView) // 使用 uView UI
return {
app
}
import { createSSRApp } from 'vue';
import App from './App';
import uView from './uni_modules/vk-uview-ui'; // 引入 uView UI
import store from "./store";
import tall from '@/apis/tall.js';
import request from '@/utils/request.js';
// import Tall from '@/utils/tall.js';
// import { setupHttp } from '@/utils/request.js'
// import { setupTall } from '@/apis/tall.js'
export function createApp() {
const app = createSSRApp(App)
app.use(uView); // 使用 uView UI
app.use(store);
// app.use(request);
// app.use(tall);
// app.use(Tall);
// setupHttp(app);
// setupTall(app);
app.config.globalProperties.$tall = tall;
app.config.globalProperties.$request = request;
return {
app
}
}
// #endif

106
package.json

@ -1,54 +1,54 @@
{
"name": "tall-4",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"commitizen": "^4.2.4",
"commitlint": "^16.0.1",
"conventional-changelog": "^3.1.25",
"conventional-changelog-cli": "^2.2.2",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.2.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.4",
"prettier": "^2.5.1",
"right-pad": "^1.0.1",
"vue-cli-plugin-commitlint": "^1.0.12"
},
"browserslist": [
"Android >= 4",
"ios >= 8"
],
"config": {
"commitizen": {
"path": "./node_modules/vue-cli-plugin-commitlint/lib/cz"
}
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,json,css,vue}": [
"eslint --fix",
"git add"
],
"*.js": "eslint --cache --fix"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"cz": "npm run log && git add . && git cz",
"log": "conventional-changelog --config ./node_modules/vue-cli-plugin-commitlint/lib/log -i CHANGELOG.md -s -r 0"
},
"author": "",
"license": "ISC"
{
"name": "tall-4",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"commitizen": "^4.2.4",
"commitlint": "^16.0.1",
"conventional-changelog": "^3.1.25",
"conventional-changelog-cli": "^2.2.2",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.2.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.4",
"prettier": "^2.5.1",
"right-pad": "^1.0.1",
"vue-cli-plugin-commitlint": "^1.0.12"
},
"browserslist": [
"Android >= 4",
"ios >= 8"
],
"config": {
"commitizen": {
"path": "./node_modules/vue-cli-plugin-commitlint/lib/cz"
}
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,json,css,vue}": [
"eslint --fix",
"git add"
],
"*.js": "eslint --cache --fix"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"cz": "npm run log && git add . && git cz",
"log": "conventional-changelog --config ./node_modules/vue-cli-plugin-commitlint/lib/log -i CHANGELOG.md -s -r 0"
},
"author": "",
"license": "ISC"
}

2
pages/index/index.vue

@ -2,7 +2,7 @@
<view :style="{ height: height }" class="flex flex-col overflow-hidden u-font-14">
<!-- 标题栏 -->
<Title />
<view class="container flex flex-col flex-1 mx-auto overflow-hidden bg-gray-100">
<!-- 角色栏 -->
<Roles />

3
store/db/actions.js

@ -1,3 +0,0 @@
const actions = {};
export default actions;

3
store/db/getters.js

@ -1,3 +0,0 @@
const getters = {};
export default getters;

12
store/db/index.js

@ -1,12 +0,0 @@
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

3
store/db/mutations.js

@ -1,3 +0,0 @@
const mutations = {};
export default mutations;

7
store/db/state.js

@ -1,7 +0,0 @@
const state = {
db: null, // indexedDB对象
name: 'TALL_indexedDB',
version: 1,
};
export default state;

80
store/index.js

@ -1,36 +1,44 @@
import Vue from 'vue';
import Vuex from 'vuex';
import messages from './messages/index';
import project from './project/index';
import role from './role/index';
import socket from './socket/index';
import task from './task/index';
import user from './user/index';
// 不属于具体模块的 应用级的 store内容
const state = {
networkConnected: true, // 网络是否连接
forceUseStorage: true, // 强制启用storage
};
const getters = {
// 是否启用本地存储
// 设置了强制启用本地存储 或者 没有网络连接的时候
useStorage({ networkConnected, forceUseStorage }) {
return forceUseStorage || !networkConnected;
},
};
const mutations = {
/**
* 设置网络是否连接的变量
* @param {*} state
* @param {boolean} networkConnected
*/
setNetworkConnected(state, networkConnected) {
state.networkConnected = networkConnected;
},
};
Vue.use(Vuex);
export default new Vuex.Store({ state, getters, mutations, modules: { user, messages, socket, project, role, task } });
import { createStore } from 'vuex';
import user from './user/index.js';
// 不属于具体模块的 应用级的 store内容
const state = {
networkConnected: true, // 网络是否连接
forceUseStorage: true, // 强制启用storage
systemInfo: null, // 系统设备信息
};
const getters = {
// 是否启用本地存储
// 设置了强制启用本地存储 或者 没有网络连接的时候
useStorage({ networkConnected, forceUseStorage }) {
return forceUseStorage || !networkConnected;
},
};
const mutations = {
/**
* 设置网络是否连接的变量
* @param {*} state
* @param {boolean} networkConnected
*/
setNetworkConnected(state, networkConnected) {
state.networkConnected = networkConnected;
},
/**
* 设置系统信息的数据
* @param {object} state
* @param {object | null} data 获取到的数据
*/
setSystemInfo(state, data) {
state.systemInfo = data;
},
};
export default createStore({
state,
getters,
mutations,
modules: {user}
});

3
store/messages/getters.js

@ -1,3 +0,0 @@
const getters = {};
export default getters;

4
store/messages/index.js

@ -1,4 +0,0 @@
import state from './state';
import mutations from './mutations';
export default { namespaced: true, state, mutations };

85
store/messages/mutations.js

@ -1,85 +0,0 @@
import storage from '@/utils/storage';
const { setStorageSync, getStorageSync, removeStorageSync } = storage;
const mutations = {
/**
* 初始化消息栈
* @param {object} state
* @param {string} type
* type:
* syncMessages 同步消息栈
* faultMessages 故障消息 未处理消息栈
* faults 所有的故障消息栈
*/
messagesInit(state, type) {
const messages = getStorageSync(type) ? JSON.parse(getStorageSync(type)) : [];
state[type] = messages;
},
/**
* 将新 消息添加到 消息栈 最前边
* @param { object } state
* @param { object } data
* data: message, type
* message 消息对象
* type:
* syncMessages 同步消息栈
* faultMessages 故障消息 未处理消息栈
* faults 所有的故障消息栈
* game 游戏的消息
*
* cache: boolean true 本地存储 false 不存储
*/
messagesAdd(state, data) {
const messages = state[data.type];
if (messages.length > 0) {
const result = messages.find(msg => msg.id === data.message.id);
if (result) return;
}
messages.unshift(data.message);
// eslint-disable-next-line no-param-reassign
state[data.type] = messages;
if (data.cache) {
setStorageSync(data.type, JSON.stringify(messages));
}
},
/**
* 通过消息id移除指定 同步 消息
* @param { object } state
* @param { object } data
* data: messageId, type
* messageId: 要移除的消息的messageId
* type:
* syncMessages 同步消息栈
* faultMessages 故障消息 未处理消息栈
* faults 所有的故障消息栈
* cache: boolean true 本地存储 false 不存储
*/
messagesRemoveById(state, data) {
const messages = state[data.type];
const index = messages.findIndex(msg => msg.id === data.messageId);
if (index < 0) return;
messages.splice(index, 1);
// eslint-disable-next-line no-param-reassign
state[data.type] = messages;
if (data.cache) {
setStorageSync(data.type, JSON.stringify(messages));
}
},
/**
* 清除指定type的消息
* @param {any} state
* @param {object} data
* data: type, cache
*/
messagesClear(state, data) {
state[data.type] = [];
if (data.cache) {
removeStorageSync(data.type);
}
},
};
export default mutations;

8
store/messages/state.js

@ -1,8 +0,0 @@
const state = {
syncMessages: [], // 同步消息
faultMessages: [], // 新收到的未处理的 故障消息
faults: [], // 所有的故障消息
game: [], // 游戏的消息
};
export default state;

3
store/project/actions.js

@ -1,3 +0,0 @@
const actions = {};
export default actions;

12
store/project/getters.js

@ -1,12 +0,0 @@
const getters = {
/**
* 当前项目的id
* @param {object} project
*/
projectId({ project }) {
uni.$t.storage.setStorageSync('projectId', project.id);
return project.id;
},
};
export default getters;

12
store/project/index.js

@ -1,12 +0,0 @@
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

43
store/project/mutations.js

@ -1,43 +0,0 @@
const mutations = {
/**
* 设置state projects书籍
* @param {object} state
* @param {array} projects 项目列表
*/
setProjects(state, projects) {
if (!projects || !projects.length) {
state.projects = [];
} else {
state.projects = [...projects];
}
},
/**
* 设置当前项目信息
* @param { object } state
* @param { object } data
*/
setProject(state, data) {
state.project = data || { name: '加载中...' };
},
/**
* 设置当前项目名称
* @param { object } state
* @param { string } data
*/
setProjectName(state, data) {
state.project.name = data;
},
/**
* 设置小红点
* @param { object } state
* @param { string } data
*/
setDotList(state, data) {
state.dotList = data;
},
};
export default mutations;

8
store/project/state.js

@ -1,8 +0,0 @@
/* eslint-disable */
const state = {
project: { name: '加载中...' }, // 当前项目信息
projects: [], // 项目列表
dotList: [], // 小红点
};
export default state;

17
store/role/actions.js

@ -1,17 +0,0 @@
const actions = {
/**
* 根据项目id查找所有成员信息
* @param {*} commit
* @param {object} params
*/
async getAllMembers({ commit }, params) {
try {
const data = await uni.$u.api.queryChecker(params);
commit('setMembers', data);
} catch (error) {
uni.$t.ui.showToast(error.msg || '成员查询失败');
}
},
};
export default actions;

13
store/role/getters.js

@ -1,13 +0,0 @@
const getters = {
// 是不是负责人
isMine({ roleId, invisibleRoles, visibleRoles }) {
if (!visibleRoles || !visibleRoles.length) return false;
const visible = visibleRoles.find(visible => visible.id === roleId);
if (visible) return visible.mine;
const invisible = invisibleRoles.find(invisible => invisible.id === roleId);
if (invisible) return visible.mine;
return false;
},
};
export default getters;

12
store/role/index.js

@ -1,12 +0,0 @@
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

39
store/role/mutations.js

@ -1,39 +0,0 @@
const mutations = {
/**
* 设置不展示的角色信息
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setInvisibleRoles(state, data) {
state.invisibleRoles = data || [];
},
/**
* 设置展示的角色信息
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setVisibleRoles(state, data) {
state.visibleRoles = data || [];
},
/**
* 设置当前角色信息
* @param {Object} state
* @param {string} roleId 当前正在展示的角色的id
*/
setRoleId(state, roleId) {
state.roleId = roleId;
},
/**
* 设置项目下所有成员信息
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setMembers(state, data) {
state.members = data || [];
},
};
export default mutations;

8
store/role/state.js

@ -1,8 +0,0 @@
const state = {
invisibleRoles: [], // 不展示的角色信息
visibleRoles: [], // 展示的角色信息
roleId: '', // 当前展示查看的角色id
members: [], // 项目下所有成员
};
export default state;

154
store/socket/actions.js

@ -1,154 +0,0 @@
const WS_BASE_URL = process.env.VUE_APP_MSG_URL;
let prevTime = 0;
let socketMsgQueue = []; // socket消息队列
let sendHeartTimer = null;
const actions = {
// 初始化socket
initSocket({ commit, dispatch, state, rootState }) {
if (state.lockSocket) return;
const { token } = rootState.user;
if (!token) return;
commit('setLockSocket', true);
commit('setSocket', uni.connectSocket({ url: WS_BASE_URL, complete: () => {} }));
dispatch('onSocketOpen');
dispatch('onSocketMessage');
dispatch('onSocketClose');
state.socket.onError(errMsg => console.error(errMsg));
commit('setLockSocket', false);
},
// 监听ws打开
onSocketOpen({ dispatch, commit, state }) {
// eslint-disable-next-line no-unused-vars
state.socket.onOpen(res => {
// console.log('ws open: ', res);
commit('setConnected', true);
prevTime = Date.now();
// this.auth();
dispatch('auth');
for (let i = 0; i < socketMsgQueue.length; i++) {
dispatch('sendSocketMessage', socketMsgQueue[i]);
}
socketMsgQueue = [];
});
},
// 监听收到的ws消息
onSocketMessage({ dispatch, state }) {
state.socket.onMessage(res => {
// console.log('收到消息:', res);
prevTime = Date.now();
if (!res || !res.data || !JSON.parse(res.data)) return;
const resData = JSON.parse(res.data);
const { messageSet, ackId } = resData;
// 处理消息体对象
messageSet.forEach(item => dispatch('handleMessagesData', item));
ackId && dispatch('sendSocketMessage', { type: 'Ack', data: { ackId } });
});
},
/**
* 处理收到的消息内容
* @param {object} item 单个消息体对象
*/
handleMessagesData({ dispatch, commit }, item) {
const data = JSON.parse(item.data);
switch (data.type) {
case 'Sync': // 开始某个节点
commit('messages/messagesAdd', { message: data, type: 'syncMessages' }, { root: true });
break;
case 'taskStatus': // 任务状态修改相关消息
commit('task/setTaskStatus', data.data, { root: true });
break;
case 'switchoverProject': // 打开新项目消息
commit('task/setNewProjectInfo', data.data, { root: true });
break;
// case 'Chrome': // !收到开始游戏的消息
// console.log('handleMessagesData', data);
// // @ts-ignore
// util.openGameApp({
// type: data.data.type,
// projectId: data.data.projectId,
// id: data.data.recordId,
// token: rootState.user.token,
// });
// break;
// case 'Deliver': // 交付物相关消息
// commit('messages/messagesAdd', { type: 'checkMessages', message: data }, { root: true });
// break;
case 'ChannelStatus':
dispatch('handleAuthMessage', data);
break;
// case 'switchoverProject': // 康复相关消息
// dispatch('home/getProjectById', data.data.projectId, { root: true });
// break;
// case 'startDrill': // 康复开始训练相关消息
// console.log('setStartDrillInfo', data.data);
// commit('home/setStartDrillMessages', data.data, { root: true });
// break;
default:
break;
}
},
// 发送消息
sendSocketMessage({ state }, data) {
if (state.connected) {
const msg = JSON.stringify({ toDomain: 'Server', data: JSON.stringify(data) });
state.socket.send({ data: msg });
} else {
socketMsgQueue.push(data);
}
},
// 监听关闭事件
onSocketClose({ dispatch, commit, state }) {
// console.log('onSocketClose');
state.socket.onClose(() => {
commit('setConnected', false);
if (sendHeartTimer) clearInterval(sendHeartTimer);
setTimeout(() => {
dispatch('initSocket');
}, 300);
});
},
// websocket发送channelId进行认证
auth({ dispatch, rootState }) {
const { token } = rootState.user;
if (!token) return;
const data = { type: 'Auth', data: { token } };
dispatch('sendSocketMessage', data);
},
// 心跳检测
sendHeart({ dispatch, state }) {
if (sendHeartTimer) clearInterval(sendHeartTimer);
sendHeartTimer = setInterval(() => {
if (Date.now() - prevTime >= 15000) {
dispatch('sendSocketMessage', { type: 'Ping' });
if (Date.now() - prevTime >= 20000) {
state.socket.close();
}
}
}, 5000);
},
/**
* 处理auth认证返回的ChannelStatus消息
* @param {object} data 消息内容对象
*/
handleAuthMessage({ commit, dispatch }, data) {
if (data.data.authed) {
dispatch('sendHeart');
} else {
uni.$u.toast('消息系统认证失败, 请退出重新登录');
uni.$t.removeStorageSync('anyringToken');
commit('setSocket', null);
}
},
};
export default actions;

5
store/socket/index.js

@ -1,5 +0,0 @@
import state from './state';
import mutations from './mutations';
import actions from './actions';
export default { namespaced: true, state, mutations, actions };

26
store/socket/mutations.js

@ -1,26 +0,0 @@
const mutations = {
// 设置socket实例
setSocket(state, socket) {
state.socket = socket;
},
/**
* 设置socket连接状态
* @param {Object} state
* @param {boolean} connected 是否连接 true -> 连接
*/
setConnected(state, connected) {
state.connected = connected;
},
/**
* 设置连接锁 正在连接中 锁上 避免多个连接同时发出
* @param {Object} state
* @param {boolean} lockSocket 是否正在连接的过程中
*/
setLockSocket(state, lockSocket) {
state.lockSocket = lockSocket;
},
};
export default mutations;

7
store/socket/state.js

@ -1,7 +0,0 @@
const state = {
socket: null, // websocket实例
connected: false, // 是否处于连接状态
lockSocket: false, // 是否正在连接状态
};
export default state;

33
store/task/actions.js

@ -1,33 +0,0 @@
const actions = {
/**
* 根据角色查找永久的日常任务
* @param {*} commit
* @param {string} roleId 角色id
*/
getPermanent({ commit }, param) {
uni.$t.$q.getPermanent(param, (err, data) => {
if (err) {
console.error('err: ', err);
} else {
commit('setPermanents', data);
}
});
},
/**
* 根据时间和角色查找日常任务
* @param {*} commit
* @param {object} param 请求参数 roleId, timeNode, timeUnit
*/
getGlobal({ commit }, param) {
uni.$t.$q.getGlobal(param, (err, data) => {
if (err) {
console.error('err: ', err);
} else {
commit('setDailyTasks', data);
}
});
},
};
export default actions;

23
store/task/getters.js

@ -1,23 +0,0 @@
const getters = {
// 所有的日常任务 永久 + 可变 日常任务
globals({ dailyTasks, permanents }) {
return [...permanents, ...dailyTasks];
},
unitConfig({ timeUnit }) {
const target = uni.$t.timeConfig.timeUnits.find(item => item.id === timeUnit);
return target;
},
// 计算任务开始时间的格式
startTimeFormat(state, { unitConfig }) {
return unitConfig.format || 'M月D日 HH:mm';
},
// 计算颗粒度 对应的 dayjs add 的单位
timeGranularity(state, { unitConfig }) {
return unitConfig.granularity;
},
};
export default getters;

12
store/task/index.js

@ -1,12 +0,0 @@
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

238
store/task/mutations.js

@ -1,238 +0,0 @@
const mutations = {
/**
* 记录时间轴向上滚动的距离
* @param { object } state
* @param { number } num
*/
setScrollTop(state, num) {
state.scrollTop = num;
},
/**
* 记录时间轴向上滚动的距离
* @param { object } state
* @param {string} taskId
*/
setScrollToTaskId(state, taskId) {
state.scrollToTaskId = taskId;
},
/**
* 设置日常任务当前是否应该处于收缩状态
* @param { object } state
* @param { boolean } data
*/
setShrink(state, data) {
state.isShrink = data;
},
/**
* 设置tip的值
* @param {object} state
* @param {object} data
*/
setTip(state, data) {
if (!data) return;
state.tip = { ...data };
},
/**
* 是否显示tips
* @param { object } state
* @param { boolean } show
*/
setTipShow(state, show) {
state.tip.show = show;
},
/**
* 是否显示tips
* @param { object } state
* @param { number } status
*/
setStatus(state, status) {
state.tip.status = status;
},
/**
* 设置时间基准点
* @param { object } state
* @param { number } data
*/
setTimeNode(state, data) {
state.timeNode = data;
},
/**
* 设置时间颗粒度
* @param { object } state
* @param { number } data
*/
setTimeUnit(state, data) {
state.timeUnit = data;
},
/**
* 设置向上查到的定期任务数据
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setUpTasks(state, data) {
if (!state.tasks.length) {
state.tasks = [...data]; // 原来没有数据
} else {
state.tasks = [...data, ...state.tasks];
let arr = [],
flag = false;
state.tasks.forEach(task => {
arr.forEach(item => {
if (task.id == item.id) {
flag = true;
}
});
if (!flag) {
arr.push(task);
}
});
state.tasks = [...arr];
// state.tasks = [...data.concat(state.tasks)];
}
},
/**
* 设置向下查到的定期任务数据
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setDownTasks(state, data) {
if (!state.tasks && !state.tasks.length) {
state.tasks = [...data];
} else {
state.tasks = [...state.tasks, ...data];
let arr = [],
flag = false;
state.tasks.forEach(task => {
arr.forEach(item => {
if (task.id == item.id) {
flag = true;
}
});
if (!flag) {
arr.push(task);
}
});
state.tasks = [...arr];
// state.tasks = [...state.tasks.concat(data)];
}
},
/**
* 添加任务后更新tasks
* @param {Object} state
* @param {Array} data 新添加的task
*/
updateTasks(state, data) {
state.tasks = [...data];
},
/**
* 设置添加任务的位置
* @param {*} state
* @param {*} data
*/
setAddPosition(state, data) {
console.log('data: ', data);
},
/**
* 设置日常任务数据
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setDailyTasks(state, data) {
state.dailyTasks = data || [];
},
/**
* 设置永久固定任务
* @param {object} state
* @param {array} tasks 服务端查询到的永久日常任务书籍
*/
setPermanents(state, tasks) {
state.permanents = tasks || [];
},
/**
* 设置时间轴是否继续向上查任务
* @param {Object} state
* @param {Boolean} show
*/
setTopEnd(state, show) {
state.topEnd = show;
},
/**
* 设置时间轴是否继续向下查任务
* @param {Object} state
* @param {Boolean} show
*/
setBottomEnd(state, show) {
state.bottomEnd = show;
},
// 清空标志位 如切换角色等使用
clearEndFlag(state) {
state.topEnd = false;
state.bottomEnd = false;
},
// 清空定期任务
clearTasks(state) {
state.tasks = [];
},
/**
* 收到消息设置任务状态
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setTaskStatus(state, data) {
const item = state.tasks.find(i => i.id === data.id);
item.process = data.taskStatus;
},
/**
* 收到打开新项目消息状态
* @param {Object} state
* @param {Array} data 服务端返回的模板数组
*/
setNewProjectInfo(state, data) {
state.newProjectInfo = data;
},
/**
* 设置骨架屏是否显示
* @param {Object} state
* @param {Boolean} show
*/
setShowSkeleton(state, show) {
state.showSkeleton = show;
},
/**
* 是否设置时间轴自动滚动的位置
* @param {Object} state
* @param {Boolean} show
*/
setShowScrollTo(state, show) {
state.showScrollTo = show;
},
};
export default mutations;

25
store/task/state.js

@ -1,25 +0,0 @@
const state = {
scrollTop: 0,
scrollToTaskId: '', // 时间轴自动滚动的位置
isShrink: false, // true: 收起, false:展开
tip: {
taskId: '', // 当前正在修改状态的任务的id
show: false,
status: 0, // 所点击任务的当前状态码
text: '',
left: 0, // 鼠标点击位置距离左边的距离
top: 0, // 鼠标点击位置距离上边的距离
},
timeNode: new Date().getTime(), // 时间基准点
timeUnit: 4, // 时间颗粒度
topEnd: false, // 时间轴向上查任务到顶了
bottomEnd: false, // 时间轴向下查任务到底了
permanents: [], // 永久日常任务
dailyTasks: [], // 日常任务
tasks: [], // 所有的定期任务
showSkeleton: false, // 定期任务骨架屏
newProjectInfo: {},
showScrollTo: false, // 是否可以设置时间轴自动滚动的位置
};
export default state;

39
store/user/actions.js

@ -1,19 +1,22 @@
const actions = {
/**
* 通过userId获取token
* @param {any} commit
* @param {string} userId 用户id
*/
async getToken({ commit }, userId) {
try {
const data = await uni.$u.api.getToken(userId);
commit('setToken', data.token);
commit('setUser', data);
return data;
} catch (error) {
uni.$t.ui.showToast(error.msg || '获取个人信息失败');
}
},
};
import util from '@/common/js/util.js';
import { getToken } from '@/apis/tall.js';
const actions = {
/**
* 通过userId获取token
* @param {any} commit
* @param {string} userId 用户id
*/
async getToken({ commit }, userId) {
try {
const data = await getToken(userId);
commit('setToken', data.token);
commit('setUser', data);
return data;
} catch (error) {
util.showToast(error.msg || '获取个人信息失败');
}
},
};
export default actions;

28
store/user/getters.js

@ -1,14 +1,14 @@
const getters = {
// 获取用户的id
userId({ user }) {
try {
if (!user) return '';
return user.id;
} catch (error) {
console.warn("user's getters 获取userId失败", error);
return '';
}
},
};
export default getters;
const getters = {
// 获取用户的id
userId({ user }) {
try {
if (!user) return '';
return user.id;
} catch (error) {
console.warn("user's getters 获取userId失败", error);
return '';
}
},
};
export default getters;

22
store/user/index.js

@ -1,12 +1,12 @@
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

48
store/user/mutations.js

@ -1,24 +1,24 @@
const mutations = {
/**
* 设置存储token
* @param {object} state
* @param {string} token
*/
setToken(state, token) {
state.token = token || '';
uni.$t.storage.setStorageSync(uni.$t.app.tokenKey, token || '');
},
/**
* 设置user数据
* @param {object} state
* @param {object} user
*/
setUser(state, user) {
if (!user) return;
state.user = { ...user };
uni.$t.storage.setStorageSync('user', JSON.stringify(user));
},
};
export default mutations;
const mutations = {
/**
* 设置存储token
* @param {object} state
* @param {string} token
*/
setToken(state, token) {
state.token = token || '';
uni.$t.storage.setStorageSync(uni.$t.app.tokenKey, token || '');
},
/**
* 设置user数据
* @param {object} state
* @param {object} user
*/
setUser(state, user) {
if (!user) return;
state.user = { ...user };
uni.$t.storage.setStorageSync('user', JSON.stringify(user));
},
};
export default mutations;

10
store/user/state.js

@ -1,5 +1,5 @@
const state = {
token: '',
user: null,
};
export default state;
const state = {
token: '',
user: null,
};
export default state;

62
utils/cache.js

@ -0,0 +1,62 @@
export const filter = {
/**
* 过滤获取到的数据 根据开始截止时间
* @param {object} data 缓存拿到的数据
* @param {number} start ms
* @param {number} end ms
* @returns
*/
projects(data, start, end) {
if (!data || !data.length) return [];
return data.filter(item => start <= +item.endTime && end >= +item.startTime);
},
};
export default {
/**
* 项目列表某天的 获取
* @param {number} startTime
* @param {number} endTime
* @returns
*/
async getProjectsByDay(startTime, endTime) {
try {
const data = await uni.$t.storage.getStorage('projects');
return filter.projects(JSON.parse(data), startTime, endTime);
} catch (error) {
return [];
}
},
/**
* 项目列表
* @param {array} data
*/
putProjects(data) {
try {
if (!data || !data.length) return; // 服务端没数据不做操作
let value = uni.$t.storage.getStorageSync('projects');
let locals = value ? JSON.parse(value) : [];
if (!locals || !locals.length) {
// 本地没数据
locals = data || [];
} else {
// 本地有数据
data.forEach(item => {
let localData = locals.find(local => item.id === local.id);
if (localData) {
// 有相同数据 就用新的data里的数据
localData = item;
} else {
// 没有就直接存本地
locals.push(item);
}
});
}
uni.$t.storage.setStorage('projects', locals);
} catch (error) {
console.error('error: ', error);
uni.$t.storage.setStorage('projects', []);
}
},
};

190
utils/cacheAndRequest.js

@ -0,0 +1,190 @@
import store from '@/store/index';
/**
* 等待token执行api
* 没有token 就延时执行自己 直到有了token在请求
* @param {function} requestFn 执行请求的函数
*/
export const waitTokenRequest = requestFn => {
if (!requestFn || typeof requestFn !== 'function') throw new Error(`requestFn must be a function`);
if (uni.$t.storage.getStorageSync(uni.$t.app.tokenKey)) {
requestFn();
} else {
setTimeout(() => waitTokenRequest(requestFn), 10);
}
};
export default {
/**
* 获取项目列表
* @param {number} startTime 起始时间
* @param {number} endTime 截止时间
*/
getProjects(startTime, endTime, fn) {
let remote = false;
if (store.getters.useStorage) {
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getProjectsByDay(startTime, endTime)
.then(data => {
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
}
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.getProjects(startTime, endTime)
.then(data => {
remote = true;
fn(null, data);
// 存api到cache里
uni.$t.cache.putProjects(data);
})
.catch(err => fn(err));
});
},
/**
* 通过项目id获取角色信息
* @param {object} params 提交的参数
*/
findShowRole(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getShowRole(params.projectId)
.then(data => {
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.findShowRole(params)
.then(data => {
remote = true;
fn(null, data);
// 存api到cache里
uni.$t.cache.putShowRole(params.projectId, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间基准点和角色查找定期任务
* @param {object} params 提交的参数
*/
getRegularTask(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getStorageRegularTask(params)
.then(data => {
console.log('cache data: ', data);
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.getRegularTask(params)
.then(data => {
console.log('api data: ', uni.$u.deepClone(data));
remote = true;
fn(null, uni.$u.deepClone(data));
// 存api到cache里
uni.$t.cache.putStorageRegularTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据角色查找永久的日常任务
* @param {object} params 提交的参数
*/
getPermanent(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getStoragePermanent(params)
.then(data => {
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.getPermanent(params)
.then(data => {
remote = true;
fn(null, data);
// 存api到cache里
uni.$t.cache.putStoragePermanent(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间和角色查找日常任务
* @param {object} params 提交的参数
*/
getGlobal(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getDailyTask(params)
.then(data => {
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.getGlobal(params)
.then(data => {
remote = true;
fn(null, data);
// 存api到cache里
uni.$t.cache.putDailyTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 获取插件信息
* @param {object} params 提交的参数
*/
getOtherPlugin(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$t.cache
.getPlugin(params.pluginId)
.then(data => {
!remote && fn(null, data);
})
.catch(err => !remote && fn(err));
waitTokenRequest(() => {
// 拿到api数据后 再用api的数据
uni.$u.api
.getOtherPlugin(params)
.then(data => {
remote = true;
fn(null, data);
// 存api到cache里
uni.$t.cache.putPlugin(params.pluginId, data);
})
.catch(err => fn(err));
});
},
};

118
utils/request.js

@ -0,0 +1,118 @@
const install = (Vue, vm) => {
Vue.prototype.$u.http.setConfig({
baseUrl: '',
showLoading: true, // 是否显示请求中的loading
loadingText: '玩命加载中...',
loadingTime: 800,
loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
// 配置请求头信息
header: {
'content-type': 'application/json;charset=UTF-8'
},
});
// 请求拦截部分,如配置,每次请求前都会执行
Vue.prototype.$u.http.interceptor.request = config => {
const token = vm.$store.state.user.token || uni.$t.storage.getStorageSync(uni.$t.app.tokenKey);
if (token) {
config.header.Authorization = `Bearer ${token}`;
}
return config;
};
// 响应拦截,如配置,每次请求结束都会执行本方法
Vue.prototype.$u.http.interceptor.response = res => {
if (res.code === 200) {
// res为服务端返回值,可能有code,result等字段
// 这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到
// 如果配置了originalData为true,请留意这里的返回值
return res.data;
} else if (res.code === 401) {
// 假设201为token失效,这里跳转登录
vm.$u.toast('验证失败,请重新登录');
setTimeout(() => {
// 此为uView的方法,详见路由相关文档
vm.$u.route('/pages/user/login');
}, 1500);
return false;
} else {
// 如果返回false,则会调用Promise的reject回调,
// 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
return false;
}
};
Vue.prototype.$u.post = (url, param = {}, header = {}) => {
return Vue.prototype.$u.http.request({
url,
method: 'POST',
header,
data: {
param
},
});
};
};
export default {
install
};
// export function setupHttp(app) {
// app.config.globalProperties.$u.http.setConfig({
// baseUrl: '',
// showLoading: true, // 是否显示请求中的loading
// loadingText: '玩命加载中...',
// loadingTime: 800,
// loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
// // 配置请求头信息
// header: {
// 'content-type': 'application/json;charset=UTF-8'
// },
// });
// // 请求拦截部分,如配置,每次请求前都会执行
// app.config.globalProperties.$u.http.interceptor.request = config => {
// const token = vm.$store.state.user.token || uni.$t.storage.getStorageSync(uni.$t.app.tokenKey);
// if (token) {
// config.header.Authorization = `Bearer ${token}`;
// }
// return config;
// };
// // 响应拦截,如配置,每次请求结束都会执行本方法
// app.config.globalProperties.$u.http.interceptor.response = res => {
// if (res.code === 200) {
// // res为服务端返回值,可能有code,result等字段
// // 这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到
// // 如果配置了originalData为true,请留意这里的返回值
// return res.data;
// } else if (res.code === 401) {
// // 假设201为token失效,这里跳转登录
// vm.$u.toast('验证失败,请重新登录');
// setTimeout(() => {
// // 此为uView的方法,详见路由相关文档
// vm.$u.route('/pages/user/login');
// }, 1500);
// return false;
// } else {
// // 如果返回false,则会调用Promise的reject回调,
// // 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
// return false;
// }
// };
// app.config.globalProperties.$u.post = (url, param = {}, header = {}) => {
// return app.config.globalProperties.$u.http.request({
// url,
// method: 'POST',
// header,
// data: {
// param
// },
// });
// };
// }

112
utils/storage.js

@ -0,0 +1,112 @@
export default {
/**
* 设置本地存储 同步
* @param {string} key
* @param {*} data
*/
setStorageSync(key, data) {
const value = typeof data === 'string' ? data : JSON.stringify(data);
uni.setStorageSync(key, value);
},
/**
* 获取本地存储的信息 根据key
* @param {string} key
* @return {string}
*/
getStorageSync(key) {
return uni.getStorageSync(key);
},
/**
* 根据key移除某条数据 同步
* @param {string} key
*/
removeStorageSync(key) {
uni.removeStorageSync(key);
},
/**
* 清楚全部数据 同步
*/
clearStorageSync() {
uni.clearStorageSync();
},
/**
* 设置本地存储 异步
* @param {string} key
* @param {*} data
*/
setStorage(key, data) {
uni.$t.storage.checkCapacity();
return new Promise((resolve, reject) => {
const value = typeof data === 'string' ? data : JSON.stringify(data);
uni.setStorage({
key,
data: value,
success() {
resolve(`数据${key}存储成功`);
},
fail() {
reject(`数据${key}存储失败`);
},
});
});
},
/**
* 获取本地存储的信息 根据key 异步
* @param {string} key
* @return {string}
*/
getStorage(key) {
return new Promise((resolve, reject) => {
uni.getStorage({
key,
success(res) {
resolve(res.data);
},
fail(error) {
reject(`数据${key}获取失败, error: ${error.errMsg}`);
},
});
});
},
/**
* 根据key移除某条数据 异步
* @param {string} key
*/
removeStorage(key) {
return new Promise((resolve, reject) => {
uni.removeStorage({
key,
success(res) {
resolve(res);
},
fail(error) {
reject(`数据${key}删除失败, error: ${error}`);
},
});
});
},
/**
* 清楚全部数据 异步
*/
clearStorage() {
uni.clearStorage();
},
// 检测local Storage容量 超出容量清空数据缓存
checkCapacity() {
/* #ifdef H5 */
const capacity = JSON.stringify(localStorage).length;
let max = 1024 * 1024 * 4;
if (capacity >= max) {
uni.$t.storage.clearStorage();
}
/* #endif */
},
};

34
utils/tall.js

@ -0,0 +1,34 @@
import app from '@/config/app.js';
import cache from '@/utils/cache.js';
import cacheAndRequest from '@/utils/cacheAndRequest.js';
import storage from '@/utils/storage.js';
import time from '@/utils/time.js';
import ui from '@/utils/ui.js';
import upload from '@/utils/upload.js';
import user from '@/config/user.js';
import zIndex from '@/config/zIndex.js';
const gateway = process.env.VUE_APP_API_URL;
const $t = {
zIndex, // 定位元素层级
app, // app级别的相关配置
storage, // 本地存储storage封装
time, // 时间处理
ui, // ui界面提示相关
chooseAndUpload: upload.chooseAndUpload, // 选择并上传单个文件相关的封装
domain: `${gateway}/defaultwbs`,
cache, // 本地存储相关
$q: cacheAndRequest,
user, // 用户相关配置
};
uni.$t = $t;
const install = Vue => {
Vue.prototype.$t = $t;
};
export default {
install
};

366
utils/time.js

@ -0,0 +1,366 @@
import dayjs from 'dayjs';
const advancedFormat = require('dayjs/plugin/advancedFormat');
const weekOfYear = require('dayjs/plugin/weekOfYear');
const duration = require('dayjs/plugin/duration');
dayjs.extend(advancedFormat);
dayjs.extend(weekOfYear);
dayjs.extend(duration);
/**
* 格式化数字
* @param {*} n
*/
const formatNumber = n => {
const str = n.toString();
return str[1] ? str : `0${str}`;
};
/**
* 格式化时间
* @param {number} beginTime
*/
const formatTime = beginTime => {
const date = new Date(beginTime);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const minute = date.getMinutes();
const second = date.getSeconds();
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`;
};
/**
* 添加一定时间的时长
* @param {number | date} time
* @param {number} num
* @param {string} cycle
*/
const add = (time, num, cycle) => {
const str = dayjs(time).add(num, cycle);
return str;
};
/**
* 时间转换 08:00 转换成8小时0分钟
* @param {string} time
* @returns {{hours: number, minutes: number}}
*/
const convertTime = time => {
const arr = time.split(':');
return {
hours: parseInt(arr[0], 10),
minutes: parseInt(arr[1], 10),
};
};
/**
* 将秒 ->
* @param {number} seconds
*/
const secondToMinute = seconds => {
const minute = formatNumber(Math.floor(seconds / 60));
const second = formatNumber(parseInt(seconds % 60, 10));
return {
minute,
second,
};
};
/**
* 将时间戳 -> :
* @param {Number} timestamp 时间戳
* @return date:2018/10/09 time: 12:59
*/
const setTimestampToStr = timestamp => {
const timeObj = new Date(timestamp);
const year = timeObj.getFullYear();
const month = formatNumber(timeObj.getMonth() + 1);
const day = formatNumber(timeObj.getDate());
const hour = formatNumber(timeObj.getHours());
const minute = formatNumber(timeObj.getMinutes());
const date = `${year}-${month}-${day}`;
const time = `${hour}:${minute}`;
return {
date,
time,
};
};
/**
* 检测时间(ms)是不是今天
* @param {Number} time 时间戳
*/
const validateTimeIsToday = time => {
const timeDate = new Date(time);
const date = new Date();
return timeDate.getFullYear() === date.getFullYear() && timeDate.getMonth() === date.getMonth() && timeDate.getDate() === date.getDate();
};
/**
* 检测两个日期是否相同
* @param {number | date} time
* @param {number | date} value
* @param {string} cycle 传入 day 将会比较 day month和 year
*/
const isSame = (time, value, cycle) => {
const str = dayjs(time).isSame(value, cycle);
return str;
};
/**
* 格式化开始时间
* @param {Number} timestamp 时间戳
* @return
* 如果是今天 -> :
* 如果不是今年 -> // :
* 否则 ** :
*/
const formatBeginTime = timestamp => {
const timeObj = new Date(timestamp);
const year = timeObj.getFullYear();
const month = formatNumber(timeObj.getMonth() + 1);
const day = formatNumber(timeObj.getDate());
const hour = formatNumber(timeObj.getHours());
const minute = formatNumber(timeObj.getMinutes());
const date = `${year}/${month}/${day}`;
const time = `${hour}:${minute}`;
const currentYear = new Date().getFullYear();
if (validateTimeIsToday(timestamp)) {
// 今天
return `今天 ${time}`;
} else if (currentYear !== year) {
// 不是今年
return `${date} ${time}`;
} else {
return `${month}${day}${time}`;
}
};
/**
* 格式化时长
* @param {Number} duration 时长
* 超过24小时 24 * 60 * 60 * 1000 ms 转换成天数 + 小时 + 分钟
* 小于1分钟 60 * 1000 ms 转换成秒钟
* 其余的显示分钟
* 超过2小时 2 * 60 * 60 * 1000 ms 转换成小时 + 分钟数
*/
const formatDuration = duration => {
const minuteTime = 60 * 1000;
const hourTime = 60 * minuteTime;
const dayTime = 24 * hourTime;
const days = Math.floor(duration / dayTime);
const hours = Math.floor((duration % dayTime) / hourTime);
const minutes = Math.floor((duration % hourTime) / minuteTime);
if (duration <= 60 * 1000) {
// 小于1分钟 返回几秒
return `${Math.floor(duration / 1000)}`;
} else if (duration > dayTime) {
// 大于1天
if (minutes === 0) {
if (hours === 0) {
// 分钟数是0 和 小时数是0 返回 几天
return `${days}`;
} else {
// 分钟是0 小时不是0 返回 几天几小时
return `${days}${hours}小时`;
}
} else {
// 分钟不是0 返回几天几时几分
return `${days}${hours}${minutes}`;
}
} else if (duration > 2 * hourTime) {
// 大于2h
if (minutes === 0) {
// 分钟是0 返回几小时
return `${hours}小时`;
} else {
// 分钟不是0 返回几小时几分钟
return `${hours}小时${minutes}分钟`;
}
} else {
// 其余情况 返回 几分钟
return `${parseInt(duration / minuteTime)}分钟`;
}
};
/**
* 格式化时长 转换成对象格式
* @param {Number} duration 时长
* 超过24小时 24 * 60 * 60 * 1000 ms 转换成{days, hours, minutes, seconds: 0}
* 小于1分钟 60 * 1000 ms 转换成秒钟 { days: 0, hours: 0, minutes: 0, seconds }
* 其余的显示分钟 { days: 0, hours: 0, minutes, seconds: 0 }
* 超过2小时 2 * 60 * 60 * 1000 ms 转换成{ days: 0, hours, minutes, seconds: 0 }
*/
const formatDurationToObject = duration => {
const minuteTime = 60 * 1000;
const hourTime = 60 * minuteTime;
const dayTime = 24 * hourTime;
const days = Math.floor(duration / dayTime);
const hours = Math.floor((duration % dayTime) / hourTime);
const minutes = Math.floor((duration % hourTime) / minuteTime);
const result = {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
};
if (duration <= 60 * 1000) {
// 小于1分钟 返回几秒
result.seconds = Math.floor(duration / 1000);
} else if (duration > dayTime) {
// 大于1天
if (minutes === 0) {
if (hours === 0) {
// 分钟数是0 和 小时数是0 返回 几天
result.days = days;
} else {
// 分钟是0 小时不是0 返回 几天几小时
result.days = days;
result.hours = hours;
}
} else {
// 分钟不是0 返回几天几时几分
result.days = days;
result.hours = hours;
result.minutes = minutes;
}
} else if (duration > 2 * hourTime) {
// 大于2h
if (minutes === 0) {
// 分钟是0 返回几小时
result.hours = hours;
} else {
// 分钟不是0 返回几小时几分钟
result.hours = hours;
result.minutes = minutes;
}
} else {
// 其余情况 返回 几分钟
result.minutes = minutes;
}
return result;
};
/**
* 将对象格式的时间转换成时间戳
* @param {obj} 对象格式的时间 days, hours, minutes, seconds
* @return 时长的ms
*/
const formatObjectTimeToMs = (days = 0, hours = 0, minutes = 0, seconds = 0) => {
return days * 24 * 60 * 60 * 1000 + hours * 60 * 60 * 1000 + minutes * 60 * 1000 + seconds * 1000;
};
/**
* 计算过滤 周期
* @param {string} time 周期字符串
* @return {string} cycle 周期英文字符串
*/
const computeCycle = time => {
// 加载下一个周期的任务
let cycle = 'day';
switch (time) {
case '天':
cycle = 'day';
break;
case '周':
cycle = 'week';
break;
case '月':
cycle = 'month';
break;
default:
cycle = '日程';
break;
}
return cycle;
};
/**
* 将时间按周期语义化
* @param {string} cycle 周期
* @param {number|string} time 时间
*/
const formatStartTimeToCycleTime = (cycle, time) => {
let result = '';
const _time = dayjs(+time);
switch (cycle) {
case '天':
result = _time.format('YYYY年M月D日');
break;
case '周':
result = _time.format('YYYY年w周');
break;
case '月':
result = _time.format('YYYY年M月');
break;
case '日程':
result = _time.format('YYYY年M月D日 HH:mm');
break;
default:
result = _time.format('YYYY年M月D日');
break;
}
return result;
};
/**
* 计算进行中状态剩余时间 显示数字
* @param {number} leftTime 剩余时间ms
* @returns { num: 显示的数字, time: 演示器演示时长 }
*/
const computeDurationText = leftTime => {
try {
if (leftTime < 0) return { num: 0, time: null };
const { years, months, days, hours, minutes, seconds, milliseconds } = dayjs.duration(leftTime).$d;
let num = 0;
let time = 1000;
if (years > 0) {
num = years;
time = 60 * 60 * 1000; // 按小时
} else if (months > 0) {
num = months;
time = 60 * 60 * 1000; // 按小时
} else if (days > 0) {
num = days;
time = 60 * 60 * 1000; // 按小时
} else if (hours > 0) {
num = hours;
} else if (minutes > 0) {
num = minutes;
} else if (seconds > 0) {
num = seconds;
} else if (milliseconds > 0) {
num = milliseconds;
time = 16;
} else {
time = null;
}
return { num, time };
} catch (error) {
console.log('🚀 ~ file: time.js ~ line 335 ~ computeDurationText ~ error', error);
return { num: 0, time: null };
}
};
export default {
formatNumber,
formatTime,
add,
convertTime,
secondToMinute,
setTimestampToStr,
isSame,
formatBeginTime,
formatDuration,
formatDurationToObject,
formatObjectTimeToMs,
computeCycle,
formatStartTimeToCycleTime,
computeDurationText,
};

59
utils/ui.js

@ -0,0 +1,59 @@
export default {
/**
* 显示toast
* @param {string} title 提示内容
* @param {number} duration 显示时间 默认2000
*/
showToast(title, duration = 2000) {
return uni.showToast({
title,
icon: 'none',
duration,
mask: true,
});
},
// 隐藏toast
hideToast() {
return uni.hideToast();
},
/**
* 显示加载雪花
* @param {string} title
*/
showLoading(title = '玩命加载中...') {
return uni.showLoading({
title,
mask: true,
});
},
// 隐藏loading
hideLoading() {
return uni.hideLoading();
},
/**
* 显示modal弹出框
* @param {string} title 标题
* @param {string} content 内容
* @param {boolean} showCancel 是否显示取消按钮 默认true
*/
showModal(title, content, showCancel = true) {
return new Promise(function(resolve, reject) {
uni.showModal({
title,
content,
showCancel,
success: ({
confirm,
cancel
}) => {
confirm && resolve();
cancel && reject();
},
});
});
},
};

110
utils/upload.js

@ -0,0 +1,110 @@
// H5选择文件
const chooseFileH5 = (extension = ['.xls', '.xlsx']) => {
return new Promise((resolve, reject) => {
uni.chooseFile({
count: 1, //默认100
extension,
success(res) {
resolve(res.tempFilePaths[0]);
},
fail() {
reject('上传失败');
},
});
});
};
// 微信选择文件 从客户端会话选择文件。
const chooseFileWeixin = (extension = ['.xls', '.xlsx']) => {
return new Promise((resolve, reject) => {
wx.chooseMessageFile({
count: 1,
extension,
type: 'file',
success(res) {
resolve(res.tempFiles[0].path);
},
fail() {
reject('上传失败');
},
});
});
};
// 选择文件
const chooseFile = (extension = ['.xls', '.xlsx']) => {
let fn = null;
/* #ifdef H5 */
fn = chooseFileH5(extension);
/* #endif */
/* #ifdef MP-WEIXIN */
fn = chooseFileWeixin(extension);
/* #endif */
return fn;
};
export default {
/**
* 上传单个文件
* @param {string} url 服务器地址
* @param {object} formData 上传的其他字段
* @param {array} extension 上传文件类型 扩展名数组
* @param {string} name
* @returns
*/
chooseAndUpload(url, formData = {}, extension = ['.xls', '.xlsx'], name = 'param') {
uni.hideLoading();
clearTimeout(timer);
let timer = null;
return new Promise((resolve, reject) => {
const token = uni.$t.storage.getStorageSync(uni.$t.app.tokenKey);
if (!token) {
return reject('用户未登录,请登录后重试');
}
chooseFile(extension)
.then(filePath => {
console.log('filePath: ', filePath);
if (!timer) {
timer = setTimeout(() => {
uni.$t.ui.showLoading('正在上传...');
timer = null;
}, 800);
}
// 开始上传
uni.uploadFile({
url,
filePath,
name,
formData,
header: { Authorization: `Bearer ${token}` },
success: ({ data, statusCode }) => {
clearTimeout(timer);
uni.hideLoading();
if (statusCode === 200 && data) {
const { code, msg } = JSON.parse(data);
if (code !== 200) {
reject(msg);
} else {
resolve(JSON.parse(data).data);
}
} else {
reject('上传失败');
}
},
fail: error => {
clearTimeout(timer);
uni.hideLoading();
reject(error);
},
});
})
.catch(error => {
clearTimeout(timer);
uni.hideLoading();
reject(error);
});
});
},
};
Loading…
Cancel
Save