temp #31

Merged
wally merged 7 commits from temp into develop 4 years ago
  1. 3
      .gitignore
  2. 9
      CHANGELOG.md
  3. 21244
      package-lock.json
  4. 3
      package.json
  5. 22
      src/components/Globals/Globals.vue
  6. 133
      src/components/Plugin/Plugin.vue
  7. 31
      src/components/Roles/Roles.vue
  8. 8
      src/components/TimeLine/TimeLine.vue
  9. 11
      src/components/TimeLine/component/TaskTools.vue
  10. 58
      src/components/TimeLine/component/TimeBox.vue
  11. 12
      src/components/Title/Title.vue
  12. 24
      src/config/time.js
  13. 49
      src/pages/pinch/pinch.vue
  14. 62
      src/pages/plugin-test/plugin-test.vue
  15. 157
      src/pages/project/project.vue
  16. 73
      src/pages/rich-text/rich-text.vue
  17. 13
      src/plugins/p-task-description/p-task-description.vue
  18. 24
      src/plugins/p-task-duration-delay/p-task-duration-delay.vue
  19. 15
      src/plugins/p-task-start-time-delay/p-task-start-time-delay.vue
  20. 13
      src/plugins/p-task-title/p-task-title.vue
  21. 6
      src/store/project/actions.js
  22. 2
      src/store/project/mutations.js
  23. 1
      src/store/project/state.js
  24. 44
      src/store/task/actions.js
  25. 13
      src/store/task/getters.js
  26. 17
      src/store/task/mutations.js
  27. 12
      src/store/task/state.js
  28. 2
      src/store/user/actions.js
  29. 2
      src/utils/tall.js

3
.gitignore

@ -12,6 +12,9 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
yarn.lock
package-lock.json
# Editor directories and files
.project
.idea

9
CHANGELOG.md

@ -1,4 +1,4 @@
# 0.1.0 (2021-07-29)
# 0.1.0 (2021-07-30)
### 🌟 新功能
范围|描述|commitId
@ -16,6 +16,7 @@
富文本插件 | 富文本插件demo测试 | ed3d644
- | 引入dayjs | 29b8b93
- | 提交到本地 | 9cbe411
- | 插件参数处理调整 | a3e68d3
- | 插件数据获取 | 5b91bdc
- | 日常任务插件调整 | c1881f9
- | 时间基准线,默认插件 | a33ba1e
@ -52,6 +53,9 @@
### 🐛 Bug 修复
范围|描述|commitId
--|--|--
plugin | 插件解析机制完善 | 0f5a27d
role | 切换角色的逻辑修正完善 | 4ae534f
task任务逻辑完善 | 减少初始global及regular的不必要请求 | bd4bd38
- | 上下滑动加载定期任务 | 4090d89
- | 上下滚动时间轴 | d533a01
- | 下拉加载定期任务传参,时间格式化修改 | 0b95a0e
@ -85,8 +89,11 @@
范围|描述|commitId
--|--|--
- | project 代码健壮性完善 | a3202c5
store/home | 删除store/home | db8a3b4
task beginTime | 格式化任务开始时间 | fbc0301
template | eslint prettier sass uview tailwindcss | 9c966a1
- | 下滑时间轴添加备注 | 4fd20e3
- | 删除多余的技术验证界面 | 542ae5b
- | 界面样式调整 | 4367249
- | 重构store分层 | 5f6fff8

21244
package-lock.json

File diff suppressed because it is too large

3
package.json

