Browse Source

feat: 表单验证

feat
xuesinan 4 years ago
parent
commit
5f64204e03
  1. 1
      CHANGELOG.md
  2. 20
      common/styles/tailwind.scss
  3. 98
      components/Plugin/Plugin.vue
  4. 1
      components/Roles/Roles.vue
  5. 8
      components/TimeLine/TimeLine.vue
  6. 23
      components/TimeLine/component/TimeBox.vue
  7. 9
      components/TimeLine/component/TimeStatus.vue
  8. 2
      config/task.js
  9. 159
      hooks/project/useGetTasks.js
  10. 449
      hooks/project/useInit - 副本.js
  11. 16
      hooks/project/useInit.js
  12. 3
      main.js
  13. 434
      pages/project/project A.vue
  14. 18
      pages/project/project.vue
  15. 366
      utils/cacheAndRequest.js
  16. 7
      utils/task.js
  17. 47
      utils/time.js

1
CHANGELOG.md

@ -3,6 +3,7 @@
### 🌟 新功能
范围|描述|commitId
--|--|--
- | 表单验证 | [8f3bc1e](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/8f3bc1e)
- | 更新代码 | [392c8cc](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/392c8cc)
- | 日历页首页 | [561c8e6](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/561c8e6)
- | 日历页添加 | [1b46a91](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/1b46a91)

20
common/styles/tailwind.scss

@ -1,5 +1,5 @@
.container {
width: 100%;
width: 100%;
}
.fixed {
@ -2207,6 +2207,15 @@
box-sizing: content-box;
}
.border-l-2 {
border-left-width: 2px;
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgba(209, 213, 219, var(--tw-border-opacity));
}
.block {
display: block;
}
@ -4310,6 +4319,11 @@
.opacity-100 {
opacity: 1;
}
.h-3 {
height: 0.75rem;
}
.h-full {
height: 100%;
}
@ -4317,6 +4331,10 @@
--tw-bg-opacity: 1;
background-color: rgba(249, 250, 251, var(--tw-bg-opacity));
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgba(243, 244, 246, var(--tw-bg-opacity));
}
.w-12 {
width: 3rem;
}

98
components/Plugin/Plugin.vue