@ -1,5 +1,5 @@
{
"name": "tall-mui-cli",
"name": "TALL",
"version": "0.1.0",
"private": true,
"scripts": {
@ -8,6 +8,7 @@
"lint": "vue-cli-service lint",
"fix": "vue-cli-service lint --fix",
"dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode development",
"dev:h5-pro": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode production",
"build:h5-test": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode development",
"build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode production",
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",

22
src/components/Globals/Globals.vue

@ -1,20 +1,21 @@
<template>
<view class="m-2">
<view class="m-2" v-if="globals && globals.length">
<u-card :show-foot="false" :show-head="false" :style="{ height: isShrink ? '106rpx' : '340rpx' }" border-radius="25" margin="0">
<view slot="body">
<scroll-view :scrollY="true" :style="{ height: isShrink ? '50rpx' : '280rpx' }">
<skeleton :banner="false" :loading="!tasks.length" :row="4" animate class="u-line-2 skeleton"></skeleton>
<skeleton :banner="false" :loading="!globals.length" :row="4" animate class="u-line-2 skeleton"></skeleton>
<view class="grid gap-2">
<template v-for="item in tasks">
<template v-for="item in globals">
<template v-if="item.plugins">
<template v-for="pluginArr in item.plugins">
<template class="p-0 u-col-between" v-if="pluginArr.length">
<Plugin
:class="getClass(plugin.col, plugin.row)"
:item="item"
:task="item"
:key="plugin.pluginTaskId"
:pluginId="plugin.pluginId"
:styleType="plugin.styleType || 0"
:plugin-task-id="plugin.pluginTaskId"
:plugin-id="plugin.pluginId"
:style-type="plugin.styleType || 0"
v-for="plugin in pluginArr"
/>
</template>
@ -29,13 +30,13 @@
</template>
<script>
import { mapState } from 'vuex';
import { mapGetters, mapState } from 'vuex';
import Skeleton from '@/components/Skeleton/Skeleton';
export default {
name: 'Global',
components: { Skeleton },
props: { tasks: { type: Array, default: () => [] } },
data() {
return {
// loading: true,
@ -43,7 +44,10 @@ export default {
};
},
computed: mapState('task', ['isShrink']),
computed: {
...mapState('task', ['isShrink']),
...mapGetters('task', ['globals']),
},
methods: {
getClass(col, row) {

133
src/components/Plugin/Plugin.vue

@ -1,72 +1,113 @@
<template>
<view class="u-font-14">
<view style="height: 100%" v-if="pluginContent">
<view v-if="pluginContent.html">
<view style="height: 100%" v-html="pluginContent.html"></view>
</view>
<view v-else>
<view v-if="item && item.name">
<p-task-title :item="item" v-if="pluginId === '1'" />
<p-task-description :item="item" v-if="pluginId === '2'" />
<p-task-duration-delay :item="item" v-if="pluginId === '3'" />
<p-task-start-time-delay :item="item" />
<!-- <p-task-start-time-delay :item="item" v-if="pluginId === '4'" /> -->
<p-deliverable :item="item" v-if="pluginId === '5'" />
<p-subtasks :item="item" v-if="pluginId === '6'" />
<p-subproject :item="item" v-if="pluginId === '7'" />
<p-task-countdown :item="item" v-if="pluginId === '8'" />
</view>
</view>
<view class="u-font-14" style="height: 100%">
<view v-if="pluginContent">
<view
style="height: 100%"
:data-uid="userId"
:data-pid="projectId"
:data-did="task.detailId"
:data-rid="roleId"
:data-tid="task.id"
:data-tname="task.name"
:data-pstart="task.planStart"
:data-rstart="task.realStart"
:data-pdu="task.planDuration"
:data-rdu="task.realDuration"
v-html="pluginContent"
></view>
</view>
<view v-else>
<p-task-title :name="task.name" v-if="pluginId === '1'" />
<p-task-description :text="task.description" v-if="pluginId === '2'" />
<p-task-duration-delay :realDuration="task.realDuration" :planDuration="task.planDuration" v-if="pluginId === '3'" />
<p-task-start-time-delay :realStart="task.realStart" :planStart="task.planStart" v-if="pluginId === '4'" />
<!-- <p-task-start-time-delay :task="task" v-if="pluginId === '4'" /> -->
<!-- <p-deliverable :task="task" v-if="pluginId === '5'" /> -->
<!-- <p-subtasks :task="task" v-if="pluginId === '6'" /> -->
<!-- <p-subproject :task="task" v-if="pluginId === '7'" /> -->
<!-- <p-task-countdown :task="task" v-if="pluginId === '8'" /> -->
</view>
</view>
</template>
<script>
import { mapGetters, mapState } from 'vuex';
export default {
name: 'Plugin',
props: {
item: {
default: () => {},
type: Object,
},
pluginId: {
default: '1',
type: String,
},
styleType: {
default: 0,
type: Number,
},
pluginTaskId: {
default: '0',
type: String,
},
task: { default: () => {}, type: Object },
pluginId: { default: '1', type: String },
styleType: { default: 0, type: Number },
pluginTaskId: { default: '', type: String },
},
data() {
return { pluginContent: null };
},
async created() {
await this.getPlugin();
let domList = Array.from(document.getElementsByTagName('script'));
const index = domList.findIndex(item => item.id === `p${this.pluginContent.pluginId}`);
if (this.pluginContent.js && index === -1) {
var scriptDom = document.createElement('script');
scriptDom.id = `p${this.pluginContent.pluginId}`;
scriptDom.innerHTML = this.pluginContent.js;
document.body.append(scriptDom);
}
computed: {
...mapGetters('user', ['userId']),
...mapGetters('project', ['projectId']),
...mapState('role', ['roleId']),
},
created() {
this.getPlugin();
},
methods: {
//
async getPlugin() {
const { pluginId, styleType } = this;
const res = await this.$u.api.getOtherPlugin({
const data = await this.$u.api.getOtherPlugin({
pluginId,
styleType,
});
this.pluginContent = res;
if (!data || !data.id) return;
const reg = /data-root=["|']?(\w+)["|']?/gi;
// console.log(data.html);
if (data.html) {
// data-root=xxx xxx pluginTaskId
if (reg.test(data.html)) {
const uuid = RegExp.$1;
// console.log('uuid: ', uuid, `p${this.pluginTaskId}`);
const str = data.html.replaceAll(uuid, `p${this.pluginTaskId}`);
this.pluginContent = str;
} else {
this.pluginContent = data.html;
}
}
// console.log(this.pluginContent);
if (data.js) {
if (reg.test(data.js)) {
const uuid = RegExp.$1;
const str = data.js.replaceAll(uuid, `p${this.pluginTaskId}`);
this.handleDom(str);
} else {
this.handleDom(data.js);
}
}
},
// script dom
handleDom(js) {
const { pluginId } = this;
let domList = Array.from(document.getElementsByTagName('script'));
const index = domList.findIndex(item => item.id === `p${pluginId}`);
if (js && index === -1) {
const scriptDom = document.createElement('script');
scriptDom.id = `p${pluginId}`;
scriptDom.setAttribute('data-type', 'plugin');
scriptDom.innerHTML = js;
this.$nextTick(() => {
document.body.append(scriptDom);
});
}
},
},
};

31
src/components/Roles/Roles.vue

@ -3,7 +3,7 @@
<view class="home-box u-skeleton">
<scroll-view :enable-flex="true" :scroll-left="scrollLeft" :throttle="false" scroll-with-animation scroll-x>
<view class="tab-box">
<view :key="index" @click="changeIndex(item.id, index)" class="tab-item" v-for="(item, index) in roles">
<view :key="index" @click="changeRole(item.id, index)" class="tab-item" v-for="(item, index) in roles">
<view :class="setColor(item.mine, item.id)" class="tab-children u-skeleton-fillet u-font-14">{{ item.name }}</view>
</view>
</view>
@ -68,7 +68,7 @@ export default {
methods: {
...mapActions('task', ['handleRegularTask']),
...mapMutations('role', ['setRoleId']),
...mapMutations('task', ['setTasks']),
...mapMutations('task', ['setTasks', 'setPermanents', 'setDailyTasks', 'clearEndFlag']),
//
setCurrentRole(index) {
@ -91,17 +91,36 @@ export default {
},
//
async changeIndex(id, index) {
// projectroleId
// projectroleId
changeRole(id, index) {
try {
// script
this.clearPluginScript();
this.setRoleId(id);
//index
this.setCurrentRole(index);
//
this.setTasks();
//
await this.$emit('getTasksByRole');
//
this.setPermanents([]);
this.setDailyTasks([]);
//
//
this.clearEndFlag();
} catch (error) {
console.log('error: ', error);
console.log('role.vue changeRole error: ', error);
}
},
// script
clearPluginScript() {
console.log('clearPluginScript: ');
const scripts = document.querySelectorAll('script[data-type=plugin]');
for (let i = 0; i < scripts.length; i++) {
document.body.removeChild(scripts[i]);
}
},

8
src/components/TimeLine/TimeLine.vue

@ -13,11 +13,11 @@
id="scroll"
>
<!-- 时间轴 -->
<u-divider bg-color="#f3f4f6" class="pt-5" fontSize="14px" v-if="topEnd">到顶啦</u-divider>
<!-- <u-divider bg-color="#f3f4f6" class="pt-5" fontSize="14px" v-if="topEnd">到顶啦</u-divider> -->
<TimeBox />
<u-divider bg-color="#f3f4f6" class="pb-5" fontSize="14px" v-if="bottomEnd">到底啦</u-divider>
<!-- <u-divider bg-color="#f3f4f6" class="pb-5" fontSize="14px" v-if="bottomEnd">到底啦</u-divider> -->
</scroll-view>
</template>
@ -57,9 +57,6 @@ export default {
async handleScrollTop() {
if (this.topEnd) return;
const startTime = this.tasks[0].planStart - 0;
console.log('this.topEnd: ', this.topEnd);
console.log('this.tasks: ', this.tasks);
console.log('this.tasks[0].plugins: ', this.tasks[0].plugins);
if (this.tasks[0].plugins && this.tasks[0].plugins.length === 0 && !this.topEnd) {
//
console.log('没有数据时: ');
@ -99,7 +96,6 @@ export default {
const startTime = this.tasks[this.tasks.length - 1].planStart - 0;
if (this.tasks[0].plugins && this.tasks[0].plugins.length === 0 && !this.topEnd) {
//
console.log('没有数据时: ');
const addTasks = [
{
panel: {},

11
src/components/TimeLine/component/TaskTools.vue

@ -0,0 +1,11 @@
<template>
<view class="flex justify-between" style="min-width: 90px">
<u-icon custom-prefix="custom-icon" name="C-bxl-redux" size="17px"></u-icon>
<u-icon custom-prefix="custom-icon" name="attachment" size="21px"></u-icon>
<u-icon custom-prefix="custom-icon" name="moneycollect" size="20px"></u-icon>
</view>
</template>
<script>
export default {};
</script>

58
src/components/TimeLine/component/TimeBox.vue

@ -1,19 +1,16 @@
<template>
<view class="column">
<view :key="index" v-for="(item, index) in tasks">
<view :key="index" v-for="(task, index) in tasks">
<view class="flex">
<TimeStatus :content="JSON.stringify(item.process)" :status="item.process" />
<TimeStatus :content="JSON.stringify(task.process)" :status="task.process" />
<view class="flex items-center justify-between flex-1 ml-2 task-column">
<view>
<span>{{ $moment(+item.planStart).format('MM-DD HH:mm') }}</span>
</view>
<view>
<view class="flex justify-between" style="min-width: 90px">
<u-icon custom-prefix="custom-icon" name="C-bxl-redux" size="17px"></u-icon>
<u-icon custom-prefix="custom-icon" name="attachment" size="21px"></u-icon>
<u-icon custom-prefix="custom-icon" name="moneycollect" size="20px"></u-icon>
</view>
<span>{{ $moment(+task.planStart).format(startTimeFormat) }}</span>
</view>
<!-- 任务功能菜单 -->
<TaskTools />
</view>
</view>
<view class="border-l-2 border-gray-300 plugin">
@ -21,27 +18,30 @@
<u-card
:show-foot="false"
:show-head="false"
:style="{ height: setHeight(item.panel) }"
@click="changeTimeNode(item.planStart)"
:style="{ height: setHeight(task.panel) }"
@click="onClickTask(+task.planStart)"
class="h-16"
margin="0"
v-if="item.plugins"
v-if="task.plugins && task.plugins.length"
>
<!-- 任务面板插件 -->
<view slot="body">
<view v-if="!item.plugins.length">
<!-- TODO: 逻辑不完善 -->
<view v-if="!task.plugins.length">
<skeleton :banner="false" :loading="true" :row="4" animate class="mt-2 u-line-2 skeleton"></skeleton>
</view>
<view class="p-0 u-col-between" v-else>
<view :key="pIndex" v-for="(p, pIndex) in item.plugins">
<view class="grid gap-2" v-if="p.length">
<view :key="pIndex" v-for="(row, pIndex) in task.plugins">
<view class="grid gap-2" v-if="row.length">
<Plugin
:class="getClass(plugin.col, plugin.row)"
:item="item"
:task="task"
:key="plugin.pluginTaskId"
:plugin-task-id="plugin.pluginTaskId"
:pluginId="plugin.pluginId"
:styleType="styleType || 0"
v-for="plugin in p"
v-for="plugin in row"
/>
</view>
</view>
@ -51,28 +51,32 @@
</view>
</view>
</view>
<!-- 局部弹框操作栏 -->
<Tips />
</view>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import TimeStatus from './TimeStatus.vue';
import { mapState, mapMutations, mapGetters, mapActions } from 'vuex';
import Skeleton from '@/components/Skeleton/Skeleton';
import TimeStatus from './TimeStatus.vue';
import TaskTools from './TaskTools.vue';
export default {
name: 'TimeBox',
components: { TimeStatus, Skeleton },
components: { TimeStatus, Skeleton, TaskTools },
data() {
return { currentComponent: '', styleType: 0 };
},
computed: {
...mapState('role', ['roleId']),
...mapState('task', ['timeNode', 'timeUnit', 'tasks', 'taskLoading']),
...mapState('task', ['timeUnit', 'tasks', 'taskLoading']),
...mapGetters('task', ['startTimeFormat']),
},
methods: {
...mapActions('task', ['getGlobal']),
...mapMutations('task', ['setTipsContent', 'setTipsContent', 'setTimeNode']),
//
@ -84,9 +88,13 @@ export default {
}
},
// store
changeTimeNode(time) {
this.setTimeNode(time);
/**
* 点击了定期任务的面板 更新可变的日常任务
* @param {number} planStart 任务计划开始时间
*/
onClickTask(planStart) {
const param = { roleId: this.roleId, timeNode: planStart, timeUnit: this.timeUnit };
this.getGlobal(param);
},
//

12
src/components/Title/Title.vue

@ -1,8 +1,8 @@
<template>
<view>
<u-navbar :is-back="false" back-text="返回">
<view class="flex justify-center flex-1">
<view>我是标题</view>
<u-navbar :is-back="false" back-text="返回" class="overflow-hidden">
<view class="flex justify-start px-3 font-bold" style="width: 460rpx">
<view class="truncate">{{ project.name }}</view>
</view>
<view class="mr-2" slot="right">
<u-icon class="m-1" name="xuanzhong2" custom-prefix="custom-icon" size="20px" @click="lwbs"></u-icon>
@ -15,11 +15,9 @@
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'Title',
data() {
return { title: '加载中...' };
},
name: 'ProjectTitle',
computed: mapState('project', ['project']),

24
src/config/time.js

@ -1,17 +1,17 @@
export default {
timeUnits: [
// 时间颗粒度
{ id: 0, value: '毫秒' },
{ id: 1, value: '秒' },
{ id: 2, value: '分' },
{ id: 3, value: '时' },
{ id: 4, value: '天' },
{ id: 5, value: '周' },
{ id: 6, value: '月' },
{ id: 7, value: '季度' },
{ id: 8, value: '年' },
{ id: 9, value: '年代' },
{ id: 10, value: '世纪' },
{ id: 11, value: '千年' },
{ id: 0, value: '毫秒', format: 'x', cycle: 'YY-M-D HH:mm:ss' },
{ id: 1, value: '秒', format: 'x', cycle: 'YY-M-D HH:mm:ss' },
{ id: 2, value: '分', format: 'ss', cycle: 'YY-M-D HH:mm' },
{ id: 3, value: '时', format: 'mm', cycle: 'YY-M-D HH时' },
{ id: 4, value: '天', format: 'D日 HH:mm', cycle: 'YY-M-D' },
{ id: 5, value: '周', format: 'D日 HH:mm', cycle: '' },
{ id: 6, value: '月', format: 'D日 H:m', cycle: 'YYYY年' },
{ id: 7, value: '季度', format: '', cycle: 'YYYY年' },
{ id: 8, value: '年', format: 'YYYY', cycle: '' },
{ id: 9, value: '年代', format: '', cycle: '' },
{ id: 10, value: '世纪', format: '', cycle: '' },
{ id: 11, value: '千年', format: '', cycle: '' },
],
};

49
src/pages/pinch/pinch.vue

@ -1,49 +0,0 @@
<template>
<view class="container flex flex-row items-center justify-center">
<image
class="w-1/2"
mode="aspectFit"
src="https://lupic.cdn.bcebos.com/20200412/3026529107_14_800_566.jpg"
v-finger:pinch="handlePinch"
v-finger:multipoint-start="handlePinchStart"
:style="{ transform: `scale(${scale})` }"
id="image"
></image>
</view>
</template>
<script>
export default {
data() {
return {
initScale: 1,
scale: 1,
element: null,
};
},
mounted() {
this.element = document.getElementById('image');
},
methods: {
handlePinchStart() {
console.log(this.element.style.transform);
// eslint-disable-next-line no-useless-escape
const reg = /scale\(([0-9]*[\.]?[0-9]*)\)/gi;
const scale = this.element.style.transform;
if (reg.test(scale)) {
this.initScale = RegExp.$1;
console.log(this.initScale);
}
// this.scale = this.element.scaleX;
},
handlePinch(event) {
console.log(typeof event.zoom, typeof this.initScale, this.initScale);
this.scale = this.initScale * event.zoom;
console.log('this.scale:', this.scale);
},
},
};
</script>

62
src/pages/plugin-test/plugin-test.vue

@ -1,62 +0,0 @@
<template>
<view>
<view v-for="(item, index) in iframes" :key="index" style="height: 500rpx" class="p-1">
<!-- <web-view :src="item"></web-view> -->
<iframe :src="item" frameborder="0" class="block w-full h-full" :id="`iframe${index}`"></iframe>
</view>
</view>
</template>
<script>
/* eslint-disable max-len */
const iframes = [
'https://uniapp.dcloud.io/static/web-view.html',
'https://baidu.com',
'https://uland.taobao.com/semm/tbsearch?refpid=mm_26632258_3504122_32554087&keyword=%E5%A5%B3%E8%A3%85&clk1=ad91ec4906f3ffe8328566a1bf604aef&upsId=ad91ec4906f3ffe8328566a1bf604aef',
'https://m.jd.com/',
'https://www.ccsens.com',
'https://www.tall.wiki/wl/1',
'https://h5.m.jd.com/active/yard-channel/index.html?themeId=24883&babelChannel=356440&innerLink=%5B%7B%22matId%22%3A%223203085%22%7D%2C%7B%22matId%22%3A%223205226%22%7D%5D&themeStyle=0&innerIndex=1',
'https://mitem.jd.hk/product/3205226.html?pdtk=ZenDw7dK%2FC8XmpuZbhgbkp%2BSbyLL5R0S14AvHWdeeAL2Z36jPKDzWg%2BYBNa0HgvE&_fd=jdm&sid=null',
'https://shop.m.jd.com/shopv2/mzpage?shopId=1000015205&venderId=1000015205&skuId=3205226&categoryId=1319_1523_7052&sceneval=2&jxsid=16243458685744852366&_fd=jdm&_fd=jdm',
'https://www.tall.wiki/wl/2',
'https://www.tall.wiki/wl/3',
'https://www.tall.wiki/wl/4',
'https://www.tall.wiki/wl/5',
'https://www.tall.wiki/wl/7',
'https://www.tall.wiki/wl/6',
];
/* eslint-enable max-len */
export default {
data() {
return { iframes, createdTime: 0, mountedTime: 0 };
},
created() {
this.createdTime = Date.now();
console.error('created:', new Date().toLocaleString());
},
mounted() {
this.mountedTime = Date.now();
console.error('mounted:', new Date().toLocaleString());
this.$nextTick(this.init);
},
methods: {
init() {
this.iframes.forEach((item, index) => {
const element = document.getElementById(`iframe${index}`);
element.addEventListener(
'load',
() => {
const now = Date.now();
console.error(`${index} ${item} 加载结束`, new Date().toLocaleString(), now - this.createdTime, now - this.mountedTime);
},
false,
);
});
},
},
};
</script>

157
src/pages/project/project.vue

@ -2,10 +2,15 @@
<view :style="{ height: height }" class="flex flex-col overflow-hidden u-font-14">
<!-- 标题栏 -->
<Title />
<view class="container flex flex-col flex-1 overflow-hidden bg-gray-100" style="margin: auto">
<!-- 角色栏 -->
<Roles @getTasksByRole="getTasksByRole" />
<Globals :tasks="allPlugins.concat(timePlugins)" />
<Roles />
<!-- 日常任务面板 -->
<Globals />
<!-- 定期任务面板 -->
<TimeLine @getTasks="getTasks" class="flex-1 overflow-hidden" ref="child" />
</view>
</view>
@ -16,7 +21,7 @@ import { mapState, mapMutations, mapActions } from 'vuex';
export default {
data() {
return { height: '', plugins: [], allPlugins: [], timePlugins: [] };
return { height: '' };
},
computed: {
@ -35,24 +40,25 @@ export default {
* 重新根据时间和角色查询普通日常任务
* 永久日常任务不发生改变
*/
async timeNode(val) {
if (val) {
timeNode(val) {
if (val && this.roleId) {
//
await this.getGlobal();
this.getGlobalData();
this.getInitTasks();
}
},
/**
* 当角色发生变化时
* 重新查询永久日常任务和普通日常任务
* 注意: 切换角色后 重新设置了时间基准点 时间基准点一定会变
* 所以监听时间基准点获取 可变日常任务即可 这里不用获取 避免重复获取
*/
async roleId(val) {
roleId(val) {
if (val) {
this.setTimeNode(new Date().getTime());
this.setTimeNode(Date.now());
//
await this.getPermanent();
//
await this.getGlobal();
this.getPermanent(val);
}
},
},
@ -65,7 +71,7 @@ export default {
...mapActions('user', ['getUserId']),
...mapActions('project', ['getProjectById']),
...mapActions('role', ['getRoles']),
...mapActions('task', ['handleRegularTask']),
...mapActions('task', ['getRegulars', 'getPermanent', 'getGlobal']),
...mapMutations('user', ['setToken']),
...mapMutations('project', ['setProject', 'setProjectName']),
...mapMutations('role', ['setInvisibleRoles', 'setVisibleRoles', 'setRoleId']),
@ -100,26 +106,25 @@ export default {
// id
await this.getRoles({ projectId: options.p });
this.setInitialRoleId(this.visibleRoles);
//
await this.getTasks({ queryType: 0 });
await this.getTasks({ queryType: 1 });
//
await this.getPermanent();
//
await this.getGlobal();
//
if (this.tasks && this.tasks.length) {
await this.getTasks({ timeNode: +this.tasks[0].planStart, queryType: 0, queryNum: 6 });
await this.getTasks({ timeNode: +this.tasks[this.tasks.length - 1].planStart, queryType: 1, queryNum: 6 });
}
}
} catch (error) {
console.error('project init function:', error);
}
},
// ||
async getInitTasks() {
//
await this.getTasks({ queryType: 0 });
await this.getTasks({ queryType: 1 });
//
if (this.tasks && this.tasks.length) {
this.getTasks({ timeNode: +this.tasks[0].planStart, queryType: 0, queryNum: 6 });
this.getTasks({ timeNode: +this.tasks[this.tasks.length - 1].planStart, queryType: 1, queryNum: 6 });
}
},
//
setInitialRoleId(visibleList) {
const index = visibleList.findIndex(item => item.mine);
@ -130,96 +135,34 @@ export default {
/**
* 根据时间基准点和角色查找定期任务
* @param {string} roleId 角色id
* @param {string} timeNode 时间基准点 默认当前
* @param {string} timeUnit 时间颗粒度 默认天
* @param {string} queryNum 查找颗粒度数量 默认3个
* @param {string} queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
* @param {object} query
* @param {string} query.roleId 角色id
* @param {string} query.timeNode 时间基准点 默认当前
* @param {string} query.timeUnit 时间颗粒度 默认天
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {string} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
async getTasks(query) {
try {
const { roleId, timeNode, timeUnit } = this;
const params = { roleId };
params.timeNode = query.timeNode || timeNode;
params.timeUnit = query.timeUnit || timeUnit;
params.queryNum = query.queryNum || 3;
params.queryType = query.queryType;
const res = await this.handleRegularTask(params);
query.queryType === 0 ? this.setUpTasks(res) : this.setDownTasks(res);
} catch (error) {
console.log('error: ', error);
}
},
/**
* 根据角色查找永久的日常任务
* @param {string} roleId 角色id
*/
async getPermanent() {
try {
this.allPlugins = [];
const res = await this.$u.api.getPermanent({ roleId: this.roleId });
// for (let item of res) {
// if (item.plugins) {
// this.allPlugins = this.allPlugins.concat(item.plugins);
// }
// }
this.allPlugins = res;
} catch (error) {
console.log('error: ', error);
}
},
/**
* 根据时间和角色查找日常任务
* @param {string} roleId 角色id
* @param {string} timeNode 时间基准点 默认当前
* @param {string} timeUnit 时间颗粒度 默认天
*/
async getGlobal() {
try {
this.timePlugins = [];
const { roleId, timeNode, timeUnit } = this;
const params = { roleId, timeNode, timeUnit };
const res = await this.$u.api.getGlobal(params);
// for (let task of res) {
// for (let item of task.plugins) {
// this.timePlugins.push(...item);
// }
// }
this.timePlugins = res;
this.setDailyTasks(res);
const params = {
roleId,
timeNode: query.timeNode || timeNode,
timeUnit: query.timeUnit || timeUnit,
queryNum: query.queryNum || 3,
queryType: query.queryType,
};
await this.getRegulars(params);
} catch (error) {
console.log('error: ', error);
}
},
//
async getTasksByRole() {
try {
await this.getTasks({ queryType: 0 });
await this.getTasks({ queryType: 1 });
//
const upQuery = {
timeNode: +this.tasks[0].planStart,
queryType: 0,
queryNum: 6,
};
await this.getTasks(upQuery);
//
// =+
const cycle = this.$t.time.computeCycle('天');
const timeNode = this.$t.time.add(+this.tasks[this.tasks.length - 1].planStart, 1, cycle).valueOf();
const downQuery = {
timeNode,
queryType: 1,
queryNum: 6,
};
await this.getTasks(downQuery);
} catch (error) {
console.log('error: ', error);
}
//
getGlobalData() {
const { roleId, timeNode, timeUnit } = this;
const param = { roleId, timeNode, timeUnit };
this.getGlobal(param);
},
},
};

73
src/pages/rich-text/rich-text.vue

@ -1,73 +0,0 @@
<template>
<view class="p-2">
<!-- <view v-if="!plugins">加载中...</view>
<template v-else>-->
<view class="my-3" id="container"></view>
<!-- </template> -->
</view>
</template>
<script>
export default {
data() {
return { plugins: null };
},
mounted() {
// window.openModal = function () {
// const modal = document.getElementById('modal');
// modal.style.display = 'block';
// alert('modal');
// };
this.getData();
},
methods: {
async getData() {
try {
const data = await this.$u.get('/tasks');
console.log(data);
this.plugins = [...data.plugins] || null;
this.renderDOM(this.plugins); // DOM
} catch (error) {
console.log('🚀 ~ file: rich-text.vue ~ line 33 ~ getData ~ error', error);
this.plugins = null;
}
},
/**
* 渲染DOM
* @param {Array | null} plugins 拿到的内置插件数据
*
* FIXME: 只处理了1个script标签的情况
* FIXME: 插件命名空间 作用域未处理
* FIXME: 插件关闭退出时, 应该移除相关的script代码
*/
renderDOM(plugins) {
if (!plugins || !plugins.length) return;
const element = document.getElementById('container');
// eslint-disable-next-line no-useless-escape
const reg = /<script\b[^>]*>([\s\S]*)<\/script>/gim;
let str = element.innerHTML;
for (let item of plugins) {
// console.log(reg.test(item), item.match(reg), RegExp.$1);
if (reg.test(item)) {
// code snippets script
const scriptElement = document.createElement('script');
const text = RegExp.$1;
try {
scriptElement.appendChild(document.createTextNode(text));
} catch (error) {
scriptElement.text = text;
}
document.body.appendChild(scriptElement); // script
str += item.replace(reg, ''); // script
} else {
str += `<div>${item}</div>`;
}
}
element.innerHTML = str;
},
},
};
</script>

13
src/plugins/p-task-description/p-task-description.vue

@ -1,20 +1,11 @@
<template>
<!-- 任务描述 -->
<view>{{ item.description }}</view>
<view>{{ text }}</view>
</template>
<script>
export default {
name: 'p-task-description',
props: { item: { type: Object, default: null } },
data() {
return {};
},
computed: {},
methods: {},
watch: {},
props: { text: { type: String, default: '' } },
};
</script>
<style></style>

24
src/plugins/p-task-duration-delay/p-task-duration-delay.vue

@ -1,28 +1,20 @@
<template>
<view v-if="item.realDuration && item.planDuration">
<view v-if="realDuration && planDuration">
<!-- 任务时长延迟插件 -->
<!-- 超时 -->
<span class="text-green-500 font-bold" v-if="+item.realDuration > +item.planDuration"
>+{{ $t.time.formatDuration(+item.realDuration - +item.planDuration) }}</span
>
<span class="font-bold text-green-500" v-if="+realDuration > +planDuration">
+{{ $t.time.formatDuration(+realDuration - +planDuration) }}
</span>
<!-- 延时 -->
<span class="text-red-500 font-bold" v-if="+item.realDuration < +item.planDuration"
>-{{ $t.time.formatDuration(+item.planDuration - +item.realDuration) }}</span
>
<span class="font-bold text-red-500" v-if="+realDuration < +planDuration">
-{{ $t.time.formatDuration(+planDuration - +realDuration) }}
</span>
</view>
</template>
<script>
export default {
name: 'p-task-duration-delay',
props: { item: { type: Object, default: null } },
data() {
return {};
},
computed: {},
methods: {},
watch: {},
props: { planDuration: { type: String, default: '0' }, realDuration: { type: String, default: '0' } },
};
</script>
<style></style>

15
src/plugins/p-task-start-time-delay/p-task-start-time-delay.vue

@ -1,23 +1,14 @@
<template>
<view v-if="item.realStart && item.planStart">
<view v-if="realStart && planStart">
<!-- 任务开始时间延迟插件 -->
<!-- 超时 -->
<span>{{ $t.time.formatDuration(+item.realStart - +item.planStart) }}</span>
<span>{{ $t.time.formatDuration(+realStart - +planStart) }}</span>
</view>
</template>
<script>
export default {
name: 'p-task-start-time-delay',
props: { item: { type: Object, default: null } },
data() {
return {};
},
computed: {},
methods: {},
watch: {},
props: { realStart: { type: String, default: '0' }, planStart: { type: String, default: '0' } },
};
</script>
<style></style>

13
src/plugins/p-task-title/p-task-title.vue

@ -1,20 +1,11 @@
<template>
<!-- 任务名插件 -->
<view>{{ item.name }}</view>
<view>{{ name }}</view>
</template>
<script>
export default {
name: 'p-task-title',
props: { item: { type: Object, default: null } },
data() {
return {};
},
computed: {},
methods: {},
watch: {},
props: { name: { type: String, default: '' } },
};
</script>
<style></style>

6
src/store/project/actions.js

@ -6,9 +6,9 @@ const actions = {
*/
async getProjectById({ commit }, params) {
try {
const res = await uni.$u.api.findProjectById(params);
commit('setProject', res);
return res;
const data = await uni.$u.api.findProjectById(params);
commit('setProject', data);
return data;
} catch (error) {
throw error || '获取项目信息失败';
}

2
src/store/project/mutations.js

@ -5,7 +5,7 @@ const mutations = {
* @param { object } data
*/
setProject(state, data) {
state.project = { ...data };
state.project = data || { name: '加载中...' };
},
/**

1
src/store/project/state.js

@ -1,3 +1,4 @@
/* eslint-disable */
const state = {
project: { name: '加载中...' }, // 当前项目信息
};

44
src/store/task/actions.js

@ -1,14 +1,48 @@
const actions = {
/**
* 根据时间基准点和角色查找定期任务
* 根据角色查找永久的日常任务
* @param {*} commit
* @param {string} roleId 角色id
* @param {string} timeNode 时间基准点 默认当前
* @param {string} timeUnit 时间颗粒度 默认天
*/
async getPermanent({ commit }, roleId) {
try {
const data = await uni.$u.api.getPermanent({ roleId });
commit('setPermanents', data);
} catch (error) {
console.log('task actions getPermanent error: ', error);
}
},
/**
* 根据时间和角色查找日常任务
* @param {*} commit
* @param {object} param 请求参数 roleId, timeNode, timeUnit
*/
async getGlobal({ commit }, param) {
try {
const data = await uni.$u.api.getGlobal(param);
commit('setDailyTasks', data);
} catch (error) {
console.log('task actions getGlobal error: ', error);
}
},
/**
* 根据时间基准点和角色查找定期任务
* @param {object} param 查询参数
* @param {number} param.queryType 必填 0 -> 向上 1 -> 向下
*/
// eslint-disable-next-line
async handleRegularTask({ commit }, param) {
async getRegulars({ commit, state }, param) {
try {
return await uni.$u.api.getRegularTask(param);
// 向上查 且 上边没数据了 不查
if (param.queryType === 0 && state.topEnd) return;
// 向下查 且 下边美术家了 不查
if (param.queryType === 1 && state.bottomEnd) return;
const data = await uni.$u.api.getRegularTask(param);
// 0 -> 向上 1 -> 向下
// data 有无的判断在mutations里
param.queryType === 0 ? commit('setUpTasks', data) : commit('setDownTasks', data);
} catch (error) {
throw error || '获取定期任务失败';
}

13
src/store/task/getters.js

@ -1,3 +1,14 @@
const getters = {};
const getters = {
// 所有的日常任务 永久 + 可变 日常任务
globals({ dailyTasks, permanents }) {
return [...permanents, ...dailyTasks];
},
// 计算任务开始时间的格式
startTimeFormat({ timeUnit }) {
const target = uni.$t.timeConfig.timeUnits.find(item => item.id === timeUnit);
return target.format || 'D日 HH:mm';
},
};
export default getters;

17
src/store/task/mutations.js

@ -96,7 +96,7 @@ const mutations = {
if (!data || !data.length) {
state.bottomEnd = true;
}
if (!state.tasks[0].name) {
if (!state.tasks[0] || !state.tasks[0].name) {
state.tasks = [...data];
} else {
state.tasks = [...state.tasks.concat(data)];
@ -137,6 +137,21 @@ const mutations = {
setDailyTasks(state, data) {
state.dailyTasks = data || [];
},
/**
* 设置永久固定任务
* @param {object} state
* @param {array} tasks 服务端查询到的永久日常任务书籍
*/
setPermanents(state, tasks) {
state.permanents = tasks || [];
},
// 清空标志位 如切换角色等使用
clearEndFlag(state) {
state.topEnd = false;
state.bottomEnd = false;
},
};
export default mutations;

12
src/store/task/state.js

@ -9,7 +9,12 @@ const state = {
status: 0, // 点击了时间轴上的哪种样式,默认点击了开始
tipsContent: '', // 提示框内的内容,需要传入
timeNode: new Date().getTime(), // 时间基准点
timeUnit: 4, // // 时间颗粒度
timeUnit: 4, // 时间颗粒度
topEnd: false, // 时间轴向上查任务到顶了
bottomEnd: false, // 时间轴向下查任务到底了
permanents: [], // 永久日常任务
dailyTasks: [], // 日常任务
// 定期任务
tasks: [
{
panel: {},
@ -26,10 +31,7 @@ const state = {
plugins: [],
planStart: uni.$t.time.add(+new Date().getTime(), 1, 'day').valueOf(),
},
], // 定期任务
topEnd: false, // 时间轴向上查任务到顶了
bottomEnd: false, // 时间轴向下查任务到底了
dailyTasks: [], // 日常任务
],
};
export default state;

2
src/store/user/actions.js

@ -11,7 +11,7 @@ const actions = {
commit('setUser', res);
return res;
} catch (error) {
throw error || '获取个人信息失败';
uni.$t.ui.showToast(error.msg || '获取个人信息失败');
}
},
};

2
src/utils/tall.js

@ -1,4 +1,5 @@
import app from '@/config/app.js';
import timeConfig from '@/config/time';
import zIndex from '@/config/zIndex.js';
import plugin from '@/config/plugin.js';
import storage from '@/utils/storage.js';
@ -11,6 +12,7 @@ const $t = {
plugin, // 插件相关配置信息
storage, // 本地存储storage封装
time, // 时间处理
timeConfig, // 时间相关配置
ui, // ui界面提示相关
};

Loading…
Cancel
Save