@ -1,6 +1,7 @@
<template>
<view class="u-font-14" style="height: 100%">
<view v-if="data.pluginContent" @click="setStorage">
插件面板
<!-- <view v-if="data.pluginContent" @click="setStorage">
<view
:data-did="task.detailId"
:data-param="param"
@ -17,9 +18,9 @@
style="height: 100%"
v-html="data.pluginContent"
></view>
</view>
</view> -->
<view v-else @click="setStorage">
<!-- <view v-else @click="setStorage"> -->
<!-- <plugin-default /> -->
<!-- <component :task="task" :is="pluginComponent"></component> -->
<!-- <p-task-title :task="task" v-if="pluginId === '1'" />
@ -37,7 +38,7 @@
<p-manage-task :task="task" v-if="pluginId === '12'" />
<p-wbs-import :task="task" v-if="pluginId === '13' || pluginId === '14'" />
<p-deliver-check :task="task" v-if="pluginId === '15'" /> -->
</view>
<!-- </view> -->
</view>
</template>
@ -53,14 +54,14 @@ const props = defineProps({
param: { type: String, default: '' },
});
const data = reactive({ pluginContent: null });
// const data = reactive({ pluginContent: null });
const store = useStore();
const roleId = computed(() => store.state.role.roleId);
const token = computed(() => store.state.user.token);
const userId = computed(() => store.getters['user/userId']);
// const token = computed(() => store.state.user.token);
// const userId = computed(() => store.getters['user/userId']);
const projectId = computed(() => store.getters['project/projectId']);
const isMine = computed(() => store.getters['role/isMine']);
// const isMine = computed(() => store.getters['role/isMine']);
//
// pluginComponent() {
@ -70,48 +71,48 @@ const isMine = computed(() => store.getters['role/isMine']);
// },
// script dom
function handleDom(js) {
const domList = Array.from(document.getElementsByTagName('script'));
const index = domList.findIndex(item => item.id === `p${props.pluginTaskId}`);
if (index >= 0) {
document.body.removeChild(document.getElementById(`p${props.pluginTaskId}`));
}
const scriptDom = document.createElement('script');
scriptDom.id = `p${props.pluginTaskId}`;
scriptDom.setAttribute('data-type', 'plugin');
scriptDom.innerHTML = js;
nextTick(() => {
document.body.append(scriptDom);
});
}
// function handleDom(js) {
// const domList = Array.from(document.getElementsByTagName('script'));
// const index = domList.findIndex(item => item.id === `p${props.pluginTaskId}`);
// if (index >= 0) {
// document.body.removeChild(document.getElementById(`p${props.pluginTaskId}`));
// }
// const scriptDom = document.createElement('script');
// scriptDom.id = `p${props.pluginTaskId}`;
// scriptDom.setAttribute('data-type', 'plugin');
// scriptDom.innerHTML = js;
// nextTick(() => {
// document.body.append(scriptDom);
// });
// }
//
async function getPlugin() {
const params = { pluginId: props.pluginId, styleType: props.styleType };
uni.$catchReq.getOtherPlugin(params, (err, data) => {
if (err) {
console.error('err: ', err);
} else {
if (!data || !data.id) return;
const reg = /data-root=["|']?(\w+)["|']?/gi;
let uuid = '';
// FIXME: js, html
if (data.html) {
// data-root=xxx xxx pluginTaskId
// async function getPlugin() {
// const params = { pluginId: props.pluginId, styleType: props.styleType };
// uni.$catchReq.getOtherPlugin(params, (err, data) => {
// if (err) {
// console.error('err: ', err);
// } else {
// if (!data || !data.id) return;
// const reg = /data-root=["|']?(\w+)["|']?/gi;
// let uuid = '';
// // FIXME: js, html
// if (data.html) {
// // data-root=xxx xxx pluginTaskId
if (reg.test(data.html)) {
uuid = RegExp.$1;
const str = data.html.replace(new RegExp(uuid, 'g'), `p${props.pluginTaskId}`);
data.pluginContent = str;
} else {
data.pluginContent = data.html;
}
// if (reg.test(data.html)) {
// uuid = RegExp.$1;
// const str = data.html.replace(new RegExp(uuid, 'g'), `p${props.pluginTaskId}`);
// data.pluginContent = str;
// } else {
// data.pluginContent = data.html;
// }
const str = data.js.replace(new RegExp(uuid, 'g'), `p${props.pluginTaskId}`);
handleDom(str);
}
}
});
// const str = data.js.replace(new RegExp(uuid, 'g'), `p${props.pluginTaskId}`);
// handleDom(str);
// }
// }
// });
// if (data.js) {
// if (reg.test(data.js)) {
@ -122,13 +123,14 @@ async function getPlugin() {
// this.handleDom(data.js);
// }
// }
}
// }
console.log('props.pluginId: ', props.pluginId);
if (props.pluginId === '5') {
// id
store.dispatch('role/getAllMembers', { projectId: projectId.value });
}
getPlugin();
// getPlugin();
// storage
async function setStorage() {

1
components/Roles/Roles.vue

@ -66,7 +66,6 @@ onMounted(() => {
query
.selectAll('.tab-children')
.boundingClientRect(res => {
console.log('data', res);
if (res.length) {
data.roleLeft = res[0].left;
}

8
components/TimeLine/TimeLine.vue

@ -15,14 +15,14 @@
<!-- 时间轴 -->
<!-- <u-divider bg-color="#f3f4f6" class="pt-5" fontSize="14px" v-if="topEnd">到顶啦</u-divider> -->
<!-- <TimeBox /> -->
<TimeBox />
<!-- <u-divider bg-color="#f3f4f6" class="pb-5" fontSize="14px" v-if="bottomEnd">到底啦</u-divider> -->
</scroll-view>
</template>
<script setup>
import { reactive, computed } from 'vue';
import { reactive, computed, defineExpose, defineEmits } from 'vue';
import { useStore } from 'vuex';
// import Barrier from './component/Barrier.vue';
import dayjs from 'dayjs';
@ -119,4 +119,8 @@ function setScrollPosition() {
}
}
}
defineExpose({
setScrollPosition
})
</script>

23
components/TimeLine/component/TimeBox.vue

@ -1,25 +1,25 @@
<template>
<view class="column" v-finger:pinch="pinchHandler">
<!-- v-if="tasks && tasks.length" -->
<view>
<!-- v-finger:pinch="pinchHandler" -->
<view class="column" >
<view v-if="tasks && tasks.length">
<view :key="task.id" v-for="task in tasks" :id="`a${task.id}`">
<view class="flex">
<!-- <TimeStatus :task="task" /> -->
<TimeStatus :task="task" />
<view class="flex items-center justify-between flex-1 ml-2 task-column">
<view v-if="task.process !== 4">{{ $moment(+task.planStart).format(startTimeFormat) }}</view>
<view v-else>{{ $moment(+task.planStart).format('D日') }}</view>
<!-- 任务功能菜单 -->
<!-- <TaskTools v-if="task.process !== 4" :task="task" /> -->
<TaskTools v-if="task.process !== 4" :task="task" />
</view>
</view>
<view class="border-l-2 border-gray-300 plugin">
<view class="plugin">
<view class="h-3" v-if="task.process === 4"></view>
<view class="ml-3 overflow-hidden shadow-lg task-box">
<u-card :show-foot="false" :show-head="false" :style="{ height: setHeight(task.panel) }" class="h-16" margin="0" v-if="showSkeleton">
<view slot="body">
<view>
<!-- <skeleton :banner="false" :loading="true" :row="4" animate class="mt-2 u-line-2 skeleton"></skeleton> -->
<skeleton :banner="false" :loading="true" :row="4" animate class="mt-2 u-line-2 skeleton"></skeleton>
</view>
</view>
</u-card>
@ -37,8 +37,8 @@
<view slot="body">
<view class="p-0 u-col-between">
<view :key="pIndex" v-for="(row, pIndex) in task.plugins">
<view class="grid gap-2 grid-cols-1" v-if="row.length">
<!-- <Plugin
<!-- <view class="grid gap-2 grid-cols-1" v-if="row.length">
<Plugin
:class="[`row-span-${plugin.row}`, `col-span-${plugin.col}`]"
:task="task"
:key="plugin.pluginTaskId"
@ -47,8 +47,8 @@
:param="plugin.param"
:style-type="data.styleType || 0"
v-for="plugin in row"
/> -->
</view>
/>
</view> -->
</view>
</view>
</view>
@ -120,6 +120,7 @@ function pinchHandler(evt) {
margin-top: 8px;
margin-bottom: 8px;
margin-left: 15px;
border-left: 2px solid #d1d5db;
}
::v-deep .ml-2 {
margin-left: 16px;

9
components/TimeLine/component/TimeStatus.vue

@ -59,6 +59,7 @@
<script setup>
import { reactive, onMounted, computed } from 'vue';
import { useStore } from 'vuex';
import dayjs from 'dayjs';
import CreateTask from '../../Title/components/CreateTask.vue';
const props = defineProps({ task: { type: Object, default: () => {} } });
@ -89,9 +90,9 @@ const data = reactive({
const store = useStore();
const tip = computed(() => store.state.task.tip);
const status = computed(() => [props.task ? props.task.process : 0]);
const taskName = computed(() => [props.task ? props.task.name : '']);
const taskId = computed(() => [props.task ? props.task.id : '']);
const status = computed(() => props.task ? props.task.process : 0);
const taskName = computed(() => props.task ? props.task.name : '');
const taskId = computed(() => props.task ? props.task.id : '');
//
function computeCyclePersent() {
@ -222,7 +223,7 @@ function confirmEndTime(e) {
// = realStart + planDuration - Date.now()
function computeDurationText() {
const { realStart, planDuration } = props.task;
const leftTime = +realStart + +planDuration - Date.now(); //
const leftTime = (realStart-0 || 0) + (planDuration-0 || 0) - Date.now(); //
const { num, time } = uni.$time.computeDurationText(leftTime);
if (num <= 0) {
clearInterval(data.timer);

2
config/task.js

@ -0,0 +1,2 @@
// 每页加载颗粒度的个数
export default { pageCount: 10 };

159
hooks/project/useGetTasks.js

@ -1,11 +1,10 @@
import { ref, computed, nextTick } from 'vue';
import { computed, nextTick } from 'vue';
import { useStore } from 'vuex';
import { flatten } from 'lodash';
import dayjs from 'dayjs';
export default function useGetTasks() {
const timeLine = ref(null);
const store = useStore();
const tasks = computed(() => store.state.task.tasks);
const showScrollTo = computed(() => store.state.task.showScrollTo);
const roleId = computed(() => store.state.role.roleId);
const timeNode = computed(() => store.state.task.timeNode);
const timeUnit = computed(() => store.state.task.timeUnit);
@ -17,67 +16,58 @@ export default function useGetTasks() {
setPrevPlaceholderTasks(); // 向上加载空数据
setNextPlaceholderTasks(); // 向下加载空数据
await getInitTasks(); // 获取初始数据
// 滚动到对应位置
// let timer = null;
// timer = setInterval(() => {
// if (showScrollTo.value) {
// clearInterval(timer);
// console.log('timeLine',timeLine)
// nextTick(() => timeLine.setScrollPosition());
// }
// }, 500);
}
// 切换了 颗粒度 || 角色时候 获取初始定期任务
function getInitTasks() {
// 预加载 上下的定期任务
// function preloadFn(that) {
// const detailId = tasks.value.findIndex(task => task.detailId);
// const arr = [];
// tasks.value.forEach(task => {
// if (task.detailId) {
// arr.push(task);
// }
// });
// if (detailId !== -1) {
// // 只要有1个真实的任务 就预加载上下周期的任务
// const {
// pageCount
// } = uni.$task;
// nextTick(() => {
// // 向上拿数据
// getTasks({
// timeNode: +tasks.value[detailId].planStart,
// queryType: 0,
// queryNum: pageCount
// });
// // 向下拿数据
// const nextQueryTime = +uni.$time.add(+arr[arr.length - 1].planStart, 1, timeGranularity.value);
// getTasks({
// timeNode: nextQueryTime,
// queryType: 1,
// queryNum: pageCount
// });
// });
// } else {
// // 没有任务 上下显示时间刻度
// // 向上加载
// setPrevPlaceholderTasks();
// // // 向下加载
// setNextPlaceholderTasks();
// }
// }
function preloadFn(that) {
const detailId = tasks.value.findIndex(task => task.detailId);
const arr = [];
tasks.value.forEach(task => {
if (task.detailId) {
arr.push(task);
}
});
if (detailId !== -1) {
// 只要有1个真实的任务 就预加载上下周期的任务
const { pageCount } = uni.$task;
nextTick(() => {
// 向上拿数据
getTasks({
timeNode: +tasks.value[detailId].planStart,
queryType: 0,
queryNum: pageCount,
});
// 向下拿数据
const nextQueryTime = +uni.$time.add(+arr[arr.length - 1].planStart, 1, timeGranularity.value);
getTasks({
timeNode: nextQueryTime,
queryType: 1,
queryNum: pageCount,
});
});
} else {
// 没有任务 上下显示时间刻度
// 向上加载
setPrevPlaceholderTasks();
// // 向下加载
setNextPlaceholderTasks();
}
}
// 根据时间基准点和角色查找定期任务
getTasks({
queryType: 0
queryType: 0,
}); // 向上获取定期任务数据
// 根据项目id获取角色列表
// 向下获取定期任务数据
// getTasks({
// queryType: 1
// }, preloadFn);
getTasks(
{
queryType: 1,
},
preloadFn,
);
}
/**
@ -105,8 +95,7 @@ export default function useGetTasks() {
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
function getTasks(query, fn) {
// store.commit('task/setShowSkeleton', false);
console.log('根据时间基准点和角色查找定期任务')
store.commit('task/setShowSkeleton', false);
const params = generateGetTaskParam(query);
uni.$catchReq.getRegularTask(params, (err, data) => {
store.commit('task/setShowSkeleton', false);
@ -118,17 +107,58 @@ export default function useGetTasks() {
// 有数据用数据替换刻度
// 没有数据 继续加载刻度
if (data && data.length) {
// replacePrevData(data, params.queryType);
replacePrevData(data, params.queryType);
params.queryType === 0 ? store.commit('task/setTopEnd', false) : store.commit('task/setBottomEnd', false);
} else {
// TODO: 0 -> 向上 1 -> 向下
// params.queryType === 0 ? setPrevPlaceholderTasks() : setNextPlaceholderTasks();
params.queryType === 0 ? setPrevPlaceholderTasks() : setNextPlaceholderTasks();
}
// if (tasks.value.length && fn) {
// fn(this);
// }
if (tasks.value.length && fn) {
fn(this);
}
}
});
}
/**
* 用拿到的新数据 替换 时间刻度/旧数据
* 先对比 新旧数据的 始末时间 补齐刻度
* 再遍历对比 用任务替换刻度
* @param {array} data 服务端返回的新数据 上边已经处理过空值
* @param {number} type 0 -> 向上 1->向下
*/
function replacePrevData(data, type) {
const obj = { tasks: tasks.value, data, timeGranularity: timeGranularity.value };
let oldTasks = fillPlaceholderTask(obj); // 已经上下补齐时间刻度的
// 遍历对比 用任务替换刻度
// TODO: tasks越来越多 遍历越来越多 需要优化
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => dayjs(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity.value));
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // 这里加入的数据是array类型的, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1维拍平
store.commit('task/clearTasks');
type === 0 ? store.commit('task/setUpTasks', oldTasks) : store.commit('task/setDownTasks', oldTasks);
}
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
*/
function fillPlaceholderTask(obj) {
const { prev, next } = uni.$task.computeFillPlaceholderTaskCount(obj);
if (prev) {
const newTasks = uni.$task.setPlaceholderTasks(+obj.tasks[0].planStart, true, obj.timeGranularity, prev);
store.commit('task/setUpTasks', newTasks);
}
if (next) {
const newTasks = uni.$task.setPlaceholderTasks(+obj.tasks[tasks.length - 1].planStart, false, obj.timeGranularity, next);
store.commit('task/setDownTasks', newTasks);
}
return tasks.value;
}
// 设置时间轴向上的空数据
@ -138,7 +168,7 @@ export default function useGetTasks() {
if (!tasks.value || !tasks.value.length) {
startTime = Date.now(); // 没有任务就应该是时间基准点
} else {
startTime = tasks[0].planStart - 0; // 有任务就是第一个任务的计划开始时间
startTime = tasks.value[0].planStart - 0; // 有任务就是第一个任务的计划开始时间
}
const placeholderTasks = uni.$task.setPlaceholderTasks(startTime, true, timeGranularity.value);
store.commit('task/setUpTasks', placeholderTasks);
@ -158,6 +188,7 @@ export default function useGetTasks() {
}
return {
initPlanTasks
}
initPlanTasks,
getTasks,
};
}

449
hooks/project/useInit - 副本.js

@ -1,449 +0,0 @@
import {
ref,
onMounted,
computed,
watch,
nextTick
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import useGetUserIdFromLocal from '@/hooks/user/useGetUserIdFromLocal';
import {
useStore
} from 'vuex';
import {
flatten
} from 'lodash';
export default function useInit() {
const store = useStore();
const token = computed(() => store.state.user.token);
const userId = useGetUserIdFromLocal();
const roleId = computed(() => store.state.role.roleId);
const timeNode = computed(() => store.state.task.timeNode);
const timeUnit = computed(() => store.state.task.timeUnit);
const tasks = computed(() => store.state.task.tasks);
const newProjectInfo = computed(() => store.state.task.newProjectInfo);
const showScrollTo = computed(() => store.state.task.showScrollTo);
const timeGranularity = computed(() => store.getters['task/timeGranularity']);
const projectId = computed(() => store.getters['project/projectId']);
const height = ref(null);
const timeLine = ref(null);
onLoad(options => {
console.log('onLoad options: ', options);
if (options.share && options.share === '1') {
shareInit(options);
} else {
init(options);
}
});
/**
* 当时间基准点发生变化时
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生 改变
*/
watch(timeNode, newValue => {
if (newValue && roleId.value) {
console.log('当时间基准点发生变化时')
clearTasksData();
getGlobalData(); // 查可变日常任务
initPlanTasks(); // 处理定期任务
}
});
/**
* 当角色发生变化时
* 重新查询永久日常任务和普通日常任务
* 注意: 切换角色后 重新设置了时间基准点 时间基准点一定会变
* 所以监听时间基准点获取 可变日常任务即可 这里不用获取 避免重复获取
*/
watch(roleId, newValue => {
if (newValue) {
console.log('当角色发生变化时')
store.commit('task/setTimeNode', Date.now());
// 根据角色查找永久的日常任务
const params = {
roleId: newValue.value,
projectId: projectId.value
};
store.dispatch('task/getPermanent', params);
}
});
/**
* 当时间基准点发生变化时
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生改变
*/
watch(newProjectInfo, newValue => {
console.log('当时间基准点发生变化时')
if (newValue && newValue.value.projectId && newValue.value.url) {
uni.$u.route('/', {
u: userId.value,
p: newValue.value.projectId,
url: newValue.value.url
});
clearTasksData();
store.commit('role/setRoleId', '');
const options = uni.$route.query;
init(options);
}
});
onMounted(() => {
const system = uni.getSystemInfoSync();
height.value = `${system.windowHeight}px`;
});
/**
* 初始化
* @param {object | null} options
*/
function init(options) {
console.log('初始化init')
if (!token.value) {
// 不论有没有token都直接从userId获取token
// token有过期时间 从本地获取可能是过期 干脆直接从userId获取
if (!options || !options.u) {
uni.$ui.showToast('缺少用户信息参数'); // 参数里没有u (userId)提示
} else {
store.dispatch('user/getToken', options.u);
}
}
// 参数里有项目名称 就设置标题里的项目名称
options && options.pname && store.commit('project/setProjectName', options.pname);
if (!options || !options.p) {
uni.$ui.showToast('缺少项目信息参数'); // 没有项目id参数
} else {
if (options.p !== uni.$storage.getStorageSync('projectId')) {
console.log('切项目了');
uni.$storage.setStorageSync('roleId', '');
}
// 根据项目id获取项目信息
const params = {
projectId: options.p,
num: 0
}
getProjectById(params);
// 查询医院是否填写了调查问卷
// this.handleQueryNotWrite(options.p);
// 根据项目id获取成员列表
store.dispatch('role/getAllMembers', {
projectId: options.p
});
}
}
// 初始化 定期任务
async function initPlanTasks() {
setPrevPlaceholderTasks(); // 向上加载空数据
setNextPlaceholderTasks(); // 向下加载空数据
await getInitTasks(); // 获取初始数据
// 滚动到对应位置
let timer = null;
timer = setInterval(() => {
if (showScrollTo.value) {
clearInterval(timer);
// nextTick(() => timeLine.setScrollPosition());
}
}, 500);
}
// 切换了 颗粒度 || 角色时候 获取初始定期任务
function getInitTasks() {
// 预加载 上下的定期任务
function preloadFn(that) {
const detailId = tasks.value.findIndex(task => task.detailId);
const arr = [];
tasks.value.forEach(task => {
if (task.detailId) {
arr.push(task);
}
});
if (detailId !== -1) {
// 只要有1个真实的任务 就预加载上下周期的任务
const {
pageCount
} = uni.$task;
nextTick(() => {
// 向上拿数据
getTasks({
timeNode: +tasks.value[detailId].planStart,
queryType: 0,
queryNum: pageCount
});
// 向下拿数据
const nextQueryTime = +uni.$time.add(+arr[arr.length - 1].planStart, 1, timeGranularity.value);
getTasks({
timeNode: nextQueryTime,
queryType: 1,
queryNum: pageCount
});
});
} else {
// 没有任务 上下显示时间刻度
// 向上加载
setPrevPlaceholderTasks();
// // 向下加载
setNextPlaceholderTasks();
}
}
// 根据时间基准点和角色查找定期任务
getTasks({
queryType: 0
}); // 向上获取定期任务数据
// 根据项目id获取角色列表
getTasks({
queryType: 1
}, preloadFn); // 向下获取定期任务数据
}
/**
* 根据时间基准点和角色查找定期任务
* @param {object} query
* @param {string} query.roleId 角色id
* @param {string} query.timeNode 时间基准点 默认当前
* @param {string} query.timeUnit 时间颗粒度 默认天
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
function getTasks(query, fn) {
store.commit('task/setShowSkeleton', false);
const params = generateGetTaskParam(query);
uni.$catchReq.getRegularTask(params, (err, data) => {
store.commit('task/setShowSkeleton', false);
if (err) {
// TODO: 提示错误
console.error('err: ', err);
} else {
store.commit('task/setShowScrollTo', true);
// 有数据用数据替换刻度
// 没有数据 继续加载刻度
if (data && data.length) {
replacePrevData(data, params.queryType);
params.queryType === 0 ? store.commit('task/setTopEnd', false) : store.commit('task/setBottomEnd', false);
} else {
// TODO: 0 -> 向上 1 -> 向下
params.queryType === 0 ? setPrevPlaceholderTasks() : setNextPlaceholderTasks();
}
if (tasks.value.length && fn) {
fn(this);
}
}
});
}
/**
* 生成getTasks所用的参数
* @param {object} query getTasks传递的参数
*/
function generateGetTaskParam(query) {
return {
roleId: roleId.value,
timeNode: query.timeNode || timeNode.value,
timeUnit: query.timeUnit || timeUnit.value,
queryNum: query.queryNum || 3,
queryType: query.queryType,
projectId: projectId.value,
};
}
// 设置时间轴向上的空数据
function setPrevPlaceholderTasks() {
store.commit('task/setTopEnd', true);
let startTime = '';
if (!tasks.value || !tasks.value.length) {
startTime = Date.now(); // 没有任务就应该是时间基准点
} else {
startTime = tasks[0].planStart - 0; // 有任务就是第一个任务的计划开始时间
}
const placeholderTasks = uni.$task.setPlaceholderTasks(startTime, true, timeGranularity.value);
store.commit('task/setUpTasks', placeholderTasks);
}
// 设置时间轴向下的空数据
function setNextPlaceholderTasks() {
store.commit('task/setBottomEnd', true);
let startTime = '';
if (!tasks.value || !tasks.value.length) {
startTime = Date.now();
} else {
startTime = +tasks.value[tasks.value.length - 1].planStart;
}
const initData = uni.$task.setPlaceholderTasks(startTime, false, timeGranularity.value);
store.commit('task/setDownTasks', initData);
}
/**
* 用拿到的新数据 替换 时间刻度/旧数据
* 先对比 新旧数据的 始末时间 补齐刻度
* 再遍历对比 用任务替换刻度
* @param {array} data 服务端返回的新数据 上边已经处理过空值
* @param {number} type 0 -> 向上 1->向下
*/
function replacePrevData(data, type) {
let oldTasks = fillPlaceholderTask({ tasks.value, data, timeGranularity.value }); // 已经上下补齐时间刻度的
// 遍历对比 用任务替换刻度
// TODO: tasks越来越多 遍历越来越多 需要优化
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => dayjs(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity
.value));
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // 这里加入的数据是array类型的, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1维拍平
store.commit('task/clearTasks');
type === 0 ? store.commit('task/setUpTasks', oldTasks) : store.commit('task/setDownTasks', oldTasks);
}
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
*/
function fillPlaceholderTask({
tasks,
data,
timeGranularity
}) {
const {
prev,
next
} = uni.$task.computeFillPlaceholderTaskCount({
tasks,
data,
timeGranularity
});
if (prev) {
const newTasks = uni.$task.setPlaceholderTasks(+tasks[0].planStart, true, timeGranularity, prev);
store.commit('task/setUpTasks', newTasks);
}
if (next) {
const newTasks = uni.$task.setPlaceholderTasks(+tasks[tasks.length - 1].planStart, false, timeGranularity, next);
store.commit('task/setDownTasks', newTasks);
}
return tasks.value;
}
// 分享链接来的初始化
async function shareInit(options) {
console.log('分享链接来的初始化init')
const storageUser = uni.$storage.getStorageSync('user');
const user = storageUser ? JSON.parse(storageUser) : null;
if (user && user.id) {
await store.dispatch('user/getToken', user.id);
const res = await clickShare({
code: options.shareId
});
if (res && res.projectId) {
let query = {
...uni.$route.query
};
query = {
u: user.id,
p: res.projectId,
};
uni.$router.push({
path: uni.$route.path,
query
});
console.log('query',query)
init(query);
}
} else {
uni.$ui.showToast('缺少用户信息参数,请登录');
}
}
/**
* 点击分享连接
* @param {any} commit
* @param {object} param 请求参数
*/
async function clickShare(param) {
try {
const data = await uni.$catchReq.clickShare(param);
return data;
} catch (error) {
uni.$ui.showToast(error.msg || '获取失败');
}
}
/**
* 通过项目id获取项目信息
* @param {object} params 提交的参数
*/
async function getProjectById(params) {
try {
const data = await uni.$u.api.findProjectById(params);
store.commit('project/setProject', data);
// 根据项目id获取角色列表
getRoles(params);
} catch (error) {
console.log('error: ', error || '获取项目信息失败');
}
}
/**
* 通过项目id获取角色信息
* @param {string} projectId
* @param {object} params 提交的参数
*/
function getRoles(params) {
uni.$catchReq.findShowRole(params, (err, data) => {
if (err) {
console.error('err: ', err || '获取角色信息失败');
} else {
store.commit('role/setInvisibleRoles', data ? data.invisibleList : []);
store.commit('role/setVisibleRoles', data ? data.visibleList : []);
setInitialRoleId(data ? data.visibleList : []);
}
});
}
// 设置 初始显示角色信息
function setInitialRoleId(visibleList) {
if (!visibleList || !visibleList.length) return;
const index = visibleList.findIndex(item => +item.mine === 1);
const currentRole = index > 0 ? visibleList[index] : visibleList[0];
const storageRoleId = uni.$storage.getStorageSync('roleId');
const currentRoleId = storageRoleId || (currentRole ? currentRole.id : '');
store.commit('role/setRoleId', currentRoleId);
// 清空storage
uni.$storage.setStorageSync('roleId', '');
}
// 获取可变全局任务
function getGlobalData() {
const param = {
roleId: roleId.value,
timeNode: timeNode.value,
timeUnit: timeUnit.value,
projectId: projectId.value
};
store.dispatch('task/getGlobal', param);
}
// 清除已有的任务数据
function clearTasksData() {
// 清空日常任务的数据
store.commit('task/setPermanents', []);
store.commit('task/setDailyTasks', []);
// 清空定期任务数据
store.commit('task/clearTasks');
// 到顶的标志复位
// 到底的标志复位
store.commit('task/clearEndFlag');
}
}

16
hooks/project/useInit.js

@ -81,8 +81,6 @@ export default function useInit() {
// 根据项目id获取项目信息
const params = { projectId: options.p, num: 0 };
getProjectById(params);
// 查询医院是否填写了调查问卷
// this.handleQueryNotWrite(options.p);
// 根据项目id获取成员列表
store.dispatch('role/getAllMembers', { projectId: options.p });
}
@ -106,5 +104,19 @@ export default function useInit() {
}
}
/**
* 点击分享连接
* @param {any} commit
* @param {object} param 请求参数
*/
async function clickShare(param) {
try {
const data = await uni.$catchReq.clickShare(param);
return data;
} catch (error) {
uni.$ui.showToast(error.msg || '获取失败');
}
}
return { init };
}

3
main.js

@ -14,6 +14,7 @@ import store from './store';
import task from '@/utils/task.js';
import time from '@/utils/time.js';
import timeConfig from '@/config/time';
import taskConfig from '@/config/task';
import uView from './uni_modules/vk-uview-ui'; // 引入 uView UI
import ui from '@/utils/ui.js';
import upload from '@/utils/upload.js';
@ -29,6 +30,7 @@ export function createApp() {
app.config.globalProperties.$upload = upload;
app.config.globalProperties.$task = task;
app.config.globalProperties.$timeConfig = timeConfig;
app.config.globalProperties.$taskConfig = taskConfig;
uni.$cache = cache;
uni.$catchReq = cacheAndRequest;
@ -38,6 +40,7 @@ export function createApp() {
uni.$upload = upload;
uni.$task = task;
uni.$timeConfig = timeConfig;
uni.$taskConfig = taskConfig;
setupDayjs(app);
app.use(uView); // 使用 uView UI

434
pages/project/project A.vue

@ -1,434 +0,0 @@
<template>
<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 />
<!-- 日常任务面板 -->
<Globals />
<!-- 定期任务面板 -->
<!-- <TimeLine @getTasks="getTasks" class="flex-1 overflow-hidden" ref="timeLine" /> -->
</view>
</view>
</template>
<script>
import { defineComponent, ref, onMounted, computed, watch, nextTick } from 'vue';
import { useStore } from 'vuex';
import { flatten } from 'lodash';
export default defineComponent({
setup(options) {
const store = useStore();
const token = computed(() => store.state.user.token);
const userId = computed(() => store.getters['user/userId']);
const roleId = computed(() => store.state.role.roleId);
const timeNode = computed(() => store.state.task.timeNode);
const timeUnit = computed(() => store.state.task.timeUnit);
const tasks = computed(() => store.state.task.tasks);
const newProjectInfo = computed(() => store.state.task.newProjectInfo);
const showScrollTo = computed(() => store.state.task.showScrollTo);
const timeGranularity = computed(() => store.getters['task/timeGranularity']);
const projectId = computed(() => store.getters['project/projectId']);
const height = ref(null);
const timeLine = ref(null);
/**
* 当时间基准点发生变化时
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生 改变
*/
watch(timeNode, newValue => {
if (newValue && roleId.value) {
clearTasksData();
getGlobalData(); //
initPlanTasks(); //
}
});
/**
* 当角色发生变化时
* 重新查询永久日常任务和普通日常任务
* 注意: 切换角色后 重新设置了时间基准点 时间基准点一定会变
* 所以监听时间基准点获取 可变日常任务即可 这里不用获取 避免重复获取
*/
watch(roleId, newValue => {
if (newValue) {
store.commit('task/setTimeNode', Date.now());
//
const params = { roleId: newValue, projectId: projectId.value };
store.dispatch('task/getPermanent', params);
}
});
/**
* 当时间基准点发生变化时
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生改变
*/
watch(newProjectInfo, newValue => {
if (newValue && newValue.projectId && newValue.url) {
uni.$u.route('/', { u: userId.value, p: newValue.projectId, url: newValue.url });
clearTasksData();
store.commit('role/setRoleId', '');
const options = uni.$route.query;
init(options);
}
});
onMounted(() => {
const system = uni.getSystemInfoSync();
height.value = `${system.windowHeight}px`;
});
//
async function initPlanTasks() {
setPrevPlaceholderTasks(); //
setNextPlaceholderTasks(); //
await getInitTasks(); //
//
let timer = null;
timer = setInterval(() => {
if (showScrollTo.value) {
clearInterval(timer);
// nextTick(() => timeLine.setScrollPosition());
}
}, 500);
}
// ||
function getInitTasks() {
//
function preloadFn(that) {
const detailId = tasks.value.findIndex(task => task.detailId);
const arr = [];
tasks.value.forEach(task => {
if (task.detailId) {
arr.push(task);
}
});
if (detailId !== -1) {
// 1
const { pageCount } = uni.$task;
nextTick(() => {
//
getTasks({ timeNode: +tasks.value[detailId].planStart, queryType: 0, queryNum: pageCount });
//
const nextQueryTime = +uni.$time.add(+arr[arr.length - 1].planStart, 1, timeGranularity.value);
getTasks({ timeNode: nextQueryTime, queryType: 1, queryNum: pageCount });
});
} else {
//
//
setPrevPlaceholderTasks();
// //
setNextPlaceholderTasks();
}
}
//
getTasks({ queryType: 0 }); //
// id
getTasks({ queryType: 1 }, preloadFn); //
}
/**
* 根据时间基准点和角色查找定期任务
* @param {object} query
* @param {string} query.roleId 角色id
* @param {string} query.timeNode 时间基准点 默认当前
* @param {string} query.timeUnit 时间颗粒度 默认天
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
function getTasks(query, fn) {
store.commit('task/setShowSkeleton', false);
const params = generateGetTaskParam(query);
uni.$catchReq.getRegularTask(params, (err, data) => {
store.commit('task/setShowSkeleton', false);
if (err) {
// TODO:
console.error('err: ', err);
} else {
store.commit('task/setShowScrollTo', true);
//
//
if (data && data.length) {
replacePrevData(data, params.queryType);
params.queryType === 0 ? store.commit('task/setTopEnd', false) : store.commit('task/setBottomEnd', false);
} else {
// TODO: 0 -> 1 ->
params.queryType === 0 ? setPrevPlaceholderTasks() : setNextPlaceholderTasks();
}
if (tasks.value.length && fn) {
fn(this);
}
}
});
}
/**
* 生成getTasks所用的参数
* @param {object} query getTasks传递的参数
*/
function generateGetTaskParam(query) {
return {
roleId: roleId.value,
timeNode: query.timeNode || timeNode.value,
timeUnit: query.timeUnit || timeUnit.value,
queryNum: query.queryNum || 3,
queryType: query.queryType,
projectId: projectId.value,
};
}
//
function setPrevPlaceholderTasks() {
store.commit('task/setTopEnd', true);
let startTime = '';
if (!tasks.value || !tasks.value.length) {
startTime = Date.now(); //
} else {
startTime = tasks[0].planStart - 0; //
}
const placeholderTasks = uni.$task.setPlaceholderTasks(startTime, true, timeGranularity.value);
store.commit('task/setUpTasks', placeholderTasks);
}
//
function setNextPlaceholderTasks() {
store.commit('task/setBottomEnd', true);
let startTime = '';
if (!tasks.value || !tasks.value.length) {
startTime = Date.now();
} else {
startTime = +tasks.value[tasks.value.length - 1].planStart;
}
const initData = uni.$task.setPlaceholderTasks(startTime, false, timeGranularity.value);
store.commit('task/setDownTasks', initData);
}
/**
* 用拿到的新数据 替换 时间刻度/旧数据
* 先对比 新旧数据的 始末时间 补齐刻度
* 再遍历对比 用任务替换刻度
* @param {array} data 服务端返回的新数据 上边已经处理过空值
* @param {number} type 0 -> 向上 1->向下
*/
function replacePrevData(data, type) {
let oldTasks = fillPlaceholderTask({ tasks.value, data, timeGranularity.value }); //
//
// TODO: tasks
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => dayjs(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity.value));
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // array, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1
store.commit('task/clearTasks');
type === 0 ? store.commit('task/setUpTasks', oldTasks) : store.commit('task/setDownTasks', oldTasks);
}
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
*/
function fillPlaceholderTask({ tasks, data, timeGranularity }) {
const { prev, next } = uni.$task.computeFillPlaceholderTaskCount({ tasks, data, timeGranularity });
if (prev) {
const newTasks = uni.$task.setPlaceholderTasks(+tasks[0].planStart, true, timeGranularity, prev);
store.commit('task/setUpTasks', newTasks);
}
if (next) {
const newTasks = uni.$task.setPlaceholderTasks(+tasks[tasks.length - 1].planStart, false, timeGranularity, next);
store.commit('task/setDownTasks', newTasks);
}
return tasks.value;
}
/**
* 初始化
* @param {object | null} options
*/
function init(options) {
if (!token.value) {
// tokenuserIdtoken
// token userId
if (!options || !options.u) {
uni.$ui.showToast('缺少用户信息参数'); // u (userId)
} else {
store.dispatch('user/getToken', options.u);
}
}
//
options && options.pname && store.commit('project/setProjectName', options.pname);
if (!options || !options.p) {
uni.$ui.showToast('缺少项目信息参数'); // id
} else {
if (options.p !== uni.$storage.getStorageSync('projectId')) {
console.log('切项目了');
uni.$storage.setStorageSync('roleId', '');
}
// TODO
getProjectById({ projectId: options.p, num: 0 }); // id
//
// this.handleQueryNotWrite(options.p);
// id
store.dispatch('role/getAllMembers', { projectId: options.p });
}
}
//
async function shareInit(options) {
const storageUser = uni.$storage.getStorageSync('user');
const user = storageUser ? JSON.parse(storageUser) : null;
if (user && user.id) {
await store.dispatch('user/getToken', user.id);
const res = await clickShare({ code: options.shareId });
if (res && res.projectId) {
let query = { ...uni.$route.query };
query = {
u: user.id,
p: res.projectId,
};
uni.$router.push({ path: uni.$route.path, query });
init(query);
}
} else {
uni.$ui.showToast('缺少用户信息参数,请登录');
}
}
function setOptions(options) {
if (options.share && options.share === '1') {
shareInit(options);
} else {
init(options);
}
}
setOptions(options);
/**
* 点击分享连接
* @param {any} commit
* @param {object} param 请求参数
*/
async function clickShare(param) {
try {
const data = await uni.$catchReq.clickShare(param);
return data;
} catch (error) {
uni.$ui.showToast(error.msg || '获取失败');
}
}
/**
* 通过项目id获取项目信息
* @param {object} params 提交的参数
*/
async function getProjectById(params) {
try {
const data = await uni.$u.api.findProjectById(params);
store.commit('project/setProject', data);
// id
getRoles(params);
} catch (error) {
console.log('error: ', error || '获取项目信息失败');
}
}
/**
* 通过项目id获取角色信息
* @param {string} projectId
* @param {object} params 提交的参数
*/
function getRoles(params) {
uni.$catchReq.findShowRole(params, (err, data) => {
if (err) {
console.error('err: ', err || '获取角色信息失败');
} else {
store.commit('role/setInvisibleRoles', data ? data.invisibleList : []);
store.commit('role/setVisibleRoles', data ? data.visibleList : []);
setInitialRoleId(data ? data.visibleList : []);
}
});
}
//
function setInitialRoleId(visibleList) {
if (!visibleList || !visibleList.length) return;
const index = visibleList.findIndex(item => +item.mine === 1);
const currentRole = index > 0 ? visibleList[index] : visibleList[0];
const storageRoleId = uni.$storage.getStorageSync('roleId');
const currentRoleId = storageRoleId || (currentRole ? currentRole.id : '');
store.commit('role/setRoleId', currentRoleId);
// storage
uni.$storage.setStorageSync('roleId', '');
}
//
function getGlobalData() {
const param = { roleId: roleId.value, timeNode: timeNode.value, timeUnit: timeUnit.value, projectId: projectId.value };
store.dispatch('task/getGlobal', param);
}
//
function clearTasksData() {
//
store.commit('task/setPermanents', []);
store.commit('task/setDailyTasks', []);
//
store.commit('task/clearTasks');
//
//
store.commit('task/clearEndFlag');
}
return {
height,
timeLine,
roleId,
timeNode,
timeUnit,
tasks,
newProjectInfo,
showScrollTo,
timeGranularity,
projectId,
userId,
initPlanTasks,
getInitTasks,
getTasks,
generateGetTaskParam,
setPrevPlaceholderTasks,
setNextPlaceholderTasks,
replacePrevData,
fillPlaceholderTask,
init,
shareInit,
setOptions,
clickShare,
getProjectById,
getRoles,
setInitialRoleId,
getGlobalData,
clearTasksData,
};
},
});
</script>
<style lang="scss" scoped>
.border-b {
border-bottom: 1px solid #e4e7ed;
}
</style>

18
pages/project/project.vue

@ -11,8 +11,7 @@
<Globals />
<!-- 定期任务面板 -->
<!-- <TimeLine @getTasks="getTasks" class="flex-1 overflow-hidden" ref="timeLine" /> -->
<TimeLine class="flex-1 overflow-hidden" ref="timeLine" />
<TimeLine @getTasks="getTasks" class="flex-1 overflow-hidden" ref="timeLine" />
<!-- TODO: DEBUG: -->
<u-button @click="$store.commit('setTheme', 'theme-test')">测试切换主题</u-button>
@ -35,7 +34,9 @@ const timeUnit = computed(() => store.state.task.timeUnit);
const projectId = computed(() => store.getters['project/projectId']);
const userId = computed(() => store.getters['user/userId']);
const newProjectInfo = computed(() => store.state.task.newProjectInfo);
const showScrollTo = computed(() => store.state.task.showScrollTo);
const height = ref(null);
const timeLine = ref(null);
onMounted(() => {
const system = uni.getSystemInfoSync();
@ -77,6 +78,15 @@ watch(timeNode, newValue => {
getGlobalData(); //
// initPlanTasks(); //
getTasksHook.initPlanTasks(); //
//
let timer = null;
timer = setInterval(() => {
if (showScrollTo.value) {
clearInterval(timer);
timeLine.value.setScrollPosition();
}
}, 500);
}
});
@ -119,6 +129,10 @@ watch(newProjectInfo, newValue => {
initHook.init(options);
}
});
function getTasks(params) {
getTasksHook.initPlanTasks(params); //
}
</script>
<style lang="scss" scoped>

366
utils/cacheAndRequest.js

@ -1,178 +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.$storage.getStorageSync('anyringToken')) {
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.$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.$cache.putProjects(data);
})
.catch(err => fn(err));
});
},
/**
* 通过项目id获取角色信息
* @param {object} params 提交的参数
*/
findShowRole(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putShowRole(params.projectId, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间基准点和角色查找定期任务
* @param {object} params 提交的参数
*/
getRegularTask(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putStorageRegularTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据角色查找永久的日常任务
* @param {object} params 提交的参数
*/
getPermanent(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putStoragePermanent(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间和角色查找日常任务
* @param {object} params 提交的参数
*/
getGlobal(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putDailyTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 获取插件信息
* @param {object} params 提交的参数
*/
getOtherPlugin(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putPlugin(params.pluginId, data);
})
.catch(err => fn(err));
});
},
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.$storage.getStorageSync('anyringToken')) {
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.$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.$cache.putProjects(data);
})
.catch(err => fn(err));
});
},
/**
* 通过项目id获取角色信息
* @param {object} params 提交的参数
*/
findShowRole(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putShowRole(params.projectId, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间基准点和角色查找定期任务
* @param {object} params 提交的参数
*/
getRegularTask(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putStorageRegularTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据角色查找永久的日常任务
* @param {object} params 提交的参数
*/
getPermanent(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putStoragePermanent(params, data);
})
.catch(err => fn(err));
});
},
/**
* 根据时间和角色查找日常任务
* @param {object} params 提交的参数
*/
getGlobal(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putDailyTask(params, data);
})
.catch(err => fn(err));
});
},
/**
* 获取插件信息
* @param {object} params 提交的参数
*/
getOtherPlugin(params, fn) {
let remote = false;
// 有缓存 且 服务端数据未返回 就先返回缓存
uni.$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.$cache.putPlugin(params.pluginId, data);
})
.catch(err => fn(err));
});
},
};

7
utils/task.js

@ -9,7 +9,7 @@ import dayjs from 'dayjs';
*/
const setPlaceholderTasks = (startTime, isUp, timeGranularity, pageCount) => {
let result = [];
pageCount = pageCount || uni.$task.pageCount;
pageCount = pageCount || uni.$taskConfig.pageCount;
for (let i = 0; i < pageCount; i++) {
const delta = isUp ? `-${i + 1}` - 0 : i + 1;
let item = {
@ -33,7 +33,8 @@ const setPlaceholderTasks = (startTime, isUp, timeGranularity, pageCount) => {
* @param {array} option.data 新拿到的任务数据 空值已经过滤过了
* @param {string} option.timeGranularity 颗粒度
*/
const computeFillPlaceholderTaskCount = ({ tasks, data, timeGranularity }) => {
const computeFillPlaceholderTaskCount = obj => {
const { tasks, data, timeGranularity } = obj;
let result = { prev: 0, next: 0 };
// 新数据的开始时间 < 旧数据的开始时间
// 超出了上限 补上限的时间刻度
@ -54,5 +55,5 @@ const computeFillPlaceholderTaskCount = ({ tasks, data, timeGranularity }) => {
export default {
setPlaceholderTasks,
computeFillPlaceholderTaskCount
computeFillPlaceholderTaskCount,
};

47
utils/time.js

@ -12,7 +12,7 @@ import dayjs from 'dayjs';
* 格式化数字
* @param {*} n
*/
const formatNumber = (n) => {
const formatNumber = n => {
const str = n.toString();
return str[1] ? str : `0${str}`;
};
@ -21,7 +21,7 @@ const formatNumber = (n) => {
* 格式化时间
* @param {number} beginTime
*/
const formatTime = (beginTime) => {
const formatTime = beginTime => {
const date = new Date(beginTime);
const year = date.getFullYear();
const month = date.getMonth() + 1;
@ -49,7 +49,7 @@ const add = (time, num, cycle) => {
* @param {string} time
* @returns {{hours: number, minutes: number}}
*/
const convertTime = (time) => {
const convertTime = time => {
const arr = time.split(':');
return {
hours: parseInt(arr[0], 10),
@ -61,7 +61,7 @@ const convertTime = (time) => {
* 将秒 ->
* @param {number} seconds
*/
const secondToMinute = (seconds) => {
const secondToMinute = seconds => {
const minute = formatNumber(Math.floor(seconds / 60));
const second = formatNumber(parseInt(seconds % 60, 10));
return {
@ -75,7 +75,7 @@ const secondToMinute = (seconds) => {
* @param {Number} timestamp 时间戳
* @return date:2018/10/09 time: 12:59
*/
const setTimestampToStr = (timestamp) => {
const setTimestampToStr = timestamp => {
const timeObj = new Date(timestamp);
const year = timeObj.getFullYear();
const month = formatNumber(timeObj.getMonth() + 1);
@ -94,11 +94,10 @@ const setTimestampToStr = (timestamp) => {
* 检测时间(ms)是不是今天
* @param {Number} time 时间戳
*/
const validateTimeIsToday = (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();
return timeDate.getFullYear() === date.getFullYear() && timeDate.getMonth() === date.getMonth() && timeDate.getDate() === date.getDate();
};
/**
@ -120,7 +119,7 @@ const isSame = (time, value, cycle) => {
* 如果不是今年 -> // :
* 否则 ** :
*/
const formatBeginTime = (timestamp) => {
const formatBeginTime = timestamp => {
const timeObj = new Date(timestamp);
const year = timeObj.getFullYear();
const month = formatNumber(timeObj.getMonth() + 1);
@ -134,7 +133,8 @@ const formatBeginTime = (timestamp) => {
if (validateTimeIsToday(timestamp)) {
// 今天
return `今天 ${time}`;
} if (currentYear !== year) {
}
if (currentYear !== year) {
// 不是今年
return `${date} ${time}`;
}
@ -149,7 +149,7 @@ const formatBeginTime = (timestamp) => {
* 其余的显示分钟
* 超过2小时 2 * 60 * 60 * 1000 ms 转换成小时 + 分钟数
*/
const formatDuration = (duration) => {
const formatDuration = duration => {
const minuteTime = 60 * 1000;
const hourTime = 60 * minuteTime;
const dayTime = 24 * hourTime;
@ -159,7 +159,8 @@ const formatDuration = (duration) => {
if (duration <= 60 * 1000) {
// 小于1分钟 返回几秒
return `${Math.floor(duration / 1000)}`;
} if (duration > dayTime) {
}
if (duration > dayTime) {
// 大于1天
if (minutes === 0) {
if (hours === 0) {
@ -171,7 +172,8 @@ const formatDuration = (duration) => {
}
// 分钟不是0 返回几天几时几分
return `${days}${hours}${minutes}`;
} if (duration > 2 * hourTime) {
}
if (duration > 2 * hourTime) {
// 大于2h
if (minutes === 0) {
// 分钟是0 返回几小时
@ -192,7 +194,7 @@ const formatDuration = (duration) => {
* 其余的显示分钟 { days: 0, hours: 0, minutes, seconds: 0 }
* 超过2小时 2 * 60 * 60 * 1000 ms 转换成{ days: 0, hours, minutes, seconds: 0 }
*/
const formatDurationToObject = (duration) => {
const formatDurationToObject = duration => {
const minuteTime = 60 * 1000;
const hourTime = 60 * minuteTime;
const dayTime = 24 * hourTime;
@ -247,14 +249,15 @@ const formatDurationToObject = (duration) => {
* @param {obj} 对象格式的时间 days, hours, minutes, seconds
* @return 时长的ms
*/
const formatObjectTimeToMs = (days = 0, hours = 0, minutes = 0, seconds = 0) => days * 24 * 60 * 60 * 1000 + hours * 60 * 60 * 1000 + minutes * 60 * 1000 + seconds * 1000;
const formatObjectTimeToMs = (days = 0, hours = 0, minutes = 0, seconds = 0) =>
days * 24 * 60 * 60 * 1000 + hours * 60 * 60 * 1000 + minutes * 60 * 1000 + seconds * 1000;
/**
* 计算过滤 周期
* @param {string} time 周期字符串
* @return {string} cycle 周期英文字符串
*/
const computeCycle = (time) => {
const computeCycle = time => {
// 加载下一个周期的任务
let cycle = 'day';
switch (time) {
@ -307,7 +310,7 @@ const formatStartTimeToCycleTime = (cycle, time) => {
* @param {number} leftTime 剩余时间ms
* @returns { num: 显示的数字, time: 演示器演示时长 }
*/
const computeDurationText = (leftTime) => {
const computeDurationText = leftTime => {
try {
if (leftTime < 0) {
return {
@ -315,15 +318,7 @@ const computeDurationText = (leftTime) => {
time: null,
};
}
const {
years,
months,
days,
hours,
minutes,
seconds,
milliseconds,
} = dayjs.duration(leftTime).$d;
const { years, months, days, hours, minutes, seconds, milliseconds } = dayjs.duration(leftTime).$d;
let num = 0;
let time = 1000;

Loading…
Cancel
Save