forked from ccsens_fe/tall-mui-3
Compare commits
85 Commits
Author | SHA1 | Date |
---|---|---|
|
2e908481c4 | 4 years ago |
|
ecd6658d15 | 4 years ago |
|
c57f9863b8 | 4 years ago |
|
ab24b333e2 | 4 years ago |
|
131ce0f201 | 4 years ago |
|
9b542fcb1b | 4 years ago |
|
9ab680e396 | 4 years ago |
|
c615924231 | 4 years ago |
|
59897c2a7b | 4 years ago |
|
ae3675b1eb | 4 years ago |
|
053be5bba5 | 4 years ago |
|
64af9369da | 4 years ago |
|
f601f3b02b | 4 years ago |
|
d653f9a251 | 4 years ago |
|
69677cecd4 | 4 years ago |
|
e68e633568 | 4 years ago |
|
e5a13c89df | 4 years ago |
|
80eb4c5e7b | 4 years ago |
|
1c23019334 | 4 years ago |
|
e1a17c52bd | 4 years ago |
|
e942887436 | 4 years ago |
|
3b400df8f9 | 4 years ago |
|
1977c00f1d | 4 years ago |
|
87ce0f7e06 | 4 years ago |
|
c8ee189c81 | 4 years ago |
|
6aa728b1b7 | 4 years ago |
|
d8672398ca | 4 years ago |
|
a9ead1abf0 | 4 years ago |
|
2f84ae1672 | 4 years ago |
|
5ea2fe40ed | 4 years ago |
|
4628301183 | 4 years ago |
|
7fc959d4e2 | 4 years ago |
|
25c78b856f | 4 years ago |
|
6a422f623e | 4 years ago |
|
2033b55c02 | 4 years ago |
|
959ae0537a | 4 years ago |
|
ce1855aedd | 4 years ago |
|
7b0a54876e | 4 years ago |
|
032d83ce66 | 4 years ago |
|
efbc67959b | 4 years ago |
|
eb2c4ba4d2 | 4 years ago |
|
9f8755671f | 4 years ago |
|
dab3d44ae9 | 4 years ago |
|
3717dd3f6b | 4 years ago |
|
8903854481 | 4 years ago |
|
4524d4a8c9 | 4 years ago |
|
4c2de55b68 | 4 years ago |
|
322b0fbcf4 | 4 years ago |
|
b8d5aeb4e2 | 4 years ago |
|
be2f3cd448 | 4 years ago |
|
7020c78b3b | 4 years ago |
|
3d9bac5022 | 4 years ago |
|
7c51a9eb9d | 4 years ago |
|
c33169d016 | 4 years ago |
|
ebe0031f34 | 4 years ago |
|
37b51bcf76 | 4 years ago |
|
9d92be5aec | 4 years ago |
|
f02b0e7d29 | 4 years ago |
|
f7d71081ae | 4 years ago |
|
5cf7d08066 | 4 years ago |
|
6e0bc4627e | 4 years ago |
|
d64131272c | 4 years ago |
|
b351b67b4b | 4 years ago |
|
858429eefe | 4 years ago |
|
15485a0ac5 | 4 years ago |
|
c864f91e31 | 4 years ago |
|
7781c7b657 | 4 years ago |
|
4d9050b32f | 4 years ago |
|
a427250a13 | 4 years ago |
|
91782556af | 4 years ago |
|
93ffea2439 | 4 years ago |
|
204f66c066 | 4 years ago |
|
a0b491b38c | 4 years ago |
|
52e0352ffe | 4 years ago |
|
af6c91e0ad | 4 years ago |
|
cefc0ebc84 | 4 years ago |
|
5a108563cb | 4 years ago |
|
b22a3663fb | 4 years ago |
|
81032bacb5 | 4 years ago |
|
7d4edfc92b | 4 years ago |
|
037adb2575 | 4 years ago |
|
e992343257 | 4 years ago |
|
63e1f0d81f | 4 years ago |
|
b0d3a362a3 | 4 years ago |
|
33889679f8 | 4 years ago |
99 changed files with 6394 additions and 1842 deletions
@ -1,204 +1,281 @@ |
|||||
# 0.1.0 (2021-08-18) |
# 0.1.0 (2021-12-27) |
||||
|
|
||||
### 🌟 新功能 |
### 🌟 新功能 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
calendar, tall.js | 上下滑动切换日历的模式,tall.js中domain根据环境变量切换 | [364e25d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/364e25d) |
- | "交付物" | ecd6658 |
||||
- | db store | [6414c4f](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/6414c4f) |
- | 绑定手机号 | 52e0352 |
||||
default plugin | 添加默认插件;项目列表;全局项目最大高度设置 | [ed1d87b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ed1d87b) |
- | 标题栏变化 | 3898cfe |
||||
- | indexedDB | [687394e](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/687394e) |
- | 标题栏变化 | c0fcd9d |
||||
pinch | alloy finger实现图片的pinch放大缩小 | [de01343](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/de01343) |
- | 标题栏角色栏全局任务组件新建 | 0500cb4 |
||||
plugin | 插件添加了token及param参数 | [aeb0292](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/aeb0292) |
- | 插件参数处理调整 | a3e68d3 |
||||
- | post 封装 | [da52e94](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/da52e94) |
- | 插件数据获取 | 5b91bdc |
||||
- | tall插件封装 | [1bcb920](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/1bcb920) |
- | 存token | b8a178d |
||||
task status | 任务状态切换未完 | [7ffd135](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7ffd135) |
- | 导入项目,更新项目 | 5e06adf |
||||
- | ws storage | [21b3a06](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/21b3a06) |
- | 导入项目后提示并打开项目详情页 | 410f527 |
||||
- | 上传逻辑变化 | [3ff1dc2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/3ff1dc2) |
- | 导入wbs | 1224fcb |
||||
- | 任务状态时间显示 | [56f5183](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/56f5183) |
- | 点击日历日期查询项目列表 | c458385 |
||||
- | 任务进行中状态数字 | [27b7326](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/27b7326) |
- | 定期任务面板骨架屏添加 | b2698c0 |
||||
- | 全局插件及默认插件位置修改 | [6c80d08](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/6c80d08) |
- | 分享项目和点击分享的项目链接 | 032d83c |
||||
- | 向右箭头图标变化 | [8e9ca55](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/8e9ca55) |
富文本插件 | 富文本插件demo测试 | ed3d644 |
||||
- | 字体大小更改 | [82cfdd4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/82cfdd4) |
- | 缓存修改 | 63e1f0d |
||||
- | 存token | [b8a178d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b8a178d) |
- | 检查交付物 | 9d92be5 |
||||
- | 定期任务面板骨架屏添加 | [b2698c0](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b2698c0) |
- | 角色栏实现 | 94cd671 |
||||
富文本插件 | 富文本插件demo测试 | [ed3d644](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ed3d644) |
- | 距调整pc端 | 5069aa1 |
||||
- | 导入wbs | [1224fcb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/1224fcb) |
- | 面变化首页变化 | 5e860f1 |
||||
- | 导入项目,更新项目 | [5e06adf](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5e06adf) |
- | 模拟接口测试 | 69e7931 |
||||
- | 导入项目后提示并打开项目详情页 | [410f527](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/410f527) |
- | 配置默认插件接口 | f0c177d |
||||
- | 引入dayjs | [29b8b93](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/29b8b93) |
- | 全局插件及默认插件位置修改 | 6c80d08 |
||||
- | 提交到本地 | [9cbe411](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/9cbe411) |
- | 任务进行中状态数字 | 27b7326 |
||||
- | 插件参数处理调整 | [a3e68d3](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a3e68d3) |
- | 任务状态时间显示 | 56f5183 |
||||
- | 插件数据获取 | [5b91bdc](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5b91bdc) |
- | 日常任务插件调整 | c1881f9 |
||||
- | 日历定位;合并 | [ea3f937](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ea3f937) |
- | 日历定位;合并 | ea3f937 |
||||
- | 日常任务插件调整 | [c1881f9](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c1881f9) |
- | 上传逻辑变化 | 3ff1dc2 |
||||
- | 时间基准线,默认插件 | [a33ba1e](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a33ba1e) |
- | 设置小红点 | 9316bcb |
||||
- | 时间轴修改状态时提示框增加 | [e841392](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e841392) |
- | 时间基准线,默认插件 | a33ba1e |
||||
- | 时间轴界面 | [33927e9](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/33927e9) |
- | 时间轴界面 | 33927e9 |
||||
- | 标题栏变化 | [3898cfe](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/3898cfe) |
- | 时间轴时间、交付物新原型 | c57f986 |
||||
- | 标题栏变化 | [c0fcd9d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c0fcd9d) |
- | 时间轴修改状态时提示框增加 | e841392 |
||||
- | 标题栏角色栏全局任务组件新建 | [0500cb4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0500cb4) |
- | 适配小程序;小程序登录 | cefc0eb |
||||
- | 模拟接口测试 | [69e7931](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/69e7931) |
- | 首页项目样式改变 | 8514c85 |
||||
- | 添加时间轴上下滚动 | [2b81bbc](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/2b81bbc) |
- | 提交到本地 | 9cbe411 |
||||
- | 点击日历日期查询项目列表 | [c458385](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c458385) |
- | 添加内置插件-交付物 | 6e0bc46 |
||||
- | 角色栏实现 | [94cd671](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/94cd671) |
- | 添加任务对接口 | 7fc959d |
||||
- | 设置小红点 | [9316bcb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/9316bcb) |
- | 添加时间轴上下滚动 | 2b81bbc |
||||
- | 距调整pc端 | [5069aa1](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5069aa1) |
- | 添加项目排序 | a0b491b |
||||
- | 配置默认插件接口 | [f0c177d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/f0c177d) |
- | 添加医院项目下的问卷悬浮按钮 | e68e633 |
||||
- | 面变化首页变化 | [5e860f1](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5e860f1) |
- | 添加子任务插件 子项目插件 | 7bda7e2 |
||||
- | 项目api url设置 | [6cd5245](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/6cd5245) |
- | 细节调整,添加project-webview | 4d9050b |
||||
- | 项目列表, 项目url | [32e005b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/32e005b) |
- | 向右箭头图标变化 | 8e9ca55 |
||||
- | 首页项目样式改变 | [8514c85](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/8514c85) |
- | 项目创建分享链接 | eb2c4ba |
||||
|
- | 项目列表, 项目url | 32e005b |
||||
|
- | 项目api url设置 | 6cd5245 |
||||
|
- | 新建任务 | ab24b33 |
||||
|
- | 新建任务 | 131ce0f |
||||
|
- | 新建任务 | 9ab680e |
||||
|
- | 新建任务 | 59897c2 |
||||
|
- | 新建任务 部分提交参数 | 25c78b8 |
||||
|
- | 新建任务 部分提交参数 | 6a422f6 |
||||
|
- | 新建任务,分享项目弹出层样式修改 | efbc679 |
||||
|
- | 新建形目 | f7d7108 |
||||
|
- | 新增任务 | 9b542fc |
||||
|
- | 引入dayjs | 29b8b93 |
||||
|
- | 字体大小更改 | 82cfdd4 |
||||
|
- | api封装 | 7d4edfc |
||||
|
bind phone | 图形验证码;短信验证码;绑定手机号 | 93ffea2 |
||||
|
- | cache indexedDB处理 | 3388967 |
||||
|
calendar, tall.js | 上下滑动切换日历的模式,tall.js中domain根据环境变量切换 | 364e25d |
||||
|
- | db store | 6414c4f |
||||
|
default plugin | 添加默认插件;项目列表;全局项目最大高度设置 | ed1d87b |
||||
|
- | indexedDB | 687394e |
||||
|
mp | 兼容小程序,去除window,document等 | 9178255 |
||||
|
- | network控制本地缓存的使用 | 858429e |
||||
|
phone-bind | 验证码validate | a427250 |
||||
|
pinch | alloy finger实现图片的pinch放大缩小 | de01343 |
||||
|
plugin | 插件添加了token及param参数 | aeb0292 |
||||
|
- | post 封装 | da52e94 |
||||
|
- | tall插件封装 | 1bcb920 |
||||
|
task status | 任务状态切换未完 | 7ffd135 |
||||
|
- | ws storage | 21b3a06 |
||||
|
|
||||
|
|
||||
### 🎨 代码样式 |
### 🎨 代码样式 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | calendar注释 | [a2ec112](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a2ec112) |
- | 代码格式细节调整 | cb2532b |
||||
- | 代码审查 | [d75134c](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/d75134c) |
- | 代码审查 | d75134c |
||||
- | 代码格式细节调整 | [cb2532b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/cb2532b) |
- | 格式细节调整 | b907a03 |
||||
- | 任务快捷方式图标增加 | [4aba872](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4aba872) |
- | 更新代码 | 8c27e68 |
||||
- | 修改角色样式 | [73e268e](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/73e268e) |
- | 更新代码 | 1f40a76 |
||||
- | 删除calendar中多余的console | [e339eec](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e339eec) |
- | 任务快捷方式图标增加 | 4aba872 |
||||
- | 删除console.log | [5064a38](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5064a38) |
- | 日常任务修改 | dfa7ee2 |
||||
- | 删除index中没用的alert代码 | [9c9eec7](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/9c9eec7) |
- | 删除插件携带的多余文件 | 0f392bb |
||||
- | 删除mock,console;upload添加loading | [99d42e2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/99d42e2) |
- | 删除多余字段 | 5ae3973 |
||||
- | 删除多余字段 | [5ae3973](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5ae3973) |
- | 删除没用代码 | 34b20e1 |
||||
- | 删除插件携带的多余文件 | [0f392bb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0f392bb) |
- | 删除无用代码 | ae3675b |
||||
- | 删除没用代码 | [34b20e1](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/34b20e1) |
- | 删除calendar中多余的console | e339eec |
||||
- | 图标修改 | [54bca09](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/54bca09) |
- | 删除console.log | a9ead1a |
||||
- | 无基本变化 | [21ac4bb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/21ac4bb) |
- | 删除console.log | 5064a38 |
||||
- | 日常任务修改 | [dfa7ee2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/dfa7ee2) |
- | 删除index中没用的alert代码 | 9c9eec7 |
||||
- | 更新代码 | [8c27e68](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/8c27e68) |
- | 删除mock,console;upload添加loading | 99d42e2 |
||||
- | 更新代码 | [1f40a76](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/1f40a76) |
- | 添加插件数据 | 2f11b42 |
||||
- | 格式细节调整 | [b907a03](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b907a03) |
- | 图标修改 | 54bca09 |
||||
- | 添加插件数据 | [2f11b42](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/2f11b42) |
- | 无基本变化 | 21ac4bb |
||||
- | 组件新建 | [89c0035](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/89c0035) |
- | 细节调整 | 2cfc09a |
||||
- | 细节调整 | [2cfc09a](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/2cfc09a) |
- | 修改角色样式 | 73e268e |
||||
|
- | 修改选择检查人样式 | 4c2de55 |
||||
|
- | 组件新建 | 89c0035 |
||||
|
- | calendar注释 | a2ec112 |
||||
|
- | indexedDB.js格式整理 | b0d3a36 |
||||
|
|
||||
|
|
||||
### 🐛 Bug 修复 |
### 🐛 Bug 修复 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | 1.时间轴数据渲染 2.时间基准线 | [d643af2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/d643af2) |
- | 1.时间轴数据渲染 2.时间基准线 | d643af2 |
||||
ID1000343 | 解决向下预加载查询参数时间没+1颗粒度;以及滚动加载颗粒度写死的问题 | [940603a](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/940603a), closes [#ID1000343](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/issues/ID1000343) |
- | 插件bug解决 | 41257eb |
||||
plugin | 插件解析机制完善 | [0f5a27d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0f5a27d) |
- | 初始展示角色修改 | 2ac4053 |
||||
project title | 项目标题修改; 切换角色移除script | [5c20017](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5c20017) |
- | 调查问卷未读数计算修改 | 69677ce |
||||
roles | 修复默认显示不是我的角色的问题 | [b69f94f](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b69f94f) |
- | 调试定期任务bug;不能合并使用 | d641312 |
||||
role | 切换角色的逻辑修正完善 | [4ae534f](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4ae534f) |
- | 定期任务本地缓存和api赋值,未完成 | 5a10856 |
||||
task任务逻辑完善 | 减少初始global及regular的不必要请求 | [bd4bd38](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/bd4bd38) |
定期任务本地缓存和api赋值,未完成 | 定期任务本地缓存和api赋值,未完成 | b22a366 |
||||
- | title.vue根据页面栈显示返回按钮;标题文本超出显示... | [0cbacf4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0cbacf4) |
- | 定期任务插件 | 92b3254 |
||||
- | 上下滑动加载定期任务 | [4090d89](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4090d89) |
- | 定期任务骨架屏修改 | 8ff72dd |
||||
- | 上下滚动时间轴 | [d533a01](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/d533a01) |
- | 定期任务接口 | aa4981c |
||||
- | 下拉加载定期任务传参,时间格式化修改 | [0b95a0e](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0b95a0e) |
- | 定期任务未加载时,显示空的时间轴并能上下滑动 | ce38093 |
||||
- | 任务开始时间延迟插件 | [992a313](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/992a313) |
- | 定期任务key值修改 | c6688db |
||||
- | 修改main | [749ae9a](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/749ae9a) |
- | 分享未登录提示修改 | 80eb4c5 |
||||
- | 修改定期任务状态0和4时不加载圆圈 | [30e352f](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/30e352f) |
- | 分享项目链接 | d867239 |
||||
- | 修改小红点传参 | [87b20fd](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/87b20fd) |
- | 骨架屏替换 | e9fdd71 |
||||
- | 修改报错 | [531c14d](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/531c14d) |
- | 滚动id函数优化 | b351b67 |
||||
- | 修改接口路径 | [df6acf2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/df6acf2) |
- | 监听时间基本点 | 033fca0 |
||||
- | 修改角色栏组件 | [a54c601](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a54c601) |
- | 检查交付物传参修改 | ebe0031 |
||||
- | 切换到默认项目角色没有激活状态的bug | [438d448](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/438d448) |
- | 检查交付物传参修改 | 37b51bc |
||||
- | 切换日历时查询小红点 | [7091789](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7091789) |
- | 交付物+考勤管理 | 7020c78 |
||||
- | 初始展示角色修改 | [2ac4053](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/2ac4053) |
- | 交付物显示样式修改 | be2f3cd |
||||
- | 定期任务key值修改 | [c6688db](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c6688db) |
- | 角色滚动问题修复 | c8ee189 |
||||
- | 定期任务接口 | [aa4981c](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/aa4981c) |
- | 角色栏修改 | 19228d6 |
||||
- | 定期任务插件 | [92b3254](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/92b3254) |
- | 角色显示状态修改 | 7d3b906 |
||||
- | 定期任务未加载时,显示空的时间轴并能上下滑动 | [ce38093](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ce38093) |
- | 接受切换项目消息,分享项目 | 2f84ae1 |
||||
- | 定期任务骨架屏修改 | [8ff72dd](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/8ff72dd) |
- | 接受切换项目消息,分享项目 | 5ea2fe4 |
||||
- | 平车演示临时去掉项目快捷方式的toast提示 | [e0b2c23](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e0b2c23) |
- | 解决进项目角色id不更新问题 | 3b400df |
||||
- | 手动展开日常任务 | [0a4a622](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0a4a622) |
- | 解决时间轴报错 | da1eece |
||||
- | 提示信息显示bug及日常任务收缩问题 | [f2f06c5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/f2f06c5) |
- | 平车演示临时去掉项目快捷方式的toast提示 | e0b2c23 |
||||
- | 插件bug解决 | [41257eb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/41257eb) |
- | 切换到默认项目角色没有激活状态的bug | 438d448 |
||||
- | 收到消息修改任务状态 | [c378063](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c378063) |
- | 切换日历时查询小红点 | 7091789 |
||||
- | 日历无任务时添加小绿点,时间轴刻度无任务不显示时分 | [0f90868](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0f90868) |
- | 全局任务点击时保存角色id到本地 | e1a17c5 |
||||
- | 日常任务html数据查验 | [880ce5c](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/880ce5c) |
- | 任务开始时间延迟插件 | 992a313 |
||||
- | 日常任务插件遍历时的key值修改 | [cd26285](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/cd26285) |
- | 日常任务插件遍历时的key值修改 | cd26285 |
||||
- | 日常任务插件面板高度修改 | [249f9e4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/249f9e4) |
- | 日常任务插件面板高度修改 | 249f9e4 |
||||
- | 时间轴上下滑动 | [4d0ae46](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4d0ae46) |
- | 日常任务html数据查验 | 880ce5c |
||||
- | 时间轴上下滚动数据加载bug修改 | [e82ede4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e82ede4) |
- | 日历无任务时添加小绿点,时间轴刻度无任务不显示时分 | 0f90868 |
||||
- | 时间轴插件 | [225d3cc](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/225d3cc) |
- | 上下滚动时间轴 | d533a01 |
||||
- | 时间轴无任务时时间刻度加载修改 | [4921672](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4921672) |
- | 上下滑动加载定期任务 | 4090d89 |
||||
- | 时间轴滚动位置修改 | [551da63](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/551da63) |
- | 设置时间轴自动滚动到当前位置 | a3474f8 |
||||
- | 时间轴骨架屏修改 | [ca78d02](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ca78d02) |
- | 时间轴插件 | 225d3cc |
||||
- | 监听时间基本点 | [033fca0](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/033fca0) |
- | 时间轴骨架屏修改 | ca78d02 |
||||
- | 角色显示状态修改 | [7d3b906](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7d3b906) |
- | 时间轴滚动位置修改 | 551da63 |
||||
- | 角色栏修改 | [19228d6](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/19228d6) |
- | 时间轴上下滚动数据加载bug修改 | e82ede4 |
||||
- | 解决时间轴报错 | [da1eece](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/da1eece) |
- | 时间轴上下滑动 | 4d0ae46 |
||||
- | 设置时间轴自动滚动到当前位置 | [a3474f8](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a3474f8) |
- | 时间轴无任务时时间刻度加载修改 | 4921672 |
||||
- | 跳转详情页返回路径修改 | [c5e17c0](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c5e17c0) |
- | 时间轴自动滚动到对应位置修改 | e5a13c8 |
||||
- | 骨架屏替换 | [e9fdd71](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e9fdd71) |
- | 时间轴自动滚动到对应位置修改 | 1c23019 |
||||
|
- | 收到消息修改任务状态 | c378063 |
||||
|
- | 手动展开日常任务 | 0a4a622 |
||||
|
- | 提示信息显示bug及日常任务收缩问题 | f2f06c5 |
||||
|
- | 添加页面返回功能 解决角色滚动bug | 87ce0f7 |
||||
|
- | 跳转详情页返回路径修改 | c5e17c0 |
||||
|
- | 下拉加载定期任务传参,时间格式化修改 | 0b95a0e |
||||
|
- | 修复日常任务面板内容显示不全的问题 | 053be5b |
||||
|
- | 修改报错 | 531c14d |
||||
|
- | 修改定期任务状态0和4时不加载圆圈 | 30e352f |
||||
|
- | 修改角色栏组件 | a54c601 |
||||
|
- | 修改接口路径 | df6acf2 |
||||
|
- | 修改时间轴定期任务加载逻辑 | 1977c00 |
||||
|
- | 修改项目详情页返回首页bug | e942887 |
||||
|
- | 修改小红点传参 | 87b20fd |
||||
|
- | 修改main | 749ae9a |
||||
|
- | api 存storage | 81032ba |
||||
|
ID1000343 | 解决向下预加载查询参数时间没+1颗粒度;以及滚动加载颗粒度写死的问题 | 940603a, closes #ID1000343 |
||||
|
plugin | 插件解析机制完善 | 0f5a27d |
||||
|
project title | 项目标题修改; 切换角色移除script | 5c20017 |
||||
|
role | 切换角色的逻辑修正完善 | 4ae534f |
||||
|
roles | 修复默认显示不是我的角色的问题 | b69f94f |
||||
|
task任务逻辑完善 | 减少初始global及regular的不必要请求 | bd4bd38 |
||||
|
- | title.vue根据页面栈显示返回按钮;标题文本超出显示... | 0cbacf4 |
||||
|
|
||||
|
|
||||
### 📝 文档 |
### 📝 文档 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | README.md | [ab0eb05](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/ab0eb05) |
- | 新建项目,分享项目样式修改 | 4524d4a |
||||
|
- | README.md | ab0eb05 |
||||
|
|
||||
|
|
||||
### 🔧 测试 |
### 🔧 测试 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | 暂时移除了jest浏览器配置 | [5088d01](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5088d01) |
- | 禁用任务开始操作 | b5425db |
||||
- | 添加测试,测试utils/time.js的computeDurationText | [e758010](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e758010) |
- | 提交交付物选择检查人样式修改 | b8d5aeb |
||||
- | 禁用任务开始操作 | [b5425db](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b5425db) |
- | 添加测试,测试utils/time.js的computeDurationText | e758010 |
||||
|
- | 暂时移除了jest浏览器配置 | 5088d01 |
||||
|
|
||||
|
|
||||
### 🔨 代码重构 |
### 🔨 代码重构 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
calendar | 日历细节调整 | [1a8d6bf](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/1a8d6bf) |
- | 更改版本号 | 64af936 |
||||
- | project 代码健壮性完善 | [a3202c5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a3202c5) |
- | 界面样式调整 | 4367249 |
||||
store/home | 删除store/home | [db8a3b4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/db8a3b4) |
- | 任务状态重构 | 4693655 |
||||
task beginTime | 格式化任务开始时间 | [fbc0301](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/fbc0301) |
- | 删除多余的技术验证界面 | 542ae5b |
||||
template | eslint prettier sass uview tailwindcss | [9c966a1](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/9c966a1) |
- | 删除多余的weekmode store里的东西 | 0841fe0 |
||||
tips | 修改任务状态方法重构 | [b57d3ac](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b57d3ac) |
- | 删除无用的修改 | f601f3b |
||||
tip | 任务状态显示及tip组件数据的重构 | [78a5750](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/78a5750) |
- | 下滑时间轴添加备注 | 4fd20e3 |
||||
title.vue | 移除测试的repeat; 样式细节调整 | [c32d2bd](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c32d2bd) |
- | 修改角色栏和日常任务面板的样式 | d653f9a |
||||
- | 下滑时间轴添加备注 | [4fd20e3](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4fd20e3) |
- | 只保留project内容 | 7781c7b |
||||
- | 任务状态重构 | [4693655](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4693655) |
- | 重构时间刻度渲染任务 | 5cf7d08 |
||||
- | 删除多余的weekmode store里的东西 | [0841fe0](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0841fe0) |
- | 重构store分层 | 5f6fff8 |
||||
- | 删除多余的技术验证界面 | [542ae5b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/542ae5b) |
calendar | 日历细节调整 | 1a8d6bf |
||||
- | 界面样式调整 | [4367249](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4367249) |
- | project 代码健壮性完善 | a3202c5 |
||||
- | 重构store分层 | [5f6fff8](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5f6fff8) |
- | puppeteer升级v10 | f02b0e7 |
||||
|
store/home | 删除store/home | db8a3b4 |
||||
|
tailwindcss | tailwindcss CDN引入;移除相关配置文件及包;开启treeShaking | 15485a0 |
||||
|
task beginTime | 格式化任务开始时间 | fbc0301 |
||||
|
template | eslint prettier sass uview tailwindcss | 9c966a1 |
||||
|
tip | 任务状态显示及tip组件数据的重构 | 78a5750 |
||||
|
tips | 修改任务状态方法重构 | b57d3ac |
||||
|
title.vue | 移除测试的repeat; 样式细节调整 | c32d2bd |
||||
|
- | webview返回主框架 | 6aa728b |
||||
|
|
||||
|
|
||||
### 🚀 性能优化 |
### 🚀 性能优化 |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | 1.时间轴筛选相同的时间替换数据 2.整理代码 | [e082ccb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/e082ccb) |
- | 1.时间轴筛选相同的时间替换数据 2.整理代码 | e082ccb |
||||
- | 修改代码格式 | [14123d7](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/14123d7) |
- | 本地缓存 | c615924 |
||||
- | 修改定期任务骨架屏高度 | [909a734](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/909a734) |
- | 测试接口 | 215e074 |
||||
- | 插件查询及展示 | [4dba770](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/4dba770) |
- | 插件查询及展示 | 4dba770 |
||||
- | 整理代码 | [7a55315](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7a55315) |
- | 角色栏文字颜色修改 | 215c6b3 |
||||
- | 日历的更改 | [7353ac8](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7353ac8) |
- | 解决警告 | c932b09 |
||||
- | 测试接口 | [215e074](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/215e074) |
- | 日常任务样式修改 | 4628301 |
||||
- | 组件文件夹新建 | [22bfe7b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/22bfe7b) |
- | 日历的更改 | 7353ac8 |
||||
- | 组件文件夹新建 | [17bb8c9](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/17bb8c9) |
- | 添加弹框动画 | 8903854 |
||||
- | 组件文件夹新建 | [1421504](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/1421504) |
- | 务,分享项目样框样式修改式弹框 | dab3d44 |
||||
- | 角色栏文字颜色修改 | [215c6b3](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/215c6b3) |
- | 小红点api缓存修改 | e992343 |
||||
- | 解决警告 | [c932b09](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c932b09) |
- | 新建任务界面完善 | 2033b55 |
||||
|
- | 修改代码格式 | 14123d7 |
||||
|
- | 修改定期任务骨架屏高度 | 909a734 |
||||
|
- | 修改样式 | 322b0fb |
||||
|
- | 整理代码 | 7a55315 |
||||
|
- | 组件文件夹新建 | 22bfe7b |
||||
|
- | 组件文件夹新建 | 17bb8c9 |
||||
|
- | 组件文件夹新建 | 1421504 |
||||
|
|
||||
|
|
||||
### chore |
### chore |
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | api 封装 | [8dcb8a2](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/8dcb8a2) |
- | 关掉了treeShaking | 3d9bac5 |
||||
- | env host修改 | [a79a4a5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a79a4a5) |
- | 删除多余的构建的命令 | 3f4eb2f |
||||
- | merge globals | [b0957cc](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/b0957cc) |
- | 删除vuedragable及修改运行端口为9000 | c864f91 |
||||
- | merge wrr | [5ccc7a5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/5ccc7a5) |
信息配置 | 配置eslint等配置 | 7421443 |
||||
- | mock | [51c24a5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/51c24a5) |
- | 修复不能build的问题 | 0b7b91e |
||||
package manifest | 去掉了摇树 | [f7c1dd4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/f7c1dd4) |
- | api 封装 | 8dcb8a2 |
||||
pwa 小程序 | 移除了pwa,alloyFinger添加平台判断 | [875fab4](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/875fab4) |
- | env host修改 | a79a4a5 |
||||
- | uview-ui | [a9ea34b](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/a9ea34b) |
- | merge globals | b0957cc |
||||
v3.0.1 | tall api 地址从1.0改成了3.0 | [db5afd5](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/db5afd5) |
- | merge wrr | 5ccc7a5 |
||||
信息配置 | 配置eslint等配置 | [7421443](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/7421443) |
- | merge wrr lucky | 959ae05 |
||||
- | 修复不能build的问题 | [0b7b91e](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/0b7b91e) |
- | mock | 51c24a5 |
||||
- | 删除多余的构建的命令 | [3f4eb2f](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/3f4eb2f) |
node-sass | 替换node-sass为sass(dart-sass) | c33169d |
||||
|
package manifest | 去掉了摇树 | f7c1dd4 |
||||
|
pwa 小程序 | 移除了pwa,alloyFinger添加平台判断 | 875fab4 |
||||
|
- | uview-ui | a9ea34b |
||||
|
v3.0.1 | tall api 地址从1.0改成了3.0 | db5afd5 |
||||
|
|
||||
|
|
||||
范围|描述|commitId |
范围|描述|commitId |
||||
--|--|-- |
--|--|-- |
||||
- | style:index | [978f272](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/978f272) |
- | style:index | 978f272 |
||||
- | !2 基础模板v1.1.0 | [f5e61dd](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/f5e61dd) |
- | !2 基础模板v1.1.0 | f5e61dd |
||||
- | init | [c0f1deb](https://dd.tall.wiki/gitea/ccsens_fe/TALL-MUI-3/commits/c0f1deb) |
- | init | c0f1deb |
||||
|
|
||||
|
@ -1,38 +1,21 @@ |
|||||
const path = require('path'); |
const path = require('path'); |
||||
|
|
||||
module.exports = { |
module.exports = { |
||||
parser: require('postcss-comment'), |
parser: require('postcss-comment'), |
||||
plugins: [ |
plugins: [ |
||||
require('postcss-import')({ |
require('postcss-import')({ |
||||
resolve(id, basedir, importOptions) { |
resolve(id, basedir, importOptions) { |
||||
if (id.startsWith('~@/')) { |
if (id.startsWith('~@/')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)); |
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)); |
||||
} else if (id.startsWith('@/')) { |
} else if (id.startsWith('@/')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)); |
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)); |
||||
} else if (id.startsWith('/') && !id.startsWith('//')) { |
} else if (id.startsWith('/') && !id.startsWith('//')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)); |
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)); |
||||
} |
} |
||||
return id; |
return id; |
||||
}, |
}, |
||||
}), |
}), |
||||
// require('autoprefixer')({ remove: process.env.UNI_PLATFORM !== 'h5' }),
|
require('autoprefixer')({ remove: process.env.UNI_PLATFORM !== 'h5' }), |
||||
require('@dcloudio/vue-cli-plugin-uni/packages/postcss'), |
require('@dcloudio/vue-cli-plugin-uni/packages/postcss'), |
||||
require('tailwindcss')({ config: "./tailwind.config.js" }), |
], |
||||
...( |
}; |
||||
process.env.UNI_PLATFORM !== 'h5' |
|
||||
? [ |
|
||||
require("postcss-class-rename")({ |
|
||||
"\\\\:": "--", |
|
||||
"\\\\/": "--", |
|
||||
"\\\\.": "--", |
|
||||
".:": "--", |
|
||||
"\\\*": "--", |
|
||||
}) |
|
||||
] : [ |
|
||||
require("autoprefixer")({ |
|
||||
remove: true, |
|
||||
}), |
|
||||
] |
|
||||
) |
|
||||
], |
|
||||
}; |
|
||||
|
@ -0,0 +1,15 @@ |
|||||
|
{ |
||||
|
"$shared": { |
||||
|
"version": "v1", |
||||
|
"identifier": "wally", |
||||
|
"credential": "111111" |
||||
|
}, |
||||
|
"dev": { |
||||
|
"name": "dev", |
||||
|
"url": "http://192.168.0.99/gateway" |
||||
|
}, |
||||
|
"local": { |
||||
|
"version": "v2", |
||||
|
"url": "http://192.168.0.99/gateway" |
||||
|
} |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
|
||||
|
### login |
||||
|
# @name login |
||||
|
POST https://www.tall.wiki/gateway/tall/v1.0/users/signin |
||||
|
content-type: application/json;charset=utf-8 |
||||
|
|
||||
|
{ |
||||
|
"client": 1, |
||||
|
"data": { |
||||
|
"credential": "123456", |
||||
|
"identifier": "zb11" |
||||
|
}, |
||||
|
"scene": 0, |
||||
|
"type": 3 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
### 导入插件 |
||||
|
# POST http://127.0.0.1:7220/plugin/import |
||||
|
POST http://www.tall.wiki/gateway/pluginshop/plugin/import |
||||
|
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW |
||||
|
Authorization: Bearer {{login.response.body.$.data.token}} |
||||
|
|
||||
|
title |
||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW |
||||
|
Content-Disposition: form-data; name="param"; filename="插件导入表格.xlsx" |
||||
|
Content-Type: xlsx |
||||
|
|
||||
|
< E:\ccsens\plugins\插件导入表格.xlsx |
||||
|
|
||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW-- |
||||
|
|
||||
|
|
||||
|
|
||||
|
### 更新redis内的插件信息 |
||||
|
POST http://www.tall.wiki/gateway/pluginshop/plugin/updatePluginOfRedis |
||||
|
content-type: application/json;charset=utf-8 |
||||
|
Authorization: Bearer {{login.response.body.$.data.token}} |
@ -1,11 +0,0 @@ |
|||||
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ |
|
||||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 |
|
||||
"version": "0.0", |
|
||||
"configurations": [{ |
|
||||
"type": "uniCloud", |
|
||||
"default": { |
|
||||
"launchtype": "local" |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
} |
|
@ -1,7 +1,9 @@ |
|||||
const install = (Vue, vm) => { |
const install = (Vue, vm) => { |
||||
vm.$u.api = { ...vm.$u.api } || {}; |
vm.$u.api = { ...vm.$u.api } || {}; |
||||
//根据时间基准点和角色查找定期任务
|
//根据项目id查找角色
|
||||
vm.$u.api.findShowRole = param => vm.$u.post(`${uni.$t.domain}/role/show`, param); |
vm.$u.api.findShowRole = param => vm.$u.post(`${uni.$t.domain}/role/show`, param); |
||||
|
//根据项目id查找所有成员
|
||||
|
vm.$u.api.queryChecker = param => vm.$u.post(`${uni.$t.domain}/deliver/queryChecker`, param); |
||||
}; |
}; |
||||
|
|
||||
export default { install }; |
export default { install }; |
||||
|
@ -1,7 +1,7 @@ |
|||||
const install = (Vue, vm) => { |
const install = (Vue, vm) => { |
||||
vm.$u.api = { ...vm.$u.api } || {}; |
vm.$u.api = { ...vm.$u.api } || {}; |
||||
// 导入wbs
|
// 导入wbs
|
||||
vm.$u.api.import = formData => vm.$t.chooseAndUpload(`${uni.$t.domain}/wbs`, formData); |
vm.$u.api.import = formData => vm.$t.chooseAndUpload(`${uni.$t.domain}/wbs`, formData, ['.xls', '.xlsx']); |
||||
}; |
}; |
||||
|
|
||||
export default { install }; |
export default { install }; |
||||
|
@ -1,3 +1,155 @@ |
|||||
.min-0 { |
.min-0 { |
||||
min-width: 0; |
min-width: 0; |
||||
} |
} |
||||
|
.border-b-1 { |
||||
|
border-bottom-width: 1px; |
||||
|
} |
||||
|
|
||||
|
/* 列表 */ |
||||
|
.uni-list { |
||||
|
background-color: #ffffff; |
||||
|
position: relative; |
||||
|
width: 100%; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
border: 1px solid #afbed1; |
||||
|
height: 80rpx; |
||||
|
line-height: 80rpx; |
||||
|
} |
||||
|
.uni-list-cell { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.uni-list-cell-hover { |
||||
|
background-color: #eee; |
||||
|
} |
||||
|
.uni-list-cell-pd { |
||||
|
padding: 22rpx 30rpx; |
||||
|
} |
||||
|
.uni-list-cell-left { |
||||
|
white-space: nowrap; |
||||
|
font-size: 28rpx; |
||||
|
padding: 0 30rpx; |
||||
|
} |
||||
|
.uni-list-cell-db, |
||||
|
.uni-list-cell-right { |
||||
|
flex: 1; |
||||
|
} |
||||
|
.uni-list-cell::after { |
||||
|
position: absolute; |
||||
|
z-index: 3; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
left: 30rpx; |
||||
|
height: 1px; |
||||
|
content: ''; |
||||
|
-webkit-transform: scaleY(0.5); |
||||
|
transform: scaleY(0.5); |
||||
|
background-color: #c8c7cc; |
||||
|
} |
||||
|
.uni-list .uni-list-cell:last-child::after { |
||||
|
height: 0rpx; |
||||
|
} |
||||
|
.uni-list-cell-last.uni-list-cell::after { |
||||
|
height: 0rpx; |
||||
|
} |
||||
|
.uni-list-cell-divider { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
color: #999; |
||||
|
background-color: #f7f7f7; |
||||
|
padding: 15rpx 20rpx; |
||||
|
} |
||||
|
.uni-list-cell-divider::before { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
height: 1px; |
||||
|
content: ''; |
||||
|
-webkit-transform: scaleY(0.5); |
||||
|
transform: scaleY(0.5); |
||||
|
background-color: #c8c7cc; |
||||
|
} |
||||
|
.uni-list-cell-divider::after { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
left: 0rpx; |
||||
|
height: 1px; |
||||
|
content: ''; |
||||
|
-webkit-transform: scaleY(0.5); |
||||
|
transform: scaleY(0.5); |
||||
|
background-color: #c8c7cc; |
||||
|
} |
||||
|
.uni-list-cell-navigate { |
||||
|
font-size: 30rpx; |
||||
|
padding: 22rpx 30rpx; |
||||
|
line-height: 48rpx; |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
box-sizing: border-box; |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.uni-list-cell-navigate { |
||||
|
padding-right: 36rpx; |
||||
|
} |
||||
|
.uni-navigate-badge { |
||||
|
padding-right: 50rpx; |
||||
|
} |
||||
|
.uni-list-cell-navigate.uni-navigate-right:after { |
||||
|
font-family: uniicons; |
||||
|
content: '\e583'; |
||||
|
position: absolute; |
||||
|
right: 24rpx; |
||||
|
top: 50%; |
||||
|
color: #bbb; |
||||
|
-webkit-transform: translateY(-50%); |
||||
|
transform: translateY(-50%); |
||||
|
} |
||||
|
.uni-list-cell-navigate.uni-navigate-bottom:after { |
||||
|
font-family: uniicons; |
||||
|
content: '\e581'; |
||||
|
position: absolute; |
||||
|
right: 24rpx; |
||||
|
top: 50%; |
||||
|
color: #bbb; |
||||
|
-webkit-transform: translateY(-50%); |
||||
|
transform: translateY(-50%); |
||||
|
} |
||||
|
.uni-list-cell-navigate.uni-navigate-bottom.uni-active::after { |
||||
|
font-family: uniicons; |
||||
|
content: '\e580'; |
||||
|
position: absolute; |
||||
|
right: 24rpx; |
||||
|
top: 50%; |
||||
|
color: #bbb; |
||||
|
-webkit-transform: translateY(-50%); |
||||
|
transform: translateY(-50%); |
||||
|
} |
||||
|
.uni-collapse.uni-list-cell { |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
.uni-list-cell-navigate.uni-active { |
||||
|
background: #eee; |
||||
|
} |
||||
|
.uni-list.uni-collapse { |
||||
|
box-sizing: border-box; |
||||
|
height: 0; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
.uni-collapse .uni-list-cell { |
||||
|
padding-left: 20rpx; |
||||
|
} |
||||
|
.uni-collapse .uni-list-cell::after { |
||||
|
left: 52rpx; |
||||
|
} |
||||
|
.uni-list.uni-active { |
||||
|
height: auto; |
||||
|
} |
||||
|
@ -1,6 +0,0 @@ |
|||||
/* ./src/common/styles/index.css */ |
|
||||
|
|
||||
/*! @import */ |
|
||||
@tailwind base; |
|
||||
@tailwind components; |
|
||||
@tailwind utilities; |
|
@ -1,473 +0,0 @@ |
|||||
<template> |
|
||||
<view class="zzx-calendar"> |
|
||||
<view class="calendar-heander"> |
|
||||
{{ timeStr }} |
|
||||
</view> |
|
||||
|
|
||||
<!-- 星期几标题 --> |
|
||||
<view class="calendar-weeks"> |
|
||||
<view class="calendar-week" :class="{ 'text-red-500': week === '六' || week === '日' }" v-for="(week, index) in weeks" :key="index"> |
|
||||
{{ week }} |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<view class="calendar-content"> |
|
||||
<swiper |
|
||||
class="calendar-swiper" |
|
||||
:style="{ |
|
||||
width: '100%', |
|
||||
height: sheight, |
|
||||
}" |
|
||||
:indicator-dots="false" |
|
||||
:autoplay="false" |
|
||||
:duration="duration" |
|
||||
:current="current" |
|
||||
@change="changeSwp" |
|
||||
:circular="true" |
|
||||
> |
|
||||
<swiper-item class="calendar-item" v-for="sitem in swiper" :key="sitem"> |
|
||||
<view class="calendar-days"> |
|
||||
<!-- 当前的 --> |
|
||||
<template v-if="sitem === current"> |
|
||||
<view |
|
||||
class="calendar-day" |
|
||||
v-for="(item, index) in days" |
|
||||
:key="index" |
|
||||
:class="{ 'day-hidden': !item.show }" |
|
||||
@click="clickItem(item)" |
|
||||
> |
|
||||
<view class="date" :class="[item.isToday ? todayClass : '', item.fullDate === selectedDate ? checkedClass : '']"> |
|
||||
{{ item.time.getDate() }} |
|
||||
</view> |
|
||||
<view class="dot-show" v-if="item.info === '0'" :style="dotStyle"> </view> |
|
||||
</view> |
|
||||
</template> |
|
||||
<template v-else> |
|
||||
<!-- 下一个月/周 --> |
|
||||
<template v-if="current - sitem === 1 || current - sitem === -2"> |
|
||||
<view |
|
||||
class="calendar-day" |
|
||||
v-for="(item, index) in predays" |
|
||||
:key="index" |
|
||||
:class="{ |
|
||||
'day-hidden': !item.show, |
|
||||
}" |
|
||||
> |
|
||||
<view class="date" :class="[item.isToday ? todayClass : '']"> |
|
||||
{{ item.time.getDate() }} |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
<!-- 上一个月/周 --> |
|
||||
<template v-else> |
|
||||
<view |
|
||||
class="calendar-day" |
|
||||
v-for="(item, index) in nextdays" |
|
||||
:key="index" |
|
||||
:class="{ |
|
||||
'day-hidden': !item.show, |
|
||||
}" |
|
||||
> |
|
||||
<view class="date" :class="[item.isToday ? todayClass : '']"> |
|
||||
{{ item.time.getDate() }} |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
</template> |
|
||||
</view> |
|
||||
</swiper-item> |
|
||||
</swiper> |
|
||||
|
|
||||
<!-- <view class="mode-change" @click="changeMode"> |
|
||||
<view :class="weekMode ? 'mode-arrow-bottom' : 'mode-arrow-top'"> </view> |
|
||||
</view> --> |
|
||||
</view> |
|
||||
|
|
||||
<view class="flex justify-center u-font-18" style="color: #3b82f6" @click="goToday"> 今日 </view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { mapState } from 'vuex'; |
|
||||
import { gegerateDates, formatDate } from './generateDates.js'; |
|
||||
|
|
||||
export default { |
|
||||
props: { |
|
||||
duration: { type: Number, default: 500 }, |
|
||||
// 是否返回今日 |
|
||||
showBack: { type: Boolean, default: false }, |
|
||||
// 今日的自定义样式class |
|
||||
todayClass: { type: String, default: 'is-today' }, |
|
||||
// 选中日期的样式class |
|
||||
checkedClass: { type: String, default: 'is-checked' }, |
|
||||
// 打点日期的自定义样式 |
|
||||
dotStyle: { |
|
||||
type: Object, |
|
||||
default: () => { |
|
||||
return { background: '#4ade80' }; |
|
||||
}, |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
watch: { |
|
||||
dotList: function (newvalue) { |
|
||||
const days = this.days.slice(0); |
|
||||
const index = days.findIndex(day => day.show); |
|
||||
days.forEach((day, i) => { |
|
||||
newvalue.forEach((item, j) => { |
|
||||
if (i - index === j) { |
|
||||
day.info = item; |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
this.days = days; |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
data() { |
|
||||
return { |
|
||||
weeks: ['日', '一', '二', '三', '四', '五', '六'], // 周 |
|
||||
current: 1, |
|
||||
currentYear: '', |
|
||||
currentMonth: '', |
|
||||
currentDate: '', |
|
||||
days: [], |
|
||||
weekMode: false, // false -> 月 true -> 显示周 |
|
||||
swiper: [0, 1, 2], |
|
||||
selectedDate: formatDate(new Date(), 'yyyy-MM-dd'), // 当前选中的日期 |
|
||||
start: '', |
|
||||
end: '', |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
computed: { |
|
||||
...mapState('project', ['dotList']), |
|
||||
sheight() { |
|
||||
// 根据年月判断有多少行 |
|
||||
// 判断该月有多少天 |
|
||||
let h = '35px'; |
|
||||
if (!this.weekMode) { |
|
||||
const d = new Date(this.currentYear, this.currentMonth, 0); |
|
||||
const days = d.getDate(); // 判断本月有多少天 |
|
||||
let day = new Date(d.setDate(1)).getDay(); |
|
||||
// if (day === 0) { |
|
||||
// day = 7; |
|
||||
// } |
|
||||
const pre = 8 - day; |
|
||||
const rows = Math.ceil((days - pre) / 7) + 1; |
|
||||
h = 35 * rows + 'px'; |
|
||||
} |
|
||||
return h; |
|
||||
}, |
|
||||
|
|
||||
// 当前日期 年月 |
|
||||
timeStr() { |
|
||||
let str = ''; |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
const y = d.getFullYear(); |
|
||||
const m = d.getMonth() + 1 <= 9 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; |
|
||||
str = `${y}年${m}月`; |
|
||||
return str; |
|
||||
}, |
|
||||
|
|
||||
// 上一周期的days书籍 |
|
||||
predays() { |
|
||||
let pres = []; |
|
||||
if (this.weekMode) { |
|
||||
// 周模式 |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
d.setDate(d.getDate() - 7); |
|
||||
pres = gegerateDates(d, 'week'); |
|
||||
} else { |
|
||||
// 月模式 |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 2, 1); |
|
||||
pres = gegerateDates(d, 'month'); |
|
||||
} |
|
||||
return pres; |
|
||||
}, |
|
||||
|
|
||||
// 下一周期的days书籍 |
|
||||
nextdays() { |
|
||||
let nexts = []; |
|
||||
if (this.weekMode) { |
|
||||
// 周模式 |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
d.setDate(d.getDate() + 7); |
|
||||
nexts = gegerateDates(d, 'week'); |
|
||||
} else { |
|
||||
// 月模式 |
|
||||
const d = new Date(this.currentYear, this.currentMonth, 1); |
|
||||
nexts = gegerateDates(d, 'month'); |
|
||||
} |
|
||||
return nexts; |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
created() { |
|
||||
this.initDate(); |
|
||||
this.start = this.$moment().startOf('month').valueOf(); |
|
||||
this.end = this.$moment().endOf('month').valueOf(); |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
// |
|
||||
/** |
|
||||
* 滑动切换上下周期 |
|
||||
* 根据前一个减去目前的值我们可以判断是下一个月/周还是上一个月/周 |
|
||||
* current - pre === 1, -2 下一个月/周 |
|
||||
* current - pre === -1, 2 上一个月或者上一周 |
|
||||
*/ |
|
||||
changeSwp(e) { |
|
||||
const pre = this.current; |
|
||||
const current = e.target.current; |
|
||||
this.current = current; |
|
||||
|
|
||||
if (current - pre === 1 || current - pre === -2) { |
|
||||
// 下一个月 或 下一周 |
|
||||
this.daysNext(); |
|
||||
const arr = this.days.filter(s => s.show); |
|
||||
const end = `${arr[arr.length - 1].fullDate} 23:59:59`; |
|
||||
this.start = this.$moment(arr[0].fullDate).valueOf(); |
|
||||
this.end = this.$moment(end).valueOf(); |
|
||||
this.$emit('handleFindPoint', this.start, this.end); |
|
||||
} else { |
|
||||
// 上一个月 或 上一周 |
|
||||
this.daysPre(); |
|
||||
const arr = this.days.filter(s => s.show); |
|
||||
const end = `${arr[arr.length - 1].fullDate} 23:59:59`; |
|
||||
this.start = this.$moment(arr[0].fullDate).valueOf(); |
|
||||
this.end = this.$moment(end).valueOf(); |
|
||||
this.$emit('handleFindPoint', this.start, this.end); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 初始化日历的方法 |
|
||||
initDate(cur) { |
|
||||
let date = ''; |
|
||||
if (cur) { |
|
||||
date = new Date(cur); |
|
||||
} else { |
|
||||
date = new Date(); |
|
||||
} |
|
||||
this.currentDate = date.getDate(); // 今日几号 |
|
||||
this.currentYear = date.getFullYear(); // 当前年份 |
|
||||
this.currentMonth = date.getMonth() + 1; // 当前月份 |
|
||||
this.currentWeek = date.getDay() === 0 ? 7 : date.getDay(); // 1...6,0 星期几 |
|
||||
// const nowY = new Date().getFullYear(); // 当前年份 |
|
||||
// const nowM = new Date().getMonth() + 1; |
|
||||
// const nowD = new Date().getDate(); // 今日日期 几号 |
|
||||
// const nowW = new Date().getDay(); |
|
||||
// this.selectedDate = formatDate(new Date(), 'yyyy-MM-dd') |
|
||||
this.days = []; |
|
||||
let days = []; |
|
||||
if (this.weekMode) { |
|
||||
days = gegerateDates(date, 'week'); |
|
||||
// this.selectedDate = days[0].fullDate; |
|
||||
} else { |
|
||||
days = gegerateDates(date, 'month'); |
|
||||
// const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/')); |
|
||||
// const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth; |
|
||||
// if(!isMonth) { |
|
||||
// this.selectedDate = formatDate(new Date(this.currentYear, this.currentMonth-1,1), 'yyyy-MM-dd') |
|
||||
// } |
|
||||
} |
|
||||
// 设置小红点 |
|
||||
days.forEach((day, i) => { |
|
||||
this.dotList.forEach((item, j) => { |
|
||||
if (i === j) { |
|
||||
day.info = item; |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
this.days = days; |
|
||||
// 派发事件,时间发生改变 |
|
||||
let obj = { |
|
||||
start: '', |
|
||||
end: '', |
|
||||
}; |
|
||||
if (this.weekMode) { |
|
||||
obj.start = this.days[0].time; |
|
||||
obj.end = this.days[6].time; |
|
||||
} else { |
|
||||
const start = new Date(this.currentYear, this.currentMonth - 1, 1); |
|
||||
const end = new Date(this.currentYear, this.currentMonth, 0); |
|
||||
obj.start = start; |
|
||||
obj.end = end; |
|
||||
} |
|
||||
this.$emit('days-change', obj); |
|
||||
}, |
|
||||
|
|
||||
// 上一个 |
|
||||
daysPre() { |
|
||||
if (this.weekMode) { |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
d.setDate(d.getDate() - 7); |
|
||||
this.initDate(d); |
|
||||
} else { |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 2, 1); |
|
||||
this.initDate(d); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 下一个 |
|
||||
daysNext() { |
|
||||
if (this.weekMode) { |
|
||||
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
d.setDate(d.getDate() + 7); |
|
||||
this.initDate(d); |
|
||||
} else { |
|
||||
const d = new Date(this.currentYear, this.currentMonth, 1); |
|
||||
this.initDate(d); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 切换模式 |
|
||||
changeMode() { |
|
||||
const premode = this.weekMode; |
|
||||
let isweek = false; |
|
||||
if (premode) { |
|
||||
isweek = !!this.days.find(item => item.fullDate === this.selectedDate); |
|
||||
} |
|
||||
this.weekMode = !this.weekMode; |
|
||||
let d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate); |
|
||||
const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/')); |
|
||||
const isMonth = sel.getFullYear() === this.currentYear && sel.getMonth() + 1 === this.currentMonth; |
|
||||
if ((this.selectedDate && isMonth) || isweek) { |
|
||||
d = new Date(this.selectedDate.replace('-', '/').replace('-', '/')); |
|
||||
} |
|
||||
this.initDate(d); |
|
||||
}, |
|
||||
|
|
||||
// 点击日期 |
|
||||
clickItem(e) { |
|
||||
this.selectedDate = e.fullDate; |
|
||||
this.$emit('selected-change', e); |
|
||||
}, |
|
||||
|
|
||||
// 返回 |
|
||||
goToday() { |
|
||||
const d = new Date(); |
|
||||
this.initDate(d); |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.zzx-calendar { |
|
||||
width: 100%; |
|
||||
height: auto; |
|
||||
background-color: #fff; |
|
||||
padding-bottom: 10px; |
|
||||
|
|
||||
.calendar-heander { |
|
||||
text-align: center; |
|
||||
padding: 16px 0; |
|
||||
position: relative; |
|
||||
font-size: 15px; |
|
||||
} |
|
||||
|
|
||||
.calendar-weeks { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
flex-flow: row nowrap; |
|
||||
margin-bottom: 10px; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
font-size: 12px; |
|
||||
color: #9ca3af; |
|
||||
font-weight: bold; |
|
||||
|
|
||||
.calendar-week { |
|
||||
width: calc(100% / 7); |
|
||||
height: 100%; |
|
||||
text-align: center; |
|
||||
} |
|
||||
} |
|
||||
swiper { |
|
||||
width: 100%; |
|
||||
height: 60upx; |
|
||||
} |
|
||||
.calendar-content { |
|
||||
min-height: 30px; |
|
||||
} |
|
||||
.calendar-swiper { |
|
||||
min-height: 35px; |
|
||||
transition: height ease-out 0.3s; |
|
||||
} |
|
||||
.calendar-item { |
|
||||
margin: 0; |
|
||||
padding: 0; |
|
||||
height: 100%; |
|
||||
} |
|
||||
.calendar-days { |
|
||||
display: flex; |
|
||||
flex-flow: row wrap; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
overflow: hidden; |
|
||||
font-size: 14px; |
|
||||
|
|
||||
.calendar-day { |
|
||||
width: calc(100% / 7); |
|
||||
height: 35px; |
|
||||
text-align: center; |
|
||||
display: flex; |
|
||||
flex-flow: column nowrap; |
|
||||
justify-content: flex-start; |
|
||||
align-items: center; |
|
||||
position: relative; |
|
||||
} |
|
||||
} |
|
||||
.day-hidden { |
|
||||
visibility: hidden; |
|
||||
} |
|
||||
|
|
||||
.mode-change { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
margin-top: 5px; |
|
||||
|
|
||||
.mode-arrow-top { |
|
||||
width: 0; |
|
||||
height: 0; |
|
||||
border-left: 6px solid transparent; |
|
||||
border-right: 6px solid transparent; |
|
||||
border-bottom: 5px solid #ff6633; |
|
||||
} |
|
||||
.mode-arrow-bottom { |
|
||||
width: 0; |
|
||||
height: 0; |
|
||||
border-left: 6px solid transparent; |
|
||||
border-right: 6px solid transparent; |
|
||||
border-top: 5px solid #ff6633; |
|
||||
} |
|
||||
} |
|
||||
.is-today { |
|
||||
background: #ffffff; |
|
||||
border: 1upx solid #ff6633; |
|
||||
border-radius: 50%; |
|
||||
color: #ff6633; |
|
||||
} |
|
||||
.is-checked { |
|
||||
background: #ff6633; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
.date { |
|
||||
width: 25px; |
|
||||
height: 25px; |
|
||||
line-height: 25px; |
|
||||
margin: 0 auto; |
|
||||
border-radius: 25px; |
|
||||
} |
|
||||
.dot-show { |
|
||||
width: 6px; |
|
||||
height: 6px; |
|
||||
// background: red; |
|
||||
border-radius: 5px; |
|
||||
position: absolute; |
|
||||
top: 2px; |
|
||||
right: 10px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
@ -1,136 +0,0 @@ |
|||||
/* |
|
||||
*此函数的作用是根据传入的一个日期,返回这一周的日期或者这一个月的日期, |
|
||||
* 如果是月的话注意还包含上个月和下个月的日期,月的话总共数据有 6 * 7 = 42个 |
|
||||
* |
|
||||
*/ |
|
||||
/* |
|
||||
* 时间格式化函数 |
|
||||
* 重要提示,微信小程序new Date('2020-04-16')在ios中无法获取时间对象 |
|
||||
* 解决方式: 建议将时间都格式化成'2020/04/16 00:00:00'的格式 |
|
||||
* 函数示例: formatDate(new Date(), 'YYYY/MM/dd hh:mm:ss') |
|
||||
*/ |
|
||||
export const formatDate = (date, fmt) => { |
|
||||
if (/(y+)/.test(fmt)) { |
|
||||
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); |
|
||||
} |
|
||||
let o = { |
|
||||
'M+': date.getMonth() + 1, |
|
||||
'd+': date.getDate(), |
|
||||
'h+': date.getHours(), |
|
||||
'm+': date.getMinutes(), |
|
||||
's+': date.getSeconds(), |
|
||||
}; |
|
||||
for (let k in o) { |
|
||||
if (new RegExp(`(${k})`).test(fmt)) { |
|
||||
let str = o[k] + ''; |
|
||||
fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str)); |
|
||||
} |
|
||||
} |
|
||||
return fmt; |
|
||||
}; |
|
||||
const padLeftZero = str => { |
|
||||
return ('00' + str).substr(str.length); |
|
||||
}; |
|
||||
|
|
||||
// 判断是不是date对象
|
|
||||
export const judgeType = s => { |
|
||||
// 函数返回数据的具体类型
|
|
||||
return Object.prototype.toString.call(s).slice(8, -1); |
|
||||
}; |
|
||||
|
|
||||
export const equalDate = (d1, d2) => { |
|
||||
let result = false; |
|
||||
if (d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate()) { |
|
||||
result = true; |
|
||||
} |
|
||||
return result; |
|
||||
}; |
|
||||
|
|
||||
/* 比较时间,时间格式为2020-04-04 |
|
||||
*/ |
|
||||
export const dateEqual = (before, after) => { |
|
||||
before = new Date(before.replace('-', '/').replace('-', '/')); |
|
||||
after = new Date(after.replace('-', '/').replace('-', '/')); |
|
||||
if (before.getTime() - after.getTime() === 0) { |
|
||||
return true; |
|
||||
} else { |
|
||||
return false; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
export const gegerateDates = (date = new Date(), type = 'week') => { |
|
||||
const result = []; |
|
||||
if (judgeType(date) === 'Date') { |
|
||||
// 年,月,日
|
|
||||
const y = date.getFullYear(); |
|
||||
const m = date.getMonth(); |
|
||||
const d = date.getDate(); |
|
||||
const days = new Date(y, m + 1, 0).getDate(); |
|
||||
// 获取日期是星期几
|
|
||||
// let weekIndex = date.getDay() === 0 ? 7 : date.getDay();
|
|
||||
let weekIndex = date.getDay(); |
|
||||
if (type === 'month') { |
|
||||
const dobj = new Date(y, m, 1); |
|
||||
// weekIndex = dobj.getDay() === 0 ? 7 : dobj.getDay();
|
|
||||
weekIndex = dobj.getDay(); |
|
||||
} |
|
||||
if (type === 'week') { |
|
||||
for (let i = weekIndex; i > 0; i--) { |
|
||||
const dtemp = new Date(y, m, d); |
|
||||
dtemp.setDate(dtemp.getDate() - i); |
|
||||
result.push({ |
|
||||
time: dtemp, |
|
||||
show: true, |
|
||||
fullDate: formatDate(dtemp, 'yyyy-MM-dd'), |
|
||||
isToday: equalDate(new Date(), dtemp), |
|
||||
}); |
|
||||
} |
|
||||
for (let i = 0; i <= 7 - weekIndex; i++) { |
|
||||
const dtemp = new Date(y, m, d); |
|
||||
dtemp.setDate(dtemp.getDate() + i); |
|
||||
result.push({ |
|
||||
time: dtemp, |
|
||||
show: true, |
|
||||
fullDate: formatDate(dtemp, 'yyyy-MM-dd'), |
|
||||
isToday: equalDate(new Date(), dtemp), |
|
||||
}); |
|
||||
} |
|
||||
} else if (type === 'month') { |
|
||||
// 上个月
|
|
||||
for (let i = weekIndex; i > 0; i--) { |
|
||||
const dtemp = new Date(y, m, 1); |
|
||||
dtemp.setDate(dtemp.getDate() - i); |
|
||||
result.push({ |
|
||||
time: dtemp, |
|
||||
show: false, |
|
||||
fullDate: formatDate(dtemp, 'yyyy-MM-dd'), |
|
||||
isToday: equalDate(new Date(), dtemp), |
|
||||
}); |
|
||||
} |
|
||||
// 这个月的日期
|
|
||||
for (let i = 0; i < days; i++) { |
|
||||
const dtemp = new Date(y, m, 1); |
|
||||
dtemp.setDate(dtemp.getDate() + i); |
|
||||
result.push({ |
|
||||
time: dtemp, |
|
||||
show: true, |
|
||||
fullDate: formatDate(dtemp, 'yyyy-MM-dd'), |
|
||||
isToday: equalDate(new Date(), dtemp), |
|
||||
}); |
|
||||
} |
|
||||
const len = 42 - result.length; |
|
||||
// 下个月的日期
|
|
||||
for (let i = 1; i <= len; i++) { |
|
||||
const dtemp = new Date(y, m + 1, 0); |
|
||||
dtemp.setDate(dtemp.getDate() + i); |
|
||||
result.push({ |
|
||||
time: dtemp, |
|
||||
show: false, |
|
||||
fullDate: formatDate(dtemp, 'yyyy-MM-dd'), |
|
||||
isToday: equalDate(new Date(), dtemp), |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return result; |
|
||||
}; |
|
@ -0,0 +1,87 @@ |
|||||
|
<template> |
||||
|
<view class="my-3" v-if="allMembers && allMembers.length"> |
||||
|
<view class="flex justify-between"> |
||||
|
<view class="flex flex-wrap text-center items-center"> |
||||
|
<u-tag |
||||
|
:type="member.checked ? 'primary' : 'info'" |
||||
|
:mode="member.checked ? 'dark' : 'light'" |
||||
|
v-for="(member, index) in topMembers" |
||||
|
:key="member.memberId" |
||||
|
class="mb-2 mr-3" |
||||
|
style="width: 60px" |
||||
|
:text="member.name" |
||||
|
:closeable="false" |
||||
|
@click="tagClick(index, member, 'topMembers')" |
||||
|
/> |
||||
|
<span class="ml-2" v-if="!show" @click="show = true">...</span> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 折叠起来的 --> |
||||
|
<view class="flex flex-wrap text-center items-center" v-if="show"> |
||||
|
<u-tag |
||||
|
:type="member.checked ? 'primary' : 'info'" |
||||
|
:mode="member.checked ? 'dark' : 'light'" |
||||
|
v-for="(member, index) in bottomMembers" |
||||
|
:key="member.memberId" |
||||
|
class="mb-2 mr-3" |
||||
|
style="width: 60px" |
||||
|
:text="member.name" |
||||
|
:closeable="false" |
||||
|
@click="tagClick(index, member, 'bottomMembers')" |
||||
|
/> |
||||
|
<u-icon class="ml-2" name="arrow-up" v-if="show" size="26" @click="show = false"></u-icon> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapState } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
checkerList: { |
||||
|
default: () => [], |
||||
|
type: Array, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { allMembers: [], show: false, topMembers: [], bottomMembers: [] }; |
||||
|
}, |
||||
|
|
||||
|
computed: mapState('role', ['members']), |
||||
|
|
||||
|
mounted() { |
||||
|
if (this.members && this.members.length) { |
||||
|
this.allMembers = this.members; |
||||
|
// TODO: 等后台返回默认检查人后修改 |
||||
|
this.allMembers.forEach(item => { |
||||
|
item.checked = false; |
||||
|
}); |
||||
|
this.topMembers = this.members.slice(0, 3); |
||||
|
this.bottomMembers = this.members.slice(3); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
tagClick(index, item, membersType) { |
||||
|
// 点击选择或取消选择 |
||||
|
const arr = this.$u.deepClone(this[membersType]); |
||||
|
arr[index].checked = !arr[index].checked; |
||||
|
this[membersType] = [...arr]; |
||||
|
// 将选中的id传给checkerList |
||||
|
this.$emit('setCheckerList', arr[index].checked, item); |
||||
|
}, |
||||
|
|
||||
|
// 清空所有选中的检查人 |
||||
|
clearChecked() { |
||||
|
for (let i = 0; i < this.topMembers.length; i++) { |
||||
|
this.topMembers[i].checked = false; |
||||
|
} |
||||
|
for (let i = 0; i < this.bottomMembers.length; i++) { |
||||
|
this.bottomMembers[i].checked = false; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
@ -0,0 +1,87 @@ |
|||||
|
<template> |
||||
|
<view class="my-3" v-if="allMembers && allMembers.length"> |
||||
|
<view class="flex justify-between"> |
||||
|
<view class="flex flex-wrap text-center items-center"> |
||||
|
<u-tag |
||||
|
:type="member.checked ? 'primary' : 'info'" |
||||
|
:mode="member.checked ? 'dark' : 'light'" |
||||
|
v-for="(member, index) in topMembers" |
||||
|
:key="member.memberId" |
||||
|
class="mb-2 mr-3" |
||||
|
style="width: 60px" |
||||
|
:text="member.name" |
||||
|
:closeable="false" |
||||
|
@click="tagClick(index, member, 'topMembers')" |
||||
|
/> |
||||
|
<span class="ml-2" v-if="!show" @click="show = true">...</span> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 折叠起来的 --> |
||||
|
<view class="flex flex-wrap text-center items-center" v-if="show"> |
||||
|
<u-tag |
||||
|
:type="member.checked ? 'primary' : 'info'" |
||||
|
:mode="member.checked ? 'dark' : 'light'" |
||||
|
v-for="(member, index) in bottomMembers" |
||||
|
:key="member.memberId" |
||||
|
class="mb-2 mr-3" |
||||
|
style="width: 60px" |
||||
|
:text="member.name" |
||||
|
:closeable="false" |
||||
|
@click="tagClick(index, member, 'bottomMembers')" |
||||
|
/> |
||||
|
<u-icon class="ml-2" name="arrow-up" v-if="show" size="26" @click="show = false"></u-icon> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapState } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
checkerList: { |
||||
|
default: () => [], |
||||
|
type: Array, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { allMembers: [], show: false, topMembers: [], bottomMembers: [] }; |
||||
|
}, |
||||
|
|
||||
|
computed: mapState('role', ['members']), |
||||
|
|
||||
|
mounted() { |
||||
|
if (this.members && this.members.length) { |
||||
|
this.allMembers = this.members; |
||||
|
// TODO: 等后台返回默认检查人后修改 |
||||
|
this.allMembers.forEach(item => { |
||||
|
item.checked = false; |
||||
|
}); |
||||
|
this.topMembers = this.members.slice(0, 3); |
||||
|
this.bottomMembers = this.members.slice(3); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
tagClick(index, item, membersType) { |
||||
|
// 点击选择或取消选择 |
||||
|
const arr = this.$u.deepClone(this[membersType]); |
||||
|
arr[index].checked = !arr[index].checked; |
||||
|
this[membersType] = [...arr]; |
||||
|
// 将选中的id传给checkerList |
||||
|
this.$emit('setCheckerList', arr[index].checked, item); |
||||
|
}, |
||||
|
|
||||
|
// 清空所有选中的检查人 |
||||
|
clearChecked() { |
||||
|
for (let i = 0; i < this.topMembers.length; i++) { |
||||
|
this.topMembers[i].checked = false; |
||||
|
} |
||||
|
for (let i = 0; i < this.bottomMembers.length; i++) { |
||||
|
this.bottomMembers[i].checked = false; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
@ -0,0 +1,101 @@ |
|||||
|
<template> |
||||
|
<view class="input-group flex-1"> |
||||
|
<input :placeholder="placeholder" @input="search" @blur="hideList" v-model="backName" /> |
||||
|
<view class="ul"> |
||||
|
<view class="li" v-for="(item, index) in dataSource" :key="index" @tap="select(item)">{{ item.name }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: { |
||||
|
placeholder: String, //默认提示 |
||||
|
searchKey: String, //模糊搜索的key值 |
||||
|
dataSource: { |
||||
|
type: Array, |
||||
|
default: function () { |
||||
|
//数据源 |
||||
|
return []; |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
list: [], |
||||
|
name: '', |
||||
|
backName: '', |
||||
|
}; |
||||
|
}, |
||||
|
destroyed() { |
||||
|
clearTimeout(this.t); |
||||
|
}, |
||||
|
methods: { |
||||
|
search(e) { |
||||
|
let val = e.detail.value; |
||||
|
console.log('val: ', val); |
||||
|
this.$emit('searchPrevTask', val); |
||||
|
|
||||
|
// let arr = []; |
||||
|
// for (let i = 0; i < dataSource.length; i++) { |
||||
|
// if (dataSource[i].name.indexOf(val) !== -1) { |
||||
|
// arr.push(dataSource[i]); |
||||
|
// } |
||||
|
// } |
||||
|
// if (!val) { |
||||
|
// this.list = []; |
||||
|
// } else { |
||||
|
// this.list = arr; |
||||
|
// } |
||||
|
}, |
||||
|
|
||||
|
select(item) { |
||||
|
console.log('item: ', item); |
||||
|
this.backName = item.name; |
||||
|
this.$emit('select', item); |
||||
|
}, |
||||
|
|
||||
|
hideList() { |
||||
|
setTimeout(() => { |
||||
|
this.$emit('clearAllTasks'); |
||||
|
}, 200); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.input-group { |
||||
|
position: relative; |
||||
|
|
||||
|
input { |
||||
|
border-bottom: 1upx solid #dcdfe6; |
||||
|
height: 90upx; |
||||
|
padding-left: 10upx; |
||||
|
font-size: 30upx; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.uni-input-placeholder { |
||||
|
color: rgb(192, 196, 204); |
||||
|
font-size: 28upx; |
||||
|
} |
||||
|
|
||||
|
.ul { |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 100%; |
||||
|
width: 100%; |
||||
|
z-index: 999; |
||||
|
background: #fff; |
||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
||||
|
max-height: 100px; |
||||
|
overflow-y: auto; |
||||
|
|
||||
|
.li { |
||||
|
border-bottom: 1upx solid #f1f1f1; |
||||
|
padding: 16upx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -1,7 +0,0 @@ |
|||||
<template> |
|
||||
<view class="flex items-center justify-between"> |
|
||||
这是子项目 |
|
||||
</template> |
|
||||
<script> |
|
||||
export default {}; |
|
||||
</script> |
|
@ -1,72 +0,0 @@ |
|||||
<template> |
|
||||
<view class="py-3 mt-4 bg-white u-font-15"> |
|
||||
<view v-for="(project, index) in projects" :key="index"> |
|
||||
<!-- 有子项目 --> |
|
||||
<view class="flex items-center justify-between p-3"> |
|
||||
<view class="text-blue-400 border border-blue-200 rounded-full order bg-blue-50"> |
|
||||
{{ index + 1 }} |
|
||||
</view> |
|
||||
|
|
||||
<view class="flex-1 px-3"> |
|
||||
<view class="flex items-center mb-1"> |
|
||||
<view class="mr-2">{{ project.name }}</view> |
|
||||
<!-- 状态 TODO:--> |
|
||||
<view class="px-2 text-xs text-green-400 bg-green-100 rounded-full">进行中</view> |
|
||||
</view> |
|
||||
|
|
||||
<view class="flex items-center text-xs text-gray-400"> |
|
||||
<view class="pr-2">{{ $moment(+project.startTime).format('MM-DD HH:mm') }}</view> |
|
||||
至 |
|
||||
<view class="pl-2"> {{ $moment(+project.endTime).format('MM-DD HH:mm') }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 箭头 --> |
|
||||
<u-icon name="arrow-right" class="text-gray-400" size="14px" @click="openProject(project)"></u-icon> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { mapGetters, mapState } from 'vuex'; |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return {}; |
|
||||
}, |
|
||||
|
|
||||
computed: { |
|
||||
...mapState('project', ['projects']), |
|
||||
...mapGetters('user', ['userId']), |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
/** |
|
||||
* 打开项目 |
|
||||
* @param {object} project 所点击的项目的信息 |
|
||||
*/ |
|
||||
openProject(project) { |
|
||||
const { name, id, url } = project; |
|
||||
url && (uni.$t.domain = url); |
|
||||
this.$u.route('pages/project/project', { |
|
||||
u: this.userId, |
|
||||
p: id, |
|
||||
pname: name, |
|
||||
url: encodeURIComponent(url), |
|
||||
}); |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.order { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
width: 32px; |
|
||||
height: 32px; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
</style> |
|
@ -1,45 +0,0 @@ |
|||||
<template> |
|
||||
<view> |
|
||||
<nav-bar title="骨架屏"></nav-bar> |
|
||||
<view class="content"> |
|
||||
基础用法 |
|
||||
<skeleton :row="3" animate :loading="loading"> |
|
||||
<view> content1 </view> |
|
||||
</skeleton> |
|
||||
显示 title |
|
||||
<skeleton :row="3" title animate :loading="loading"> |
|
||||
<view> content2 </view> |
|
||||
</skeleton> |
|
||||
显示头像(上面) |
|
||||
<skeleton :avatar="avatarTop" :row="3" animate :loading="loading" style="margin-top: 24rpx"> |
|
||||
<view> content3 </view> |
|
||||
</skeleton> |
|
||||
显示头像(左面) |
|
||||
<skeleton title :avatar="avatarLeft" :row="3" animate :loading="loading" style="margin-top: 24rpx"> |
|
||||
<view> content4 </view> |
|
||||
</skeleton> |
|
||||
显示banner |
|
||||
<skeleton banner :row="0" animate :loading="loading" style="margin-top: 24rpx"> |
|
||||
<view> content5 </view> |
|
||||
</skeleton> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
loading: true, // 是否显示骨架屏组件 |
|
||||
avatarTop: 'top', |
|
||||
avatarLeft: 'left', |
|
||||
}; |
|
||||
}, |
|
||||
onLoad() { |
|
||||
// 通过延时模拟向后端请求数据,调隐藏骨架屏 |
|
||||
setTimeout(() => { |
|
||||
this.loading = false; |
|
||||
}, 3000); |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
@ -1 +0,0 @@ |
|||||
Subproject commit 2603a0bc8b5036c399a5f28b93586072c4850c4b |
|
@ -1,11 +1,189 @@ |
|||||
<template> |
<template> |
||||
<view class="flex justify-between" style="min-width: 90px"> |
<view> |
||||
<u-icon custom-prefix="custom-icon" name="C-bxl-redux" size="17px"></u-icon> |
<view class="flex justify-between" style="min-width: 90px; position: relative"> |
||||
<u-icon custom-prefix="custom-icon" name="attachment" size="21px"></u-icon> |
<u-icon custom-prefix="custom-icon" name="C-bxl-redux" size="17px"></u-icon> |
||||
<u-icon custom-prefix="custom-icon" name="moneycollect" size="20px"></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> --> |
||||
|
<u-icon name="xuanxiang" custom-prefix="custom-icon" size="21px" @click="operation"></u-icon> |
||||
|
|
||||
|
<!-- 右上角 ... 弹窗 --> |
||||
|
<view class="popup border shadow-md" v-if="show"> |
||||
|
<!-- <view class="flex justify-center pb-3 border-b-1"> |
||||
|
<span>添加插件</span> |
||||
|
</view> --> |
||||
|
<view class="flex justify-center pb-3 border-b-1"> |
||||
|
<span @click="createTask">新建任务</span> |
||||
|
</view> |
||||
|
<view class="flex pt-3 justify-center"> |
||||
|
<span>克隆任务</span> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 遮罩 --> |
||||
|
<view class="mask" v-if="maskShow" @click="closeMask"></view> |
||||
|
<!-- 新建任务弹窗 --> |
||||
|
<CreateTask |
||||
|
:startTime="startTime" |
||||
|
:endTime="endTime" |
||||
|
:task="task" |
||||
|
:source="'regular'" |
||||
|
@showTime="showTime" |
||||
|
@closeMask="closeMask" |
||||
|
class="thirdPopup flex transition-transform" |
||||
|
v-if="createTaskShow" |
||||
|
/> |
||||
|
|
||||
|
<u-picker title="开始时间" mode="time" v-model="showStart" :params="params" @confirm="confirmStartTime"></u-picker> |
||||
|
<u-picker title="结束时间" mode="time" v-model="showEnd" :params="params" @confirm="confirmEndTime"></u-picker> |
||||
</view> |
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
export default {}; |
import CreateTask from '../../Title/components/CreateTask.vue'; |
||||
|
|
||||
|
export default { |
||||
|
components: { CreateTask }, |
||||
|
|
||||
|
props: { |
||||
|
task: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
show: false, //右上角 ... 显示 |
||||
|
createTaskShow: false, //新建项目显示 |
||||
|
secondShow: false, //分享项目显示 |
||||
|
maskShow: false, //遮罩显示 |
||||
|
showStart: false, |
||||
|
showEnd: false, |
||||
|
startTime: '', // 新建任务的开始时间 |
||||
|
endTime: '', // 新建任务的截止时间 |
||||
|
params: { |
||||
|
year: true, |
||||
|
month: true, |
||||
|
day: true, |
||||
|
hour: true, |
||||
|
minute: true, |
||||
|
second: true, |
||||
|
}, |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
//操作 |
||||
|
operation() { |
||||
|
// this.$t.ui.showToast('操作'); |
||||
|
this.show = !this.show; |
||||
|
}, |
||||
|
|
||||
|
// 新建项目 |
||||
|
createTask() { |
||||
|
// 关闭 ... 弹窗 |
||||
|
this.show = false; |
||||
|
// 打开遮罩 |
||||
|
this.maskShow = true; |
||||
|
// 打开新建项目弹窗 |
||||
|
this.createTaskShow = true; |
||||
|
}, |
||||
|
|
||||
|
//点击遮罩,关闭弹窗 |
||||
|
closeMask() { |
||||
|
// 关闭遮罩 |
||||
|
this.maskShow = false; |
||||
|
// 关闭分享项目弹窗 |
||||
|
this.secondShow = false; |
||||
|
// 关闭新建项目弹窗 |
||||
|
this.createTaskShow = false; |
||||
|
}, |
||||
|
|
||||
|
showTime() { |
||||
|
this.showStart = !this.showStart; |
||||
|
}, |
||||
|
|
||||
|
// 选择开始时间 |
||||
|
confirmStartTime(e) { |
||||
|
this.startTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}:${e.second}`; |
||||
|
this.showEnd = true; |
||||
|
}, |
||||
|
|
||||
|
// 选择结束时间 |
||||
|
confirmEndTime(e) { |
||||
|
this.endTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}:${e.second}`; |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
</script> |
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.mask { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
z-index: 21; |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
background: rgba(0, 0, 0, 0.3); |
||||
|
} |
||||
|
|
||||
|
.thirdPopup { |
||||
|
background: #ffffff; |
||||
|
position: fixed; |
||||
|
left: 50%; |
||||
|
top: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
z-index: 33; |
||||
|
border-radius: 5px; |
||||
|
width: 90%; |
||||
|
} |
||||
|
|
||||
|
.popup { |
||||
|
width: 110px; |
||||
|
background: #fff; |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
top: 35px; |
||||
|
z-index: 99; |
||||
|
padding: 15px 0; |
||||
|
color: black; |
||||
|
animation: opacity 1s ease-in; |
||||
|
} |
||||
|
|
||||
|
@keyframes opacity { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
50% { |
||||
|
opacity: 0.8; |
||||
|
} |
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-slot-content { |
||||
|
min-width: 0; |
||||
|
} |
||||
|
::v-deep .u-dropdown__content { |
||||
|
min-height: 120px !important; |
||||
|
height: auto !important; |
||||
|
overflow-y: auto; |
||||
|
background: #fff !important; |
||||
|
transition: none !important; |
||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
::v-deep .u-dropdown__menu__item .u-flex { |
||||
|
justify-content: space-between; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
flex-wrap: nowrap; |
||||
|
border: 1px solid #afbed1; |
||||
|
padding: 0 8px; |
||||
|
} |
||||
|
::v-deep .u-dropdown__content__mask { |
||||
|
display: none; |
||||
|
} |
||||
|
</style> |
||||
|
@ -0,0 +1,466 @@ |
|||||
|
<template> |
||||
|
<div class="new-projects-box"> |
||||
|
<div class="form"> |
||||
|
<!-- 项目名称 --> |
||||
|
<view class="mb-3 font-bold text-base flex justify-center text-black">新建任务</view> |
||||
|
<div class="flex items-center mb-2"> |
||||
|
<div>名称<span class="text-red-500">*</span>:</div> |
||||
|
<u-input max-length="5" v-model="name" :type="type" :border="border" /> |
||||
|
</div> |
||||
|
<!-- 起止时间 --> |
||||
|
<div class="mb-2"> |
||||
|
<div>起止时间:</div> |
||||
|
<u-input placeholder="请选择起止时间" v-model="timeValue" :type="type" :border="border" @click="$emit('showTime')" /> |
||||
|
</div> |
||||
|
<!-- 多选框 --> |
||||
|
<div class="flex justify-between items-center"> |
||||
|
<div>负责人<span class="text-red-500">*</span>:</div> |
||||
|
<div class="flex-1" v-if="hasRole">{{ roleName }}</div> |
||||
|
<div label="负责人" class="flex-1" v-else> |
||||
|
<u-dropdown disabled ref="uDropdown" placeholder="请选择负责人"> |
||||
|
<u-dropdown-item :title="roleList"> |
||||
|
<view class="slot-content bg-white"> |
||||
|
<div |
||||
|
class="flex flex-row justify-between mb-1 drop-item" |
||||
|
v-for="(role, roleIndex) in roleOptions" |
||||
|
:key="roleIndex" |
||||
|
@click="change(roleIndex)" |
||||
|
> |
||||
|
<view v-model="role.id">{{ role.name }}</view> |
||||
|
<u-icon v-if="role.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon> |
||||
|
</div> |
||||
|
</view> |
||||
|
</u-dropdown-item> |
||||
|
</u-dropdown> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- 下拉图标 --> |
||||
|
<div class="flex justify-center my-6"> |
||||
|
<u-icon v-if="arrow" name="arrow-down" size="28" @click="openDropdown"></u-icon> |
||||
|
<u-icon v-else name="arrow-up" size="28" @click="closeSecondDropdown"></u-icon> |
||||
|
</div> |
||||
|
<!-- 下拉框的内容 --> |
||||
|
<div v-if="show" class="mb-6"> |
||||
|
<!-- 描述 --> |
||||
|
<div class="flex items-center mb-2"> |
||||
|
<div>描述:</div> |
||||
|
<u-input v-model="description" max-length="48" type="textarea" height="36" auto-height :border="border" /> |
||||
|
</div> |
||||
|
<!-- 所属项目 --> |
||||
|
<div class="w flex items-center mb-2"> |
||||
|
<div>所属项目<span class="text-red-500">*</span>:</div> |
||||
|
<div>{{ project.name }}</div> |
||||
|
</div> |
||||
|
<!-- 所属任务 --> |
||||
|
<div class="w flex items-center mb-2" v-if="task && task.id"> |
||||
|
<div>所属任务:</div> |
||||
|
<div>{{ task.name }}</div> |
||||
|
</div> |
||||
|
<!-- 上道工序 --> |
||||
|
<div class="flex items-center mb-2"> |
||||
|
<div>上道工序:</div> |
||||
|
<InputSearch |
||||
|
@searchPrevTask="searchPrevTask" |
||||
|
:dataSource="allTasks" |
||||
|
@select="handleChange" |
||||
|
@clearAllTasks="clearAllTasks" |
||||
|
placeholder="请输入上道工序" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- 检查人多选框 --> |
||||
|
<div class="flex justify-between items-center"> |
||||
|
<div>检查人<span class="text-red-500">*</span>:</div> |
||||
|
<div label="检查人" class="flex-1"> |
||||
|
<u-dropdown ref="dropdown"> |
||||
|
<u-dropdown-item :title="checkerList"> |
||||
|
<view class="slot-content bg-white"> |
||||
|
<div |
||||
|
class="flex flex-row justify-between mb-1 drop-item" |
||||
|
v-for="(checkoutOption, Index) in checkoutOptions" |
||||
|
:key="Index" |
||||
|
@click="choose(Index)" |
||||
|
> |
||||
|
<view v-model="checkoutOption.value">{{ checkoutOption.name }}</view> |
||||
|
<u-icon v-if="checkoutOption.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon> |
||||
|
</div> |
||||
|
</view> |
||||
|
</u-dropdown-item> |
||||
|
</u-dropdown> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- 是否是日常任务 --> |
||||
|
<div class="flex justify-between items-center mt-6"> |
||||
|
是否是日常任务: |
||||
|
<u-switch v-model="isGlobal" size="28"></u-switch> |
||||
|
</div> |
||||
|
<div class="mt-6"> |
||||
|
<div>交付物:</div> |
||||
|
<div v-for="(sort, sortIndex) in deliverSort" :key="sortIndex"> |
||||
|
<u-input |
||||
|
@blur="addDeliverInput" |
||||
|
v-model="sort.name" |
||||
|
:placeholder="`交付物名称${sortIndex + 1}`" |
||||
|
:type="type" |
||||
|
:border="border" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="flex items-center mb-6"> |
||||
|
<u-button type="primary" size="medium" @click="setParameters">提交</u-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
startTime: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
endTime: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
task: { |
||||
|
type: Object, |
||||
|
default: null, |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
arrow: true, |
||||
|
show: false, |
||||
|
isGlobal: false, //是否日常任务 |
||||
|
name: '', //名称 |
||||
|
showChooseTime: false, |
||||
|
timeValue: '', //起止时间 |
||||
|
description: '', //描述 |
||||
|
projectShow: false, //所属项目模糊搜索展示 |
||||
|
processTaskId: '', //上道工序 |
||||
|
type: 'text', |
||||
|
border: true, |
||||
|
roleList: undefined, //负责人默认多选 |
||||
|
checkerList: undefined, //检查人默认多选 |
||||
|
roleOptions: [], // 负责人下拉多选列表 |
||||
|
checkoutOptions: [], // 检查人下拉多选列表 |
||||
|
roleIdList: [], // 选中的负责人id |
||||
|
checkerIdList: [], // 选中的检查人id |
||||
|
deliverables: [], // 交付物 |
||||
|
deliverSort: [{ name: '' }], // 交付物排序 |
||||
|
allTasks: [], |
||||
|
roleName: '', // 负责人名字 |
||||
|
hasRole: false, // 有没有负责人 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
...mapState('role', ['visibleRoles', 'roleId']), |
||||
|
...mapState('project', ['project']), |
||||
|
...mapState('task', ['tasks']), |
||||
|
...mapGetters('project', ['projectId']), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
endTime(val) { |
||||
|
if (val) { |
||||
|
this.timeValue = this.startTime + ' 至 ' + val; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
// 获取负责人和检查人列表 |
||||
|
if (this.visibleRoles.length) { |
||||
|
this.visibleRoles.forEach(role => { |
||||
|
role.dropdownShow = false; |
||||
|
role.status = false; |
||||
|
}); |
||||
|
} |
||||
|
this.roleOptions = this.$u.deepClone(this.visibleRoles); |
||||
|
this.checkoutOptions = this.$u.deepClone(this.visibleRoles); |
||||
|
|
||||
|
// 判断有没有负责人 是不是添加子任务 |
||||
|
if (this.roleId) { |
||||
|
const item = this.visibleRoles.find(r => r.id === this.roleId); |
||||
|
if (item) { |
||||
|
this.roleName = item.name; |
||||
|
this.hasRole = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
...mapMutations('task', ['updateTasks']), |
||||
|
...mapActions('task', ['getPermanent']), |
||||
|
|
||||
|
// 负责人下拉多选选中 |
||||
|
change(index) { |
||||
|
let arr = [...this.roleOptions]; |
||||
|
// 选择多选项图标的展示 |
||||
|
arr[index].dropdownShow = !arr[index].dropdownShow; |
||||
|
// 多选展示的改变 |
||||
|
this.roleList = arr[index].name; |
||||
|
let shows = ''; |
||||
|
// 遍历arr,如果选中,添加到多选展示框上 |
||||
|
arr.map(val => { |
||||
|
if (val.dropdownShow === true) { |
||||
|
shows += val.name + ','; |
||||
|
this.roleIdList.push(val.id); |
||||
|
} |
||||
|
}); |
||||
|
this.roleOptions = [...arr]; |
||||
|
// 删除最后的',' |
||||
|
this.roleList = shows.slice(0, shows.length - 1); |
||||
|
}, |
||||
|
|
||||
|
// 检查人下拉多选选中 |
||||
|
choose(index) { |
||||
|
let arr = [...this.checkoutOptions]; |
||||
|
// 选择多选项图标的展示 |
||||
|
arr[index].dropdownShow = !arr[index].dropdownShow; |
||||
|
// 多选展示的改变 |
||||
|
this.checkerList = arr[index].name; |
||||
|
let shows = ''; |
||||
|
// 遍历arr,如果选中,添加到多选展示框上 |
||||
|
arr.map(val => { |
||||
|
if (val.dropdownShow === true) { |
||||
|
shows += val.name + ','; |
||||
|
this.checkerIdList.push(val.id); |
||||
|
} |
||||
|
}); |
||||
|
this.checkoutOptions = [...arr]; |
||||
|
// 删除最后的',' |
||||
|
this.checkerList = shows.slice(0, shows.length - 1); |
||||
|
// this.roleList = arr[value - 1].name; |
||||
|
}, |
||||
|
|
||||
|
// 打开下拉框 |
||||
|
openDropdown() { |
||||
|
this.arrow = !this.arrow; |
||||
|
this.show = true; |
||||
|
}, |
||||
|
|
||||
|
// 关闭下拉框 |
||||
|
closeSecondDropdown() { |
||||
|
this.arrow = !this.arrow; |
||||
|
this.show = false; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 模糊查询 查找项目下的任务 |
||||
|
* @param name 任务名 |
||||
|
* @param projectId 项目id |
||||
|
*/ |
||||
|
async searchPrevTask(val) { |
||||
|
try { |
||||
|
const params = { name: val, projectId: this.projectId }; |
||||
|
const data = await this.$u.api.queryTaskOfProject(params); |
||||
|
this.allTasks = data; |
||||
|
return data; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//用户点击获取的数据 |
||||
|
handleChange(data) { |
||||
|
console.log('data', data); |
||||
|
this.processTaskId = data.detailId; |
||||
|
}, |
||||
|
// 清空模糊查询信息 |
||||
|
clearAllTasks() { |
||||
|
this.allTasks = []; |
||||
|
}, |
||||
|
|
||||
|
// 数组最后一项有值 添加一条交付物输入框 |
||||
|
addDeliverInput() { |
||||
|
if (this.deliverSort[this.deliverSort.length - 1].name) { |
||||
|
this.deliverSort.push({ name: '' }); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 设置提交参数 |
||||
|
async setParameters() { |
||||
|
const { |
||||
|
projectId, |
||||
|
task, |
||||
|
name, |
||||
|
startTime, |
||||
|
endTime, |
||||
|
hasRole, |
||||
|
roleIdList, |
||||
|
roleId, |
||||
|
description, |
||||
|
processTaskId, |
||||
|
checkerIdList, |
||||
|
isGlobal, |
||||
|
} = this; |
||||
|
if (!name) { |
||||
|
this.$t.ui.showToast('请输入名称'); |
||||
|
return; |
||||
|
} |
||||
|
if ((!roleIdList || !roleIdList.length) && !hasRole) { |
||||
|
this.$t.ui.showToast('请选择负责人'); |
||||
|
return; |
||||
|
} |
||||
|
if (!checkerIdList || !checkerIdList.length) { |
||||
|
this.$t.ui.showToast('请选择检查人'); |
||||
|
return; |
||||
|
} |
||||
|
const deliverList = []; |
||||
|
this.deliverSort.forEach(item => { |
||||
|
if (item.name) { |
||||
|
deliverList.push(item.name); |
||||
|
} |
||||
|
}); |
||||
|
const params = { |
||||
|
name, |
||||
|
startTime: startTime ? this.$moment(startTime).format('x') - 0 : '', |
||||
|
endTime: endTime ? this.$moment(endTime).format('x') - 0 : '', |
||||
|
roleIdList: hasRole ? [roleId] : roleIdList, |
||||
|
description, |
||||
|
projectId, |
||||
|
parentTaskId: task && task.id ? task.id : '', // 父任务 |
||||
|
processTaskId, // 上道工序 TODO |
||||
|
checkerIdList, |
||||
|
global: isGlobal ? 1 : 0, |
||||
|
deliverList, |
||||
|
}; |
||||
|
await this.handleSubmit(params); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 新建任务 |
||||
|
* @param name 任务名 |
||||
|
* @param startTime 开始时间 |
||||
|
* @param endTime 结束时间 |
||||
|
* @param roleIdList 负责人id(数组) |
||||
|
* @param description 描述 |
||||
|
* @param projectId 所属项目id |
||||
|
* @param parentTaskId 所属任务id |
||||
|
* @param processTaskId 上道工序(任务id) |
||||
|
* @param checkerIdList 检查人id(数组) |
||||
|
* @param global 是否日常任务 0否 1是 |
||||
|
* @param deliverList 交付物名字(数组) |
||||
|
*/ |
||||
|
async handleSubmit(params) { |
||||
|
try { |
||||
|
const data = await this.$u.api.saveTask(params); |
||||
|
// TODO 任务新建成功 继续 or 取消 |
||||
|
this.$emit('closeMask'); |
||||
|
const newTasks = { |
||||
|
data: data[0], |
||||
|
processTaskId: params.processTaskId, |
||||
|
}; |
||||
|
// 将新加的任务加到store |
||||
|
// 判断不是子任务 |
||||
|
if (!this.task || !this.task.id) { |
||||
|
this.addNewTasks(newTasks); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
this.$emit('closeMask'); |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 添加任务后更新tasks |
||||
|
addNewTasks(data) { |
||||
|
const oldTasks = this.$u.deepClone(this.tasks); |
||||
|
let res = data.data; |
||||
|
console.log('添加任务后更新tasks', data); |
||||
|
// 判断有没有选择上道工序 |
||||
|
if (data.processTaskId) { |
||||
|
const index = oldTasks.find(item => item.detailId === data.processTaskId); |
||||
|
if (index) { |
||||
|
oldTasks.splice(index + 1, 0, res); |
||||
|
} |
||||
|
} else { |
||||
|
this.setAddPosition(res, oldTasks); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 设置添加位置 |
||||
|
setAddPosition(res, oldTasks) { |
||||
|
console.log('设置添加位置', res, oldTasks); |
||||
|
|
||||
|
if (res.planStart - 0 < oldTasks[0].planStart - 0) { |
||||
|
// 开始时间小于列表的第一个 插入最前面 |
||||
|
oldTasks.splice(0, 0, res); |
||||
|
} else if (res.planStart - 0 === oldTasks[0].planStart - 0) { |
||||
|
// 开始时间等于列表的第一个 插入第二 |
||||
|
oldTasks.splice(1, 0, res); |
||||
|
} else if (res.planStart - 0 >= oldTasks[oldTasks.length - 1].planStart - 0) { |
||||
|
// 开始时间大等于列表的最后一个 插入最后 |
||||
|
oldTasks.splice(-1, 0, res); |
||||
|
} else { |
||||
|
// 判断开始时间在列表中间的哪个位置 |
||||
|
for (let i = 0; i < oldTasks.length; i++) { |
||||
|
const item = oldTasks[i]; |
||||
|
if (res.planStart - 0 > item.planStart - 0) { |
||||
|
if (res.planStart - 0 <= oldTasks[i + 1].planStart - 0) { |
||||
|
oldTasks.splice(i + 1, 0, res); |
||||
|
// console.log('res: ', res); |
||||
|
// return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// TODO: 不能全更新 |
||||
|
console.log('oldTasks: ', oldTasks); |
||||
|
this.updateTasks([...oldTasks]); |
||||
|
const params = { roleId: this.roleId, projectId: this.projectId }; |
||||
|
this.getPermanent(params); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.form { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
width: 100%; |
||||
|
max-height: 400px; |
||||
|
overflow-y: scroll; |
||||
|
} |
||||
|
|
||||
|
.drop-item { |
||||
|
border-bottom: 1px solid #f1f1f1; |
||||
|
padding: 16rpx; |
||||
|
} |
||||
|
|
||||
|
::v-deep.u-input--border { |
||||
|
border: none; |
||||
|
border-radius: 0; |
||||
|
} |
||||
|
::v-deep.u-dropdown__menu__item > uni-view { |
||||
|
border: none !important; |
||||
|
padding: 5px; |
||||
|
} |
||||
|
.u-input { |
||||
|
border-bottom: 1px solid #dcdfe6; |
||||
|
} |
||||
|
|
||||
|
.new-projects-box { |
||||
|
margin-top: 20px; |
||||
|
padding: 15px; |
||||
|
width: 100%; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.w { |
||||
|
width: 300px; |
||||
|
height: 39px; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu__item .u-flex { |
||||
|
border: 0 !important; |
||||
|
border-bottom: 1px solid #dcdfe6 !important; |
||||
|
padding: 0 20rpx; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,583 @@ |
|||||
|
<template> |
||||
|
<div class="new-projects-box"> |
||||
|
<div class="form"> |
||||
|
<!-- 项目名称 --> |
||||
|
<view class="new-projects-title font-bold text-base flex justify-center items-center text-black">新建任务</view> |
||||
|
|
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">名称<span class="text-red-500">*</span></div> |
||||
|
<u-input :maxlength="8" v-model="name" type="text" :inputAlign="'right'" :clearable="false" placeholder="请输入任务名称" /> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 开始时间 --> |
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">开始时间<span class="text-red-500" v-if="source === 'regular'">*</span></div> |
||||
|
<div class="flex justify-end items-center flex-1"> |
||||
|
<u-input |
||||
|
placeholder="请选择开始时间" |
||||
|
v-model="startTime" |
||||
|
type="text" |
||||
|
:inputAlign="'right'" |
||||
|
:clearable="false" |
||||
|
@click="$emit('showTime', 1)" |
||||
|
/> |
||||
|
<u-icon class="ml-1" name="arrow-right" color="#969799" size="28"></u-icon> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 结束时间 --> |
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">结束时间<span class="text-red-500" v-if="source === 'regular'">*</span></div> |
||||
|
<div class="flex justify-end items-center flex-1"> |
||||
|
<u-input |
||||
|
placeholder="请选择结束时间" |
||||
|
v-model="endTime" |
||||
|
type="text" |
||||
|
:inputAlign="'right'" |
||||
|
:clearable="false" |
||||
|
@click="$emit('showTime', 2)" |
||||
|
/> |
||||
|
<u-icon class="ml-1" name="arrow-right" color="#969799" size="28"></u-icon> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 多选框 --> |
||||
|
<div class="form-item flex justify-between items-center"> |
||||
|
<div class="mr-4">负责人<span class="text-red-500">*</span></div> |
||||
|
<div class="flex-1 text-right" v-if="hasRole">{{ roleName }}</div> |
||||
|
<div label="负责人" class="flex-1" v-else> |
||||
|
<u-dropdown disabled ref="uDropdown" placeholder="请选择负责人"> |
||||
|
<u-dropdown-item :title="roleList"> |
||||
|
<view class="slot-content bg-white"> |
||||
|
<div |
||||
|
class="flex flex-row justify-between mb-1 drop-item" |
||||
|
v-for="(role, roleIndex) in roleOptions" |
||||
|
:key="roleIndex" |
||||
|
@click="change(roleIndex)" |
||||
|
> |
||||
|
<view v-model="role.id">{{ role.name }}</view> |
||||
|
<u-icon v-if="role.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon> |
||||
|
</div> |
||||
|
</view> |
||||
|
</u-dropdown-item> |
||||
|
</u-dropdown> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 描述 --> |
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">描述</div> |
||||
|
<u-input v-model="description" :maxlength="48" type="text" :inputAlign="'right'" :clearable="false" /> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 所属项目 --> |
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">所属项目<span class="text-red-500">*</span></div> |
||||
|
<div class="flex-1 text-right">{{ project.name }}</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 所属任务 --> |
||||
|
<div class="form-item flex items-center" v-if="task && task.id"> |
||||
|
<div class="mr-4">所属任务</div> |
||||
|
<div class="flex-1 text-right">{{ task.name }}</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 上道工序 --> |
||||
|
<div class="form-item flex items-center"> |
||||
|
<div class="mr-4">上道工序</div> |
||||
|
<InputSearch |
||||
|
@searchPrevTask="searchPrevTask" |
||||
|
:dataSource="allTasks" |
||||
|
@select="handleChange" |
||||
|
@clearAllTasks="clearAllTasks" |
||||
|
placeholder="请输入上道工序" |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 检查人多选框 --> |
||||
|
<div class="form-item flex justify-between items-center"> |
||||
|
<div class="mr-4 flex-shrink-0">检查人<span class="text-red-500">*</span></div> |
||||
|
<div label="检查人" class="flex-1" style="width: calc(100% - 65px)"> |
||||
|
<u-dropdown ref="dropdown"> |
||||
|
<u-dropdown-item :title="checkerList"> |
||||
|
<view class="slot-content bg-white"> |
||||
|
<div |
||||
|
class="flex flex-row justify-between mb-1 drop-item" |
||||
|
v-for="(checkoutOption, Index) in checkoutOptions" |
||||
|
:key="Index" |
||||
|
@click="choose(Index)" |
||||
|
> |
||||
|
<view v-model="checkoutOption.value">{{ checkoutOption.name }}</view> |
||||
|
<u-icon v-if="checkoutOption.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon> |
||||
|
</div> |
||||
|
</view> |
||||
|
</u-dropdown-item> |
||||
|
</u-dropdown> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 是否是日常任务 --> |
||||
|
<div class="form-item flex justify-between items-center" v-if="!source"> |
||||
|
是否是日常任务 |
||||
|
<u-switch v-model="isGlobal" size="28"></u-switch> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-item flex justify-between items-center" v-for="(sort, sortIndex) in deliverSort" :key="sortIndex"> |
||||
|
<div class="mr-4">{{ `交付物${sortIndex + 1}` }}</div> |
||||
|
<div class="flex-1"> |
||||
|
<u-input |
||||
|
@blur="addDeliverInput" |
||||
|
v-model="sort.name" |
||||
|
:placeholder="`交付物名称${sortIndex + 1}`" |
||||
|
type="text" |
||||
|
:inputAlign="'right'" |
||||
|
:clearable="false" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- <div class="form-item flex items-center"> |
||||
|
<div class="mr-4">添加插件</div> |
||||
|
<u-input :maxlength="8" v-model="name" type="text" :inputAlign="'right'" :clearable="false" placeholder="选择插件" /> |
||||
|
</div> --> |
||||
|
|
||||
|
<div class="form-btn flex items-center mt-4"> |
||||
|
<u-button type="primary" size="medium" @click="setParameters">提交</u-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
startTime: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
endTime: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
task: { |
||||
|
type: Object, |
||||
|
default: null, |
||||
|
}, |
||||
|
source: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
// arrow: true, |
||||
|
// show: false, |
||||
|
isGlobal: false, //是否日常任务 |
||||
|
name: '', //名称 |
||||
|
// showChooseTime: false, |
||||
|
// timeValue: '', //起止时间 |
||||
|
// taskStartTime: '', // 新建任务开始时间 |
||||
|
// taskEndTime: '', // 新建任务结束时间 |
||||
|
description: '', //描述 |
||||
|
// projectShow: false, //所属项目模糊搜索展示 |
||||
|
processTaskId: '', //上道工序 |
||||
|
// type: 'text', |
||||
|
// border: true, |
||||
|
roleList: undefined, //负责人默认多选 |
||||
|
checkerList: undefined, //检查人默认多选 |
||||
|
roleOptions: [], // 负责人下拉多选列表 |
||||
|
checkoutOptions: [], // 检查人下拉多选列表 |
||||
|
roleIdList: [], // 选中的负责人id |
||||
|
checkerIdList: [], // 选中的检查人id |
||||
|
deliverables: [], // 交付物 |
||||
|
deliverSort: [{ name: '' }], // 交付物排序 |
||||
|
allTasks: [], |
||||
|
roleName: '', // 负责人名字 |
||||
|
hasRole: false, // 有没有负责人 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
...mapState('role', ['visibleRoles', 'roleId']), |
||||
|
...mapState('project', ['project']), |
||||
|
...mapState('task', ['tasks']), |
||||
|
...mapGetters('project', ['projectId']), |
||||
|
}, |
||||
|
|
||||
|
// watch: { |
||||
|
// endTime(val) { |
||||
|
// if (val) { |
||||
|
// this.timeValue = this.startTime + ' 至 ' + val; |
||||
|
// } |
||||
|
// }, |
||||
|
// }, |
||||
|
|
||||
|
mounted() { |
||||
|
// 获取负责人和检查人列表 |
||||
|
if (this.visibleRoles.length) { |
||||
|
this.visibleRoles.forEach(role => { |
||||
|
role.dropdownShow = false; |
||||
|
role.status = false; |
||||
|
}); |
||||
|
} |
||||
|
this.roleOptions = this.$u.deepClone(this.visibleRoles); |
||||
|
this.checkoutOptions = this.$u.deepClone(this.visibleRoles); |
||||
|
|
||||
|
// 判断有没有负责人 是不是添加子任务 |
||||
|
if (this.roleId) { |
||||
|
const item = this.visibleRoles.find(r => r.id === this.roleId); |
||||
|
if (item) { |
||||
|
this.roleName = item.name; |
||||
|
this.hasRole = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
...mapMutations('task', ['updateTasks']), |
||||
|
...mapActions('task', ['getPermanent']), |
||||
|
|
||||
|
// 负责人下拉多选选中 |
||||
|
change(index) { |
||||
|
let arr = [...this.roleOptions]; |
||||
|
// 选择多选项图标的展示 |
||||
|
arr[index].dropdownShow = !arr[index].dropdownShow; |
||||
|
// 多选展示的改变 |
||||
|
this.roleList = arr[index].name; |
||||
|
let shows = ''; |
||||
|
// 遍历arr,如果选中,添加到多选展示框上 |
||||
|
arr.map(val => { |
||||
|
if (val.dropdownShow === true) { |
||||
|
shows += val.name + ','; |
||||
|
this.roleIdList.push(val.id); |
||||
|
} |
||||
|
}); |
||||
|
this.roleOptions = [...arr]; |
||||
|
// 删除最后的',' |
||||
|
this.roleList = shows.slice(0, shows.length - 1); |
||||
|
}, |
||||
|
|
||||
|
// 检查人下拉多选选中 |
||||
|
choose(index) { |
||||
|
let arr = [...this.checkoutOptions]; |
||||
|
// 选择多选项图标的展示 |
||||
|
arr[index].dropdownShow = !arr[index].dropdownShow; |
||||
|
// 多选展示的改变 |
||||
|
this.checkerList = arr[index].name; |
||||
|
let shows = ''; |
||||
|
// 遍历arr,如果选中,添加到多选展示框上 |
||||
|
arr.map(val => { |
||||
|
if (val.dropdownShow === true) { |
||||
|
shows += val.name + ','; |
||||
|
this.checkerIdList.push(val.id); |
||||
|
} |
||||
|
}); |
||||
|
this.checkoutOptions = [...arr]; |
||||
|
// 删除最后的',' |
||||
|
this.checkerList = shows.slice(0, shows.length - 1); |
||||
|
// this.roleList = arr[value - 1].name; |
||||
|
}, |
||||
|
|
||||
|
// 打开下拉框 |
||||
|
// openDropdown() { |
||||
|
// this.arrow = !this.arrow; |
||||
|
// this.show = true; |
||||
|
// }, |
||||
|
|
||||
|
// // 关闭下拉框 |
||||
|
// closeSecondDropdown() { |
||||
|
// this.arrow = !this.arrow; |
||||
|
// this.show = false; |
||||
|
// }, |
||||
|
|
||||
|
/** |
||||
|
* 模糊查询 查找项目下的任务 |
||||
|
* @param name 任务名 |
||||
|
* @param projectId 项目id |
||||
|
*/ |
||||
|
async searchPrevTask(val) { |
||||
|
try { |
||||
|
const params = { name: val, projectId: this.projectId }; |
||||
|
const data = await this.$u.api.queryTaskOfProject(params); |
||||
|
this.allTasks = data; |
||||
|
return data; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//用户点击获取的数据 |
||||
|
handleChange(data) { |
||||
|
console.log('data', data); |
||||
|
this.processTaskId = data.detailId; |
||||
|
}, |
||||
|
// 清空模糊查询信息 |
||||
|
clearAllTasks() { |
||||
|
this.allTasks = []; |
||||
|
}, |
||||
|
|
||||
|
// 数组最后一项有值 添加一条交付物输入框 |
||||
|
addDeliverInput() { |
||||
|
if (this.deliverSort[this.deliverSort.length - 1].name) { |
||||
|
this.deliverSort.push({ name: '' }); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 设置提交参数 |
||||
|
async setParameters() { |
||||
|
if (this.source) { |
||||
|
this.isGlobal = 0; |
||||
|
} |
||||
|
|
||||
|
const { |
||||
|
projectId, |
||||
|
task, |
||||
|
name, |
||||
|
startTime, |
||||
|
endTime, |
||||
|
hasRole, |
||||
|
roleIdList, |
||||
|
roleId, |
||||
|
description, |
||||
|
processTaskId, |
||||
|
checkerIdList, |
||||
|
isGlobal, |
||||
|
} = this; |
||||
|
if (!name) { |
||||
|
this.$t.ui.showToast('请输入任务名称'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!isGlobal) { |
||||
|
if (!startTime) { |
||||
|
this.$t.ui.showToast('定期任务时间不能为空'); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (startTime && endTime) { |
||||
|
let start = startTime ? this.$moment(startTime).format('x') - 0 : ''; |
||||
|
let end = endTime ? this.$moment(endTime).format('x') - 0 : ''; |
||||
|
if (start > end) { |
||||
|
this.$t.ui.showToast('结束时间不能小于开始时间'); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ((!roleIdList || !roleIdList.length) && !hasRole) { |
||||
|
this.$t.ui.showToast('请选择负责人'); |
||||
|
return; |
||||
|
} |
||||
|
if (!checkerIdList || !checkerIdList.length) { |
||||
|
this.$t.ui.showToast('请选择检查人'); |
||||
|
return; |
||||
|
} |
||||
|
const deliverList = []; |
||||
|
this.deliverSort.forEach(item => { |
||||
|
if (item.name) { |
||||
|
deliverList.push(item.name); |
||||
|
} |
||||
|
}); |
||||
|
const params = { |
||||
|
name, |
||||
|
startTime: startTime ? this.$moment(startTime).format('x') - 0 : '', |
||||
|
endTime: endTime ? this.$moment(endTime).format('x') - 0 : '', |
||||
|
roleIdList: hasRole ? [roleId] : roleIdList, |
||||
|
description, |
||||
|
projectId, |
||||
|
parentTaskId: task && task.process !== 4 && task.id ? task.id : '', // 父任务 |
||||
|
processTaskId, // 上道工序 TODO |
||||
|
checkerIdList, |
||||
|
global: isGlobal ? 1 : 0, |
||||
|
deliverList, |
||||
|
}; |
||||
|
await this.handleSubmit(params); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 新建任务 |
||||
|
* @param name 任务名 |
||||
|
* @param startTime 开始时间 |
||||
|
* @param endTime 结束时间 |
||||
|
* @param roleIdList 负责人id(数组) |
||||
|
* @param description 描述 |
||||
|
* @param projectId 所属项目id |
||||
|
* @param parentTaskId 所属任务id |
||||
|
* @param processTaskId 上道工序(任务id) |
||||
|
* @param checkerIdList 检查人id(数组) |
||||
|
* @param global 是否日常任务 0否 1是 |
||||
|
* @param deliverList 交付物名字(数组) |
||||
|
*/ |
||||
|
async handleSubmit(params) { |
||||
|
try { |
||||
|
const data = await this.$u.api.saveTask(params); |
||||
|
// TODO 任务新建成功 继续 or 取消 |
||||
|
this.$emit('closeMask'); |
||||
|
const newTasks = { |
||||
|
data: data[0], |
||||
|
processTaskId: params.processTaskId, |
||||
|
}; |
||||
|
// 将新加的任务加到store |
||||
|
// 判断不是子任务 -- 暂无子任务,暂不判断 |
||||
|
// if (!this.task || !this.task.id || this.task.process === 4) { |
||||
|
// this.addNewTasks(newTasks); |
||||
|
// } |
||||
|
|
||||
|
this.addNewTasks(newTasks); |
||||
|
} catch (error) { |
||||
|
this.$emit('closeMask'); |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 添加任务后更新tasks |
||||
|
addNewTasks(data) { |
||||
|
const oldTasks = this.$u.deepClone(this.tasks); |
||||
|
let res = data.data; |
||||
|
|
||||
|
// 判断有没有选择上道工序 |
||||
|
if (data.processTaskId) { |
||||
|
const index = oldTasks.find(item => item.detailId === data.processTaskId); |
||||
|
if (index) { |
||||
|
oldTasks.splice(index + 1, 0, res); |
||||
|
} |
||||
|
} else { |
||||
|
this.setAddPosition(res, oldTasks); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 设置添加位置 |
||||
|
setAddPosition(res, oldTasks) { |
||||
|
if (res.planStart - 0 < oldTasks[0].planStart - 0) { |
||||
|
// 开始时间小于列表的第一个 插入最前面 |
||||
|
oldTasks.splice(0, 0, res); |
||||
|
} else if (res.planStart - 0 === oldTasks[0].planStart - 0) { |
||||
|
// 开始时间等于列表的第一个 插入第二 |
||||
|
oldTasks.splice(1, 0, res); |
||||
|
} else if (res.planStart - 0 >= oldTasks[oldTasks.length - 1].planStart - 0) { |
||||
|
// 开始时间大等于列表的最后一个 插入最后 |
||||
|
oldTasks.splice(-1, 0, res); |
||||
|
} else { |
||||
|
// 判断开始时间在列表中间的哪个位置 |
||||
|
for (let i = 0; i < oldTasks.length; i++) { |
||||
|
const item = oldTasks[i]; |
||||
|
if (res.planStart - 0 > item.planStart - 0) { |
||||
|
if (res.planStart - 0 <= oldTasks[i + 1].planStart - 0) { |
||||
|
oldTasks.splice(i + 1, 0, res); |
||||
|
// console.log('res: ', res); |
||||
|
// return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// TODO: 不能全更新 |
||||
|
console.log('oldTasks: ', oldTasks); |
||||
|
this.updateTasks([...oldTasks]); |
||||
|
const params = { roleId: this.roleId, projectId: this.projectId }; |
||||
|
this.getPermanent(params); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.form { |
||||
|
// display: flex; |
||||
|
// flex-direction: column; |
||||
|
width: 100%; |
||||
|
max-height: 400px; |
||||
|
overflow-y: scroll; |
||||
|
} |
||||
|
|
||||
|
.drop-item { |
||||
|
border-bottom: 1px solid #f1f1f1; |
||||
|
padding: 16rpx 32rpx; |
||||
|
} |
||||
|
|
||||
|
// ::v-deep.u-input--border { |
||||
|
// border: none; |
||||
|
// border-radius: 0; |
||||
|
// padding: 0 !important; |
||||
|
// } |
||||
|
::v-deep.u-dropdown__menu__item > uni-view { |
||||
|
border: none !important; |
||||
|
padding: 5px; |
||||
|
} |
||||
|
// .u-input { |
||||
|
// border-bottom: 1px solid #dcdfe6; |
||||
|
// } |
||||
|
|
||||
|
.new-projects-box { |
||||
|
margin-top: 20px; |
||||
|
// padding: 15px; |
||||
|
width: 100%; |
||||
|
overflow: hidden; |
||||
|
color: #595959; |
||||
|
} |
||||
|
|
||||
|
.new-projects-title { |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.form-item { |
||||
|
padding: 0 16px; |
||||
|
height: 48px; |
||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.form-item ::v-deep .input-group uni-input { |
||||
|
border: 0; |
||||
|
font-size: 14px; |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.form-btn { |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.form-btn .u-btn { |
||||
|
width: 156px; |
||||
|
height: 32px; |
||||
|
font-size: 16px; |
||||
|
border-radius: 4px; |
||||
|
} |
||||
|
|
||||
|
.w { |
||||
|
width: 300px; |
||||
|
height: 39px; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu { |
||||
|
height: 48px !important; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu__item { |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu__item .u-flex { |
||||
|
border: 0 !important; |
||||
|
// border-bottom: 1px solid #dcdfe6 !important; |
||||
|
padding: 0 !important; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu__item__arrow { |
||||
|
margin-left: 10px; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__menu__item__text { |
||||
|
width: calc(100% - 23px); |
||||
|
text-align: right; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-dropdown__content { |
||||
|
top: 48px !important; |
||||
|
box-shadow: 0 4px 6px 1px rgba(0, 0, 0, 0.1) !important; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,210 @@ |
|||||
|
<template> |
||||
|
<view class="flex justify-center"> |
||||
|
<view class="content p-3 pb-8"> |
||||
|
<view class="mb-3 font-bold text-base flex justify-center">创建分享链接</view> |
||||
|
<view class="flex flex-col"> |
||||
|
<view class="mb-1">用户以什么角色加入项目</view> |
||||
|
<!-- 下拉多选 --> |
||||
|
<view class="uni-list"> |
||||
|
<view class="uni-list-cell"> |
||||
|
<view class="uni-list-cell-db ml-2" v-if="rolesArray.length"> |
||||
|
<picker @change="changeRole" :value="index" :range="rolesArray"> |
||||
|
<view class="uni-input">{{ allRolesName[index].name }}</view> |
||||
|
</picker> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 复制链接 --> |
||||
|
<view class="link flex items-center mt-4"> |
||||
|
<view class="link-url">{{ links }}</view> |
||||
|
<u-button |
||||
|
style="border-radius: 0; height: 100%" |
||||
|
type="primary" |
||||
|
v-clipboard:copy="copyText" |
||||
|
v-clipboard:success="copySuccess" |
||||
|
v-clipboard:error="copyError" |
||||
|
> |
||||
|
复制链接 |
||||
|
</u-button> |
||||
|
</view> |
||||
|
<view @click="select"> |
||||
|
<!-- 全选按钮 --> |
||||
|
<!-- <view class="flex mt-4"> |
||||
|
<view> |
||||
|
<u-checkbox-group> |
||||
|
<u-checkbox v-model="checked" @change="checkedAll"></u-checkbox> |
||||
|
</u-checkbox-group> |
||||
|
</view> |
||||
|
<view>已选择({{ this.quantity }})</view> |
||||
|
<view style="color: #f37378; margin-left: 20px">批量删除</view> |
||||
|
</view> --> |
||||
|
<!-- 多选框 --> |
||||
|
<!-- <view> |
||||
|
<u-checkbox-group class="checkboxs flex flex-1 items-center mt-4" v-for="(item, index) in list" :key="index"> |
||||
|
<div class="flex-1 flex items-center"> |
||||
|
<u-checkbox v-model="item.checked"></u-checkbox> |
||||
|
<u-avatar :src="item.src" size="55" style="background: #d8dce0; margin-right: 10px"></u-avatar> |
||||
|
<div style="width: 60%; font-size: 12px"> |
||||
|
<div style="color: gray">{{ item.name }}</div> |
||||
|
<div style="color: #c4d0e1">{{ item.joinMethod }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</u-checkbox-group> |
||||
|
</view> --> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapGetters, mapState } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
rolesArray: [], |
||||
|
allRolesName: [], |
||||
|
index: 0, |
||||
|
links: '', //复制的链接 |
||||
|
copyText: '', |
||||
|
checked: false, //全选按钮是否选中 |
||||
|
roleName: '观众', |
||||
|
// 多选框列表 |
||||
|
list: [ |
||||
|
{ |
||||
|
name: '冯老师', |
||||
|
src: '', |
||||
|
joinMethod: '文件创建者', |
||||
|
role: '观众', |
||||
|
checked: false, |
||||
|
disabled: false, |
||||
|
}, |
||||
|
{ |
||||
|
name: '马壮', |
||||
|
src: '', |
||||
|
joinMethod: '通过链接加入', |
||||
|
role: '干系人', |
||||
|
checked: false, |
||||
|
disabled: false, |
||||
|
}, |
||||
|
{ |
||||
|
name: '张野', |
||||
|
src: '', |
||||
|
joinMethod: '通过链接加入', |
||||
|
role: '观众', |
||||
|
checked: false, |
||||
|
disabled: false, |
||||
|
}, |
||||
|
], |
||||
|
quantity: 0, //多选里面已选择的数量 |
||||
|
path: '', |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
...mapState('role', ['visibleRoles', 'invisibleRoles']), |
||||
|
...mapState('project', ['project']), |
||||
|
...mapGetters('project', ['projectId']), |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.path = window.location.href.split('?')[0]; |
||||
|
const { path, projectId } = this; |
||||
|
const params = { path: `${path}`, projectId, roleId: '0' }; |
||||
|
this.creatShare(params); |
||||
|
}); |
||||
|
|
||||
|
if (this.visibleRoles.length || this.invisibleRoles.length) { |
||||
|
const arr = this.visibleRoles.concat(this.invisibleRoles); |
||||
|
arr.forEach(role => { |
||||
|
let item = { id: '', name: '' }; |
||||
|
item.id = role.id; |
||||
|
item.name = role.name; |
||||
|
this.allRolesName.push(item); |
||||
|
this.rolesArray.push(role.name); |
||||
|
}); |
||||
|
const firstItem = { id: '0', name: '观众' }; |
||||
|
this.allRolesName.unshift(firstItem); |
||||
|
this.rolesArray.unshift('观众'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 选择角色 |
||||
|
async changeRole(e) { |
||||
|
this.index = e.target.value; |
||||
|
this.roleName = this.allRolesName[this.index].name; |
||||
|
const { path, projectId } = this; |
||||
|
const params = { path, projectId, roleId: this.allRolesName[this.index].id }; |
||||
|
await this.creatShare(params); |
||||
|
}, |
||||
|
|
||||
|
// 复制成功 |
||||
|
copySuccess() { |
||||
|
this.$t.ui.showToast('复制成功'); |
||||
|
}, |
||||
|
// 复制失败 |
||||
|
copyError() { |
||||
|
this.$t.ui.showToast('复制失败,请稍后重试'); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 创建分享链接 |
||||
|
* @param path 路径前缀 |
||||
|
* @param projectId 项目id |
||||
|
* @param roleId 角色id |
||||
|
*/ |
||||
|
async creatShare(params) { |
||||
|
try { |
||||
|
const data = await this.$u.api.createShare(params); |
||||
|
this.links = data.path; |
||||
|
this.copyText = `邀请您加入${this.project.name}的项目,角色为${this.roleName},链接为${data.path}&url=${this.$t.domain}`; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
//已选择 |
||||
|
select() { |
||||
|
this.quantity = 0; |
||||
|
this.list.forEach(val => { |
||||
|
if (val.checked == true) { |
||||
|
this.quantity++; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 全选 |
||||
|
checkedAll() { |
||||
|
this.list.map(val => { |
||||
|
val.checked = !this.checked; |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.content { |
||||
|
width: 100%; |
||||
|
max-height: 400px; |
||||
|
} |
||||
|
|
||||
|
.link { |
||||
|
height: 40px; |
||||
|
border: 1px solid #afbed1; |
||||
|
} |
||||
|
|
||||
|
.link-url { |
||||
|
color: #afbed1; |
||||
|
width: 80%; |
||||
|
line-height: 40px; |
||||
|
margin-left: 5px; |
||||
|
overflow: hidden; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,22 @@ |
|||||
|
export default { |
||||
|
created() { |
||||
|
if (this.type === 'message') { |
||||
|
// 不显示遮罩
|
||||
|
this.maskShow = false; |
||||
|
// 获取子组件对象
|
||||
|
this.childrenMsg = null; |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
customOpen() { |
||||
|
if (this.childrenMsg) { |
||||
|
this.childrenMsg.open(); |
||||
|
} |
||||
|
}, |
||||
|
customClose() { |
||||
|
if (this.childrenMsg) { |
||||
|
this.childrenMsg.close(); |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,23 @@ |
|||||
|
import message from './message.js'; |
||||
|
// 定义 type 类型:弹出类型:top/bottom/center
|
||||
|
const config = { |
||||
|
// 顶部弹出
|
||||
|
top: 'top', |
||||
|
// 底部弹出
|
||||
|
bottom: 'bottom', |
||||
|
// 居中弹出
|
||||
|
center: 'center', |
||||
|
// 消息提示
|
||||
|
message: 'top', |
||||
|
// 对话框
|
||||
|
dialog: 'center', |
||||
|
// 分享
|
||||
|
share: 'bottom', |
||||
|
}; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { config: config }; |
||||
|
}, |
||||
|
mixins: [message], |
||||
|
}; |
@ -0,0 +1,246 @@ |
|||||
|
<template> |
||||
|
<view class="uni-popup-dialog"> |
||||
|
<view class="uni-dialog-title"> |
||||
|
<text class="uni-dialog-title-text" :class="['uni-popup__' + dialogType]">{{ title }}</text> |
||||
|
</view> |
||||
|
<view class="uni-dialog-content"> |
||||
|
<text class="uni-dialog-content-text" v-if="mode === 'base'">{{ content }}</text> |
||||
|
<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" /> |
||||
|
</view> |
||||
|
<view class="uni-dialog-button-group"> |
||||
|
<view class="uni-dialog-button" @click="close"> |
||||
|
<text class="uni-dialog-button-text">取消</text> |
||||
|
</view> |
||||
|
<view class="uni-dialog-button uni-border-left" @click="onOk"> |
||||
|
<text class="uni-dialog-button-text uni-button-color">确定</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
/** |
||||
|
* PopUp 弹出层-对话框样式 |
||||
|
* @description 弹出层-对话框样式 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
||||
|
* @property {String} value input 模式下的默认值 |
||||
|
* @property {String} placeholder input 模式下输入提示 |
||||
|
* @property {String} type = [success|warning|info|error] 主题样式 |
||||
|
* @value success 成功 |
||||
|
* @value warning 提示 |
||||
|
* @value info 消息 |
||||
|
* @value error 错误 |
||||
|
* @property {String} mode = [base|input] 模式、 |
||||
|
* @value base 基础对话框 |
||||
|
* @value input 可输入对话框 |
||||
|
* @property {String} content 对话框内容 |
||||
|
* @property {Boolean} beforeClose 是否拦截取消事件 |
||||
|
* @event {Function} confirm 点击确认按钮触发 |
||||
|
* @event {Function} close 点击取消按钮触发 |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
name: 'uniPopupDialog', |
||||
|
props: { |
||||
|
value: { |
||||
|
type: [String, Number], |
||||
|
default: '', |
||||
|
}, |
||||
|
placeholder: { |
||||
|
type: [String, Number], |
||||
|
default: '请输入内容', |
||||
|
}, |
||||
|
/** |
||||
|
* 对话框主题 success/warning/info/error 默认 success |
||||
|
*/ |
||||
|
type: { |
||||
|
type: String, |
||||
|
default: 'error', |
||||
|
}, |
||||
|
/** |
||||
|
* 对话框模式 base/input |
||||
|
*/ |
||||
|
mode: { |
||||
|
type: String, |
||||
|
default: 'base', |
||||
|
}, |
||||
|
/** |
||||
|
* 对话框标题 |
||||
|
*/ |
||||
|
title: { |
||||
|
type: String, |
||||
|
default: '提示', |
||||
|
}, |
||||
|
/** |
||||
|
* 对话框内容 |
||||
|
*/ |
||||
|
content: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
/** |
||||
|
* 拦截取消事件 ,如果拦截取消事件,必须监听close事件,执行 done() |
||||
|
*/ |
||||
|
beforeClose: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
dialogType: 'error', |
||||
|
focus: false, |
||||
|
val: '', |
||||
|
}; |
||||
|
}, |
||||
|
inject: ['popup'], |
||||
|
watch: { |
||||
|
type(val) { |
||||
|
this.dialogType = val; |
||||
|
}, |
||||
|
mode(val) { |
||||
|
if (val === 'input') { |
||||
|
this.dialogType = 'info'; |
||||
|
} |
||||
|
}, |
||||
|
value(val) { |
||||
|
this.val = val; |
||||
|
}, |
||||
|
}, |
||||
|
created() { |
||||
|
// 对话框遮罩不可点击 |
||||
|
this.popup.mkclick = false; |
||||
|
if (this.mode === 'input') { |
||||
|
this.dialogType = 'info'; |
||||
|
this.val = this.value; |
||||
|
} else { |
||||
|
this.dialogType = this.type; |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.focus = true; |
||||
|
}, |
||||
|
methods: { |
||||
|
/** |
||||
|
* 点击确认按钮 |
||||
|
*/ |
||||
|
onOk() { |
||||
|
this.$emit( |
||||
|
'confirm', |
||||
|
() => { |
||||
|
this.popup.close(); |
||||
|
if (this.mode === 'input') this.val = this.value; |
||||
|
}, |
||||
|
this.mode === 'input' ? this.val : '', |
||||
|
); |
||||
|
}, |
||||
|
/** |
||||
|
* 点击取消按钮 |
||||
|
*/ |
||||
|
close() { |
||||
|
if (this.beforeClose) { |
||||
|
this.$emit('close', () => { |
||||
|
this.popup.close(); |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
this.popup.close(); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.uni-popup-dialog { |
||||
|
width: 300px; |
||||
|
border-radius: 15px; |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-title { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
padding-top: 15px; |
||||
|
padding-bottom: 5px; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-title-text { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-content { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
padding: 5px 15px 15px 15px; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-content-text { |
||||
|
font-size: 14px; |
||||
|
color: #6e6e6e; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-button-group { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
border-top-color: #f5f5f5; |
||||
|
border-top-style: solid; |
||||
|
border-top-width: 1px; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-button { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
|
||||
|
flex: 1; |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
height: 45px; |
||||
|
} |
||||
|
|
||||
|
.uni-border-left { |
||||
|
border-left-color: #f0f0f0; |
||||
|
border-left-style: solid; |
||||
|
border-left-width: 1px; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-button-text { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.uni-button-color { |
||||
|
color: $uni-color-primary; |
||||
|
} |
||||
|
|
||||
|
.uni-dialog-input { |
||||
|
flex: 1; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__success { |
||||
|
color: $uni-color-success; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__warn { |
||||
|
color: $uni-color-warning; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__error { |
||||
|
color: $uni-color-error; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__info { |
||||
|
color: #909399; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,115 @@ |
|||||
|
<template> |
||||
|
<view class="uni-popup-message" :class="'uni-popup__' + [type]"> |
||||
|
<text class="uni-popup-message-text" :class="'uni-popup__' + [type] + '-text'">{{ message }}</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
/** |
||||
|
* PopUp 弹出层-消息提示 |
||||
|
* @description 弹出层-消息提示 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
||||
|
* @property {String} type = [success|warning|info|error] 主题样式 |
||||
|
* @value success 成功 |
||||
|
* @value warning 提示 |
||||
|
* @value info 消息 |
||||
|
* @value error 错误 |
||||
|
* @property {String} message 消息提示文字 |
||||
|
* @property {String} duration 显示时间,设置为 0 则不会自动关闭 |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
name: 'UniPopupMessage', |
||||
|
props: { |
||||
|
/** |
||||
|
* 主题 success/warning/info/error 默认 success |
||||
|
*/ |
||||
|
type: { |
||||
|
type: String, |
||||
|
default: 'success', |
||||
|
}, |
||||
|
/** |
||||
|
* 消息文字 |
||||
|
*/ |
||||
|
message: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
/** |
||||
|
* 显示时间,设置为 0 则不会自动关闭 |
||||
|
*/ |
||||
|
duration: { |
||||
|
type: Number, |
||||
|
default: 3000, |
||||
|
}, |
||||
|
}, |
||||
|
inject: ['popup'], |
||||
|
data() { |
||||
|
return {}; |
||||
|
}, |
||||
|
created() { |
||||
|
this.popup.childrenMsg = this; |
||||
|
}, |
||||
|
methods: { |
||||
|
open() { |
||||
|
if (this.duration === 0) return; |
||||
|
clearTimeout(this.popuptimer); |
||||
|
this.popuptimer = setTimeout(() => { |
||||
|
this.popup.close(); |
||||
|
}, this.duration); |
||||
|
}, |
||||
|
close() { |
||||
|
clearTimeout(this.popuptimer); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
<style lang="scss" scoped> |
||||
|
.uni-popup-message { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
background-color: #e1f3d8; |
||||
|
padding: 10px 15px; |
||||
|
border-color: #eee; |
||||
|
border-style: solid; |
||||
|
border-width: 1px; |
||||
|
} |
||||
|
.uni-popup-message-text { |
||||
|
font-size: 14px; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__success { |
||||
|
background-color: #e1f3d8; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__success-text { |
||||
|
color: #67c23a; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__warn { |
||||
|
background-color: #faecd8; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__warn-text { |
||||
|
color: #e6a23c; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__error { |
||||
|
background-color: #fde2e2; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__error-text { |
||||
|
color: #f56c6c; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__info { |
||||
|
background-color: #f2f6fc; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__info-text { |
||||
|
color: #909399; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,171 @@ |
|||||
|
<template> |
||||
|
<view class="uni-popup-share"> |
||||
|
<view class="uni-share-title"> |
||||
|
<text class="uni-share-title-text">{{ title }}</text> |
||||
|
</view> |
||||
|
<view class="uni-share-content"> |
||||
|
<view class="uni-share-content-box"> |
||||
|
<view class="uni-share-content-item" v-for="(item, index) in bottomData" :key="index" @click.stop="select(item, index)"> |
||||
|
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image> |
||||
|
<text class="uni-share-text">{{ item.text }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="uni-share-button-box"> |
||||
|
<button class="uni-share-button" @click="close">取消</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'UniPopupShare', |
||||
|
props: { |
||||
|
title: { |
||||
|
type: String, |
||||
|
default: '分享到', |
||||
|
}, |
||||
|
}, |
||||
|
inject: ['popup'], |
||||
|
data() { |
||||
|
return { |
||||
|
bottomData: [ |
||||
|
{ |
||||
|
text: '微信', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-2.png', |
||||
|
name: 'wx', |
||||
|
}, |
||||
|
{ |
||||
|
text: '支付宝', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-8.png', |
||||
|
name: 'wx', |
||||
|
}, |
||||
|
{ |
||||
|
text: 'QQ', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/gird-3.png', |
||||
|
name: 'qq', |
||||
|
}, |
||||
|
{ |
||||
|
text: '新浪', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-1.png', |
||||
|
name: 'sina', |
||||
|
}, |
||||
|
{ |
||||
|
text: '百度', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-7.png', |
||||
|
name: 'copy', |
||||
|
}, |
||||
|
{ |
||||
|
text: '其他', |
||||
|
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-5.png', |
||||
|
name: 'more', |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
}, |
||||
|
created() {}, |
||||
|
methods: { |
||||
|
/** |
||||
|
* 选择内容 |
||||
|
*/ |
||||
|
select(item, index) { |
||||
|
this.$emit( |
||||
|
'select', |
||||
|
{ |
||||
|
item, |
||||
|
index, |
||||
|
}, |
||||
|
() => { |
||||
|
this.popup.close(); |
||||
|
}, |
||||
|
); |
||||
|
}, |
||||
|
/** |
||||
|
* 关闭窗口 |
||||
|
*/ |
||||
|
close() { |
||||
|
this.popup.close(); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
<style lang="scss" scoped> |
||||
|
.uni-popup-share { |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
.uni-share-title { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 40px; |
||||
|
} |
||||
|
.uni-share-title-text { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
} |
||||
|
.uni-share-content { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
padding-top: 10px; |
||||
|
} |
||||
|
|
||||
|
.uni-share-content-box { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
flex-wrap: wrap; |
||||
|
width: 360px; |
||||
|
} |
||||
|
|
||||
|
.uni-share-content-item { |
||||
|
width: 90px; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
padding: 10px 0; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.uni-share-content-item:active { |
||||
|
background-color: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
.uni-share-image { |
||||
|
width: 30px; |
||||
|
height: 30px; |
||||
|
} |
||||
|
|
||||
|
.uni-share-text { |
||||
|
margin-top: 10px; |
||||
|
font-size: 14px; |
||||
|
color: #3b4144; |
||||
|
} |
||||
|
|
||||
|
.uni-share-button-box { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
padding: 10px 15px; |
||||
|
} |
||||
|
|
||||
|
.uni-share-button { |
||||
|
flex: 1; |
||||
|
border-radius: 50px; |
||||
|
color: #666; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.uni-share-button::after { |
||||
|
border-radius: 50px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,289 @@ |
|||||
|
<template> |
||||
|
<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" @touchmove.stop.prevent="clear"> |
||||
|
<uni-transition v-if="maskShow" :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" /> |
||||
|
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap"> |
||||
|
<view class="uni-popup__wrapper-box" @click.stop="clear"> |
||||
|
<slot /> |
||||
|
</view> |
||||
|
</uni-transition> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import uniTransition from '../uni-transition/uni-transition.vue'; |
||||
|
import popup from './popup.js'; |
||||
|
/** |
||||
|
* PopUp 弹出层 |
||||
|
* @description 弹出层组件,为了解决遮罩弹层的问题 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
||||
|
* @property {String} type = [top|center|bottom] 弹出方式 |
||||
|
* @value top 顶部弹出 |
||||
|
* @value center 中间弹出 |
||||
|
* @value bottom 底部弹出 |
||||
|
* @value message 消息提示 |
||||
|
* @value dialog 对话框 |
||||
|
* @value share 底部分享示例 |
||||
|
* @property {Boolean} animation = [ture|false] 是否开启动画 |
||||
|
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗 |
||||
|
* @event {Function} change 打开关闭弹窗触发,e={show: false} |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
name: 'UniPopup', |
||||
|
components: { uniTransition }, |
||||
|
props: { |
||||
|
// 开启动画 |
||||
|
animation: { |
||||
|
type: Boolean, |
||||
|
default: true, |
||||
|
}, |
||||
|
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层 |
||||
|
// message: 消息提示 ; dialog : 对话框 |
||||
|
type: { |
||||
|
type: String, |
||||
|
default: 'center', |
||||
|
}, |
||||
|
// maskClick |
||||
|
maskClick: { |
||||
|
type: Boolean, |
||||
|
default: true, |
||||
|
}, |
||||
|
}, |
||||
|
provide() { |
||||
|
return { popup: this }; |
||||
|
}, |
||||
|
mixins: [popup], |
||||
|
watch: { |
||||
|
/** |
||||
|
* 监听type类型 |
||||
|
*/ |
||||
|
type: { |
||||
|
handler: function (newVal) { |
||||
|
this[this.config[newVal]](); |
||||
|
}, |
||||
|
immediate: true, |
||||
|
}, |
||||
|
/** |
||||
|
* 监听遮罩是否可点击 |
||||
|
* @param {Object} val |
||||
|
*/ |
||||
|
maskClick(val) { |
||||
|
this.mkclick = val; |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
duration: 300, |
||||
|
ani: [], |
||||
|
showPopup: false, |
||||
|
showTrans: false, |
||||
|
maskClass: { |
||||
|
position: 'fixed', |
||||
|
bottom: 0, |
||||
|
top: 0, |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
backgroundColor: 'rgba(0, 0, 0, 0.4)', |
||||
|
}, |
||||
|
transClass: { |
||||
|
position: 'fixed', |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
}, |
||||
|
maskShow: true, |
||||
|
mkclick: true, |
||||
|
popupstyle: 'top', |
||||
|
}; |
||||
|
}, |
||||
|
created() { |
||||
|
this.mkclick = this.maskClick; |
||||
|
if (this.animation) { |
||||
|
this.duration = 300; |
||||
|
} else { |
||||
|
this.duration = 0; |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
clear(e) { |
||||
|
// TODO nvue 取消冒泡 |
||||
|
e.stopPropagation(); |
||||
|
}, |
||||
|
open() { |
||||
|
this.showPopup = true; |
||||
|
this.$nextTick(() => { |
||||
|
new Promise(resolve => { |
||||
|
clearTimeout(this.timer); |
||||
|
this.timer = setTimeout(() => { |
||||
|
this.showTrans = true; |
||||
|
// fixed by mehaotian 兼容 app 端 |
||||
|
this.$nextTick(() => { |
||||
|
resolve(); |
||||
|
}); |
||||
|
}, 50); |
||||
|
}).then(res => { |
||||
|
console.log('res: ', res); |
||||
|
// 自定义打开事件 |
||||
|
clearTimeout(this.msgtimer); |
||||
|
this.msgtimer = setTimeout(() => { |
||||
|
this.customOpen && this.customOpen(); |
||||
|
}, 100); |
||||
|
this.$emit('change', { |
||||
|
show: true, |
||||
|
type: this.type, |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
close(type) { |
||||
|
this.showTrans = false; |
||||
|
this.$nextTick(() => { |
||||
|
this.$emit('change', { |
||||
|
show: false, |
||||
|
type, |
||||
|
}); |
||||
|
clearTimeout(this.timer); |
||||
|
// 自定义关闭事件 |
||||
|
this.customOpen && this.customClose(); |
||||
|
this.timer = setTimeout(() => { |
||||
|
this.showPopup = false; |
||||
|
}, 300); |
||||
|
}); |
||||
|
}, |
||||
|
onTap() { |
||||
|
if (!this.mkclick) return; |
||||
|
this.close(); |
||||
|
}, |
||||
|
/** |
||||
|
* 顶部弹出样式处理 |
||||
|
*/ |
||||
|
top() { |
||||
|
this.popupstyle = 'top'; |
||||
|
this.ani = ['slide-top']; |
||||
|
this.transClass = { |
||||
|
position: 'fixed', |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
}; |
||||
|
}, |
||||
|
/** |
||||
|
* 底部弹出样式处理 |
||||
|
*/ |
||||
|
bottom() { |
||||
|
this.popupstyle = 'bottom'; |
||||
|
this.ani = ['slide-bottom']; |
||||
|
this.transClass = { |
||||
|
position: 'fixed', |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
bottom: 0, |
||||
|
}; |
||||
|
}, |
||||
|
/** |
||||
|
* 中间弹出样式处理 |
||||
|
*/ |
||||
|
center() { |
||||
|
this.popupstyle = 'center'; |
||||
|
this.ani = ['zoom-out', 'fade']; |
||||
|
this.transClass = { |
||||
|
position: 'fixed', |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: 'flex', |
||||
|
flexDirection: 'column', |
||||
|
/* #endif */ |
||||
|
bottom: 0, |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
top: 0, |
||||
|
justifyContent: 'center', |
||||
|
alignItems: 'center', |
||||
|
}; |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
<style lang="scss" scoped> |
||||
|
.uni-popup { |
||||
|
position: fixed; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
z-index: 99; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.uni-popup__mask { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
background-color: $uni-bg-color-mask; |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.mask-ani { |
||||
|
transition-property: opacity; |
||||
|
transition-duration: 0.2s; |
||||
|
} |
||||
|
|
||||
|
.uni-top-mask { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.uni-bottom-mask { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.uni-center-mask { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__wrapper { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: block; |
||||
|
/* #endif */ |
||||
|
position: absolute; |
||||
|
} |
||||
|
|
||||
|
.top { |
||||
|
/* #ifdef H5 */ |
||||
|
top: var(--window-top); |
||||
|
/* #endif */ |
||||
|
/* #ifndef H5 */ |
||||
|
top: 0; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.uni-popup__wrapper-box { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: block; |
||||
|
/* #endif */ |
||||
|
position: relative; |
||||
|
/* iphonex 等安全区设置,底部安全区适配 */ |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
padding-bottom: constant(safe-area-inset-bottom); |
||||
|
padding-bottom: env(safe-area-inset-bottom); |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.content-ani { |
||||
|
// transition: transform 0.3s; |
||||
|
transition-property: transform, opacity; |
||||
|
transition-duration: 0.2s; |
||||
|
} |
||||
|
|
||||
|
.uni-top-content { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
.uni-bottom-content { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
.uni-center-content { |
||||
|
transform: scale(1); |
||||
|
opacity: 1; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,276 @@ |
|||||
|
<template> |
||||
|
<view |
||||
|
v-if="isShow" |
||||
|
ref="ani" |
||||
|
class="uni-transition" |
||||
|
:class="[ani.in]" |
||||
|
:style="'transform:' + transform + ';' + stylesObject" |
||||
|
@click="change" |
||||
|
> |
||||
|
<slot></slot> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
// #ifdef APP-NVUE |
||||
|
const animation = uni.requireNativePlugin('animation'); |
||||
|
// #endif |
||||
|
/** |
||||
|
* Transition 过渡动画 |
||||
|
* @description 简单过渡动画组件 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=985 |
||||
|
* @property {Boolean} show = [false|true] 控制组件显示或隐藏 |
||||
|
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型 |
||||
|
* @value fade 渐隐渐出过渡 |
||||
|
* @value slide-top 由上至下过渡 |
||||
|
* @value slide-right 由右至左过渡 |
||||
|
* @value slide-bottom 由下至上过渡 |
||||
|
* @value slide-left 由左至右过渡 |
||||
|
* @value zoom-in 由小到大过渡 |
||||
|
* @value zoom-out 由大到小过渡 |
||||
|
* @property {Number} duration 过渡动画持续时间 |
||||
|
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red` |
||||
|
*/ |
||||
|
export default { |
||||
|
name: 'uniTransition', |
||||
|
props: { |
||||
|
show: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
modeClass: { |
||||
|
type: Array, |
||||
|
default() { |
||||
|
return []; |
||||
|
}, |
||||
|
}, |
||||
|
duration: { |
||||
|
type: Number, |
||||
|
default: 300, |
||||
|
}, |
||||
|
styles: { |
||||
|
type: Object, |
||||
|
default() { |
||||
|
return {}; |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
isShow: false, |
||||
|
transform: '', |
||||
|
ani: { in: '', active: '' }, |
||||
|
}; |
||||
|
}, |
||||
|
watch: { |
||||
|
show: { |
||||
|
handler(newVal) { |
||||
|
if (newVal) { |
||||
|
this.open(); |
||||
|
} else { |
||||
|
this.close(); |
||||
|
} |
||||
|
}, |
||||
|
immediate: true, |
||||
|
}, |
||||
|
}, |
||||
|
computed: { |
||||
|
stylesObject() { |
||||
|
let styles = { |
||||
|
...this.styles, |
||||
|
'transition-duration': this.duration / 1000 + 's', |
||||
|
}; |
||||
|
let transfrom = ''; |
||||
|
for (let i in styles) { |
||||
|
let line = this.toLine(i); |
||||
|
transfrom += line + ':' + styles[i] + ';'; |
||||
|
} |
||||
|
return transfrom; |
||||
|
}, |
||||
|
}, |
||||
|
created() { |
||||
|
// this.timer = null |
||||
|
// this.nextTick = (time = 50) => new Promise(resolve => { |
||||
|
// clearTimeout(this.timer) |
||||
|
// this.timer = setTimeout(resolve, time) |
||||
|
// return this.timer |
||||
|
// }); |
||||
|
}, |
||||
|
methods: { |
||||
|
change() { |
||||
|
this.$emit('click', { detail: this.isShow }); |
||||
|
}, |
||||
|
open() { |
||||
|
clearTimeout(this.timer); |
||||
|
this.isShow = true; |
||||
|
this.transform = ''; |
||||
|
this.ani.in = ''; |
||||
|
for (let i in this.getTranfrom(false)) { |
||||
|
if (i === 'opacity') { |
||||
|
this.ani.in = 'fade-in'; |
||||
|
} else { |
||||
|
this.transform += `${this.getTranfrom(false)[i]} `; |
||||
|
} |
||||
|
} |
||||
|
this.$nextTick(() => { |
||||
|
setTimeout(() => { |
||||
|
this._animation(true); |
||||
|
}, 50); |
||||
|
}); |
||||
|
}, |
||||
|
close() { |
||||
|
clearTimeout(this.timer); |
||||
|
this._animation(false); |
||||
|
}, |
||||
|
_animation(type) { |
||||
|
let styles = this.getTranfrom(type); |
||||
|
// #ifdef APP-NVUE |
||||
|
if (!this.$refs['ani']) return; |
||||
|
animation.transition( |
||||
|
this.$refs['ani'].ref, |
||||
|
{ |
||||
|
styles, |
||||
|
duration: this.duration, //ms |
||||
|
timingFunction: 'ease', |
||||
|
needLayout: false, |
||||
|
delay: 0, //ms |
||||
|
}, |
||||
|
() => { |
||||
|
if (!type) { |
||||
|
this.isShow = false; |
||||
|
} |
||||
|
this.$emit('change', { detail: this.isShow }); |
||||
|
}, |
||||
|
); |
||||
|
// #endif |
||||
|
// #ifndef APP-NVUE |
||||
|
this.transform = ''; |
||||
|
for (let i in styles) { |
||||
|
if (i === 'opacity') { |
||||
|
this.ani.in = `fade-${type ? 'out' : 'in'}`; |
||||
|
} else { |
||||
|
this.transform += `${styles[i]} `; |
||||
|
} |
||||
|
} |
||||
|
this.timer = setTimeout(() => { |
||||
|
if (!type) { |
||||
|
this.isShow = false; |
||||
|
} |
||||
|
this.$emit('change', { detail: this.isShow }); |
||||
|
}, this.duration); |
||||
|
// #endif |
||||
|
}, |
||||
|
getTranfrom(type) { |
||||
|
let styles = { transform: '' }; |
||||
|
this.modeClass.forEach(mode => { |
||||
|
switch (mode) { |
||||
|
case 'fade': |
||||
|
styles.opacity = type ? 1 : 0; |
||||
|
break; |
||||
|
case 'slide-top': |
||||
|
styles.transform += `translateY(${type ? '0' : '-100%'}) `; |
||||
|
break; |
||||
|
case 'slide-right': |
||||
|
styles.transform += `translateX(${type ? '0' : '100%'}) `; |
||||
|
break; |
||||
|
case 'slide-bottom': |
||||
|
styles.transform += `translateY(${type ? '0' : '100%'}) `; |
||||
|
break; |
||||
|
case 'slide-left': |
||||
|
styles.transform += `translateX(${type ? '0' : '-100%'}) `; |
||||
|
break; |
||||
|
case 'zoom-in': |
||||
|
styles.transform += `scale(${type ? 1 : 0.8}) `; |
||||
|
break; |
||||
|
case 'zoom-out': |
||||
|
styles.transform += `scale(${type ? 1 : 1.2}) `; |
||||
|
break; |
||||
|
} |
||||
|
}); |
||||
|
return styles; |
||||
|
}, |
||||
|
_modeClassArr(type) { |
||||
|
let mode = this.modeClass; |
||||
|
if (typeof mode !== 'string') { |
||||
|
let modestr = ''; |
||||
|
mode.forEach(item => { |
||||
|
modestr += item + '-' + type + ','; |
||||
|
}); |
||||
|
return modestr.substr(0, modestr.length - 1); |
||||
|
} else { |
||||
|
return mode + '-' + type; |
||||
|
} |
||||
|
}, |
||||
|
// getEl(el) { |
||||
|
// console.log(el || el.ref || null); |
||||
|
// return el || el.ref || null |
||||
|
// }, |
||||
|
toLine(name) { |
||||
|
return name.replace(/([A-Z])/g, '-$1').toLowerCase(); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.uni-transition { |
||||
|
transition-timing-function: ease; |
||||
|
transition-duration: 0.3s; |
||||
|
transition-property: transform, opacity; |
||||
|
} |
||||
|
|
||||
|
.fade-in { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.fade-active { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.slide-top-in { |
||||
|
/* transition-property: transform, opacity; */ |
||||
|
transform: translateY(-100%); |
||||
|
} |
||||
|
|
||||
|
.slide-top-active { |
||||
|
transform: translateY(0); |
||||
|
/* opacity: 1; */ |
||||
|
} |
||||
|
|
||||
|
.slide-right-in { |
||||
|
transform: translateX(100%); |
||||
|
} |
||||
|
|
||||
|
.slide-right-active { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
|
.slide-bottom-in { |
||||
|
transform: translateY(100%); |
||||
|
} |
||||
|
|
||||
|
.slide-bottom-active { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
.slide-left-in { |
||||
|
transform: translateX(-100%); |
||||
|
} |
||||
|
|
||||
|
.slide-left-active { |
||||
|
transform: translateX(0); |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.zoom-in-in { |
||||
|
transform: scale(0.8); |
||||
|
} |
||||
|
|
||||
|
.zoom-out-active { |
||||
|
transform: scale(1); |
||||
|
} |
||||
|
|
||||
|
.zoom-out-in { |
||||
|
transform: scale(1.2); |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,2 @@ |
|||||
|
// 每页加载颗粒度的个数
|
||||
|
export default { pageCount: 10 }; |
@ -0,0 +1,43 @@ |
|||||
|
// 用户登录client
|
||||
|
export const clients = { mp: 0, h5: 1, android: 2, ios: 3 }; |
||||
|
|
||||
|
// 用户登录类型
|
||||
|
export const types = { |
||||
|
mp: 0, |
||||
|
phone: 1, |
||||
|
email: 2, |
||||
|
username: 3, |
||||
|
wx: 4, |
||||
|
wx_web: 5, |
||||
|
wb: 6, |
||||
|
}; |
||||
|
|
||||
|
// 小程序获取参数
|
||||
|
export const mp = () => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
uni.login({ |
||||
|
provider: 'weixin', |
||||
|
success(res) { |
||||
|
if (res.code) { |
||||
|
const params = { |
||||
|
client: uni.$t.user.clients['mp'], |
||||
|
type: uni.$t.user.types['mp'], |
||||
|
data: { identifier: res.code }, |
||||
|
}; |
||||
|
resolve(params); |
||||
|
} else { |
||||
|
reject(res.errMsg); |
||||
|
} |
||||
|
}, |
||||
|
fail() { |
||||
|
console.log('fail'); |
||||
|
reject('微信登录失败'); |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
export default { |
||||
|
clients, |
||||
|
types, |
||||
|
}; |
@ -1,44 +0,0 @@ |
|||||
import { mapGetters } from 'vuex'; |
|
||||
|
|
||||
const mixin = { |
|
||||
computed: mapGetters('task', ['timeGranularity']), |
|
||||
|
|
||||
methods: { |
|
||||
/** |
|
||||
* 设置时间轴空数据 |
|
||||
* @param {*} startTime |
|
||||
* @param {*} show true 向上加载,false 向下加载 |
|
||||
*/ |
|
||||
setTime(startTime, show) { |
|
||||
let { timeGranularity } = this; |
|
||||
let arr = []; |
|
||||
let str = {}; |
|
||||
if (show) { |
|
||||
for (let i = 10; i > 0; i--) { |
|
||||
str = { |
|
||||
id: this.$u.guid(20, false, 10), |
|
||||
panel: {}, |
|
||||
plugins: [], |
|
||||
process: 4, |
|
||||
planStart: this.$t.time.add(startTime, `-${i}` - 0, timeGranularity).valueOf(), |
|
||||
}; |
|
||||
arr.push(str); |
|
||||
} |
|
||||
} else { |
|
||||
for (let i = 0; i < 10; i++) { |
|
||||
str = { |
|
||||
id: this.$u.guid(20, false, 10), |
|
||||
panel: {}, |
|
||||
plugins: [], |
|
||||
process: 4, |
|
||||
planStart: this.$t.time.add(startTime, i + 1, timeGranularity).valueOf(), |
|
||||
}; |
|
||||
arr.push(str); |
|
||||
} |
|
||||
} |
|
||||
return arr; |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
export default mixin; |
|
@ -0,0 +1,37 @@ |
|||||
|
{ |
||||
|
"pages": [ |
||||
|
{ |
||||
|
"path": "pages/index/index", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom" , |
||||
|
"navigationBarTextStyle": "white" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/project/project", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom" , |
||||
|
"navigationBarTextStyle": "white" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/test/test", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "测试" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"globalStyle": { |
||||
|
"navigationBarTextStyle": "black", |
||||
|
"navigationBarTitleText": "TALL", |
||||
|
"navigationBarBackgroundColor": "#F8F8F8", |
||||
|
"backgroundColor": "#F8F8F8" |
||||
|
}, |
||||
|
"easycom": { |
||||
|
"autoscan": true, |
||||
|
"custom": { |
||||
|
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue", |
||||
|
"^p-(.*)": "@/plugins/p-$1/p-$1.vue" |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,31 +1,24 @@ |
|||||
{ |
{ |
||||
"pages": [ |
"pages": [ |
||||
{ |
{ |
||||
"path": "pages/index/index", |
"path": "pages/project/project", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" , |
"navigationStyle": "custom", |
||||
"navigationBarTextStyle": "white" |
"navigationBarTextStyle": "white" |
||||
} |
} |
||||
}, |
} |
||||
{ |
], |
||||
"path": "pages/project/project", |
"globalStyle": { |
||||
"style": { |
"navigationBarTextStyle": "black", |
||||
"navigationStyle": "custom" , |
"navigationBarTitleText": "TALL", |
||||
"navigationBarTextStyle": "white" |
"navigationBarBackgroundColor": "#F8F8F8", |
||||
} |
"backgroundColor": "#F8F8F8" |
||||
} |
}, |
||||
], |
"easycom": { |
||||
"globalStyle": { |
"autoscan": true, |
||||
"navigationBarTextStyle": "black", |
"custom": { |
||||
"navigationBarTitleText": "TALL", |
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue", |
||||
"navigationBarBackgroundColor": "#F8F8F8", |
"^p-(.*)": "@/plugins/p-$1/p-$1.vue" |
||||
"backgroundColor": "#F8F8F8" |
} |
||||
}, |
} |
||||
"easycom": { |
|
||||
"autoscan": true, |
|
||||
"custom": { |
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue", |
|
||||
"^p-(.*)": "@/plugins/p-$1/p-$1.vue" |
|
||||
} |
|
||||
} |
|
||||
} |
} |
||||
|
@ -1,128 +0,0 @@ |
|||||
<template> |
|
||||
<view class="flex flex-col h-full bg-gray-50" @touchmove="onMove"> |
|
||||
<view class="relative"> |
|
||||
<!-- 日历 --> |
|
||||
<Calendar @selected-change="onDateChange" :show-back="true" ref="calendar" @handleFindPoint="handleFindPoint" /> |
|
||||
<!-- 上传 导入wbs --> |
|
||||
<Upload @success="onUploadSuccess" @error="onUploadError" /> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 项目列表 --> |
|
||||
<Projects class="flex-1 overflow-y-auto" /> |
|
||||
|
|
||||
<!-- 全局提示框 --> |
|
||||
<u-top-tips ref="uTips"></u-top-tips> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { mapState, mapMutations } from 'vuex'; |
|
||||
|
|
||||
let prevY = 0; |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
calendar: null, |
|
||||
days: [], |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
computed: mapState('user', ['token']), |
|
||||
|
|
||||
watch: { |
|
||||
token(value) { |
|
||||
if (!value) return; |
|
||||
this.getProjects(); |
|
||||
this.handleFindPoint(); |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
onShow() { |
|
||||
if (!this.token) return; |
|
||||
this.getProjects(); |
|
||||
this.handleFindPoint(); |
|
||||
}, |
|
||||
|
|
||||
onReady() { |
|
||||
this.calendar = this.$refs.calendar; |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
...mapMutations('project', ['setProjects', 'setDotList']), |
|
||||
|
|
||||
// 获取项目列表 |
|
||||
async getProjects(start = this.$moment().startOf('day').valueOf(), end = this.$moment().endOf('day').valueOf()) { |
|
||||
try { |
|
||||
const data = await this.$u.api.getProjects(start, end); |
|
||||
this.setProjects(data); |
|
||||
} catch (error) { |
|
||||
console.error('error: ', error); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 查询小红点 |
|
||||
* @param { string } endTime 结束时间 |
|
||||
* @param { string } startTime 开始时间 |
|
||||
*/ |
|
||||
async handleFindPoint(start, end) { |
|
||||
try { |
|
||||
const startTime = start || this.$moment().startOf('month').valueOf(); |
|
||||
const endTime = end || this.$moment().endOf('month').valueOf(); |
|
||||
const data = await this.$u.api.findRedPoint(startTime, endTime); |
|
||||
this.setDotList(data); |
|
||||
} catch (error) { |
|
||||
console.log('error: ', error); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 点击了某个日期 |
|
||||
onDateChange(event) { |
|
||||
const day = this.$moment(event.fullDate); |
|
||||
const start = day.startOf('date').valueOf(); |
|
||||
const end = day.endOf('date').valueOf(); |
|
||||
this.getProjects(start, end); |
|
||||
}, |
|
||||
|
|
||||
// 监听触摸滑动 切换日历的模式 月/周 |
|
||||
onMove(event) { |
|
||||
const y = event.changedTouches[0].pageY; |
|
||||
if (y - prevY > 0) { |
|
||||
// 向下滑动 如果是周视图weekMode=true 就 变成 月视图weekMode=false |
|
||||
this.calendar.weekMode && (this.calendar.weekMode = false); |
|
||||
} else if (y - prevY < 0) { |
|
||||
// 向上滑动 如果是月视图weekMode=false 就变成 周视图weekMode=true |
|
||||
!this.calendar.weekMode && (this.calendar.weekMode = true); |
|
||||
} |
|
||||
prevY = y; |
|
||||
this.calendar.initDate(); |
|
||||
}, |
|
||||
|
|
||||
// 导入成功 |
|
||||
onUploadSuccess() { |
|
||||
this.$refs.uTips.show({ |
|
||||
title: '导入成功,即将打开新项目', |
|
||||
type: 'success', |
|
||||
duration: '3000', |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 导入失败 |
|
||||
onUploadError(error) { |
|
||||
this.$refs.uTips.show({ |
|
||||
title: error || '导入失败', |
|
||||
type: 'error', |
|
||||
duration: '6000', |
|
||||
}); |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
page { |
|
||||
height: 100%; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
</style> |
|
@ -1,15 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container p-3"> |
|
||||
<u-button type="primary" @click="add">add</u-button> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
methods: { |
|
||||
add() { |
|
||||
this.$db.create('projects', { id: '123' }); |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
@ -1,7 +1,120 @@ |
|||||
<template> |
<template> |
||||
<view>交付物检查</view> |
<!-- 交付物审核 --> |
||||
|
<view class="examine-popup pt-6 bg-white"> |
||||
|
<view class="text-center pb-6 font-semibold text-lg text-black">{{ auditStatus === 1 ? '审核通过' : '审核驳回' }}</view> |
||||
|
|
||||
|
<view class="px-6"> |
||||
|
<u-input :auto-height="autoHeight" :border="border" :height="height" :type="type" placeholder="输入备注" v-model="remark" /> |
||||
|
<view class="flex flex-row-reverse text-xs text-gray-400 mt-2">{{ wordNum }}/140</view> |
||||
|
|
||||
|
<!-- 评分 --> |
||||
|
<view class="flex justify-between mt-3" v-if="auditStatus === 1"> |
||||
|
<u-input :border="border" :type="type1" @input="changeNumber" maxlength="100" placeholder="输入分数" v-model="score" /> |
||||
|
<slider :value="score" @change="sliderChange" max="100" min="0" show-value style="width: 50%" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="examine-btn flex justify-center mt-5"> |
||||
|
<u-button @click="submit">提交</u-button> |
||||
|
<u-button @click="$emit('closeScore')">取消</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
export default {}; |
export default { |
||||
|
name: 'p-deliver-check', |
||||
|
|
||||
|
props: { |
||||
|
auditStatus: { |
||||
|
type: Number, |
||||
|
default: 1, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
remark: '', |
||||
|
type: 'textarea', |
||||
|
border: true, |
||||
|
height: 100, |
||||
|
autoHeight: true, |
||||
|
wordNum: 0, |
||||
|
score: 0, |
||||
|
type1: 'number', |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
remark(val) { |
||||
|
this.wordNum = val.length; |
||||
|
}, |
||||
|
|
||||
|
score(val) { |
||||
|
this.score1 = val; |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 提交交付物 |
||||
|
submit() { |
||||
|
this.$emit('submit', this.remark, this.score); |
||||
|
}, |
||||
|
|
||||
|
sliderChange(e) { |
||||
|
this.score = e.detail.value; |
||||
|
}, |
||||
|
|
||||
|
changeNumber(e) { |
||||
|
if (e > 100) { |
||||
|
this.score = 100; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
</script> |
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.examine-popup { |
||||
|
width: 85vw; |
||||
|
border-radius: 8px; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
.examine-btn { |
||||
|
border-top: 1px solid rgba(0, 0, 0, 0.1); |
||||
|
|
||||
|
uni-button { |
||||
|
width: 50%; |
||||
|
height: 55px; |
||||
|
border-radius: 0; |
||||
|
border: none; |
||||
|
} |
||||
|
|
||||
|
uni-button:after { |
||||
|
border: none; |
||||
|
width: 200%; |
||||
|
height: 200%; |
||||
|
} |
||||
|
|
||||
|
uni-button:first-child { |
||||
|
border-right: 1px solid rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
uni-slider { |
||||
|
margin-right: 0; |
||||
|
} |
||||
|
|
||||
|
uni-slider ::v-deep .uni-slider-handle, |
||||
|
uni-slider ::v-deep .uni-slider-thumb { |
||||
|
width: 10px !important; |
||||
|
height: 10px !important; |
||||
|
margin-top: -5px !important; |
||||
|
margin-left: -5px !important; |
||||
|
} |
||||
|
|
||||
|
uni-slider ::v-deep .uni-slider-thumb { |
||||
|
box-shadow: 0 0 2px rgba(0, 0, 0, 1); |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
@ -0,0 +1,64 @@ |
|||||
|
<template> |
||||
|
<!-- 交付物审核 --> |
||||
|
<view class="px-3 py-6 bg-white"> |
||||
|
<u-input :auto-height="autoHeight" :border="border" :height="height" :type="type" placeholder="输入备注" v-model="remark" /> |
||||
|
<view class="flex flex-row-reverse text-xs text-gray-400 mt-2">{{ wordNum }}/140</view> |
||||
|
<!-- 评分 --> |
||||
|
<view class="flex justify-between mt-3"> |
||||
|
<slider :value="score" @change="sliderChange" max="100" min="0" show-value style="width: 60%" /> |
||||
|
<u-input :border="border" :type="type1" @input="changeNumber" maxlength="100" placeholder="输入分数" v-model="score" /> |
||||
|
</view> |
||||
|
|
||||
|
<view class="flex flex-col justify-center mt-5"> |
||||
|
<u-button @click="submit" size="medium" type="primary">提交</u-button> |
||||
|
<u-button @click="$emit('closeScore')" class="mt-2" size="medium">取消</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'p-deliver-check', |
||||
|
data() { |
||||
|
return { |
||||
|
remark: '', |
||||
|
type: 'textarea', |
||||
|
border: true, |
||||
|
height: 100, |
||||
|
autoHeight: true, |
||||
|
wordNum: 0, |
||||
|
score: 0, |
||||
|
type1: 'number', |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
remark(val) { |
||||
|
this.wordNum = val.length; |
||||
|
}, |
||||
|
|
||||
|
score(val) { |
||||
|
this.score1 = val; |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 提交交付物 |
||||
|
submit() { |
||||
|
this.$emit('submit', this.remark, this.score); |
||||
|
}, |
||||
|
|
||||
|
sliderChange(e) { |
||||
|
this.score = e.detail.value; |
||||
|
}, |
||||
|
|
||||
|
changeNumber(e) { |
||||
|
if (e > 100) { |
||||
|
this.score = 100; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style></style> |
@ -1,20 +0,0 @@ |
|||||
<template> |
|
||||
<!-- 交付物 --> |
|
||||
<view>交付物</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
name: 'p-deliverable', |
|
||||
props: { item: { type: Object, default: null } }, |
|
||||
data() { |
|
||||
return {}; |
|
||||
}, |
|
||||
|
|
||||
computed: {}, |
|
||||
methods: {}, |
|
||||
watch: {}, |
|
||||
}; |
|
||||
</script> |
|
||||
|
|
||||
<style></style> |
|
@ -0,0 +1,156 @@ |
|||||
|
<template> |
||||
|
<!-- 交付物 --> |
||||
|
<view class="mt-3"> |
||||
|
<view v-if="lists && lists.length"> |
||||
|
<view :key="list.id" v-for="list in lists"> |
||||
|
<view class="text-gray-400 u-font-12 font-thin leading-none"> |
||||
|
<span class="mr-2">{{ list.name }}</span> |
||||
|
<span>{{ $moment(+list.time).format('YYYY-MM-DD HH:mm:ss') }}</span> |
||||
|
</view> |
||||
|
<view class="mt-2 py-1 px-2.5 border border-gray-200 rounded flex flex-wrap overflow-hidden break-all" v-if="list.content"> |
||||
|
<a :href="list.content" class="text-blue-500 u-font-12 font-thin" target="_blank" v-if="CheckUrl(list.content)">{{ |
||||
|
list.content |
||||
|
}}</a> |
||||
|
<span v-else>{{ list.content }}</span> |
||||
|
</view> |
||||
|
<view :class="index === 0 ? 'mt-4' : 'mt-3'" v-for="(checker, index) in list.checkerList" :key="index"> |
||||
|
<view class="flex justify-between leading-none"> |
||||
|
<view> |
||||
|
{{ checker.checkerName }} |
||||
|
<span v-if="checker.isMine">(我)</span> |
||||
|
</view> |
||||
|
<view> |
||||
|
<span class="text-blue-500" v-if="checker.status === 1">通过</span> |
||||
|
<span class="text-red-500" v-if="checker.status === 2">驳回</span> |
||||
|
<span class="ml-4" v-if="checker.status !== 0">{{ checker.score }}分</span> |
||||
|
<span class="text-gray-400" v-if="checker.status === 0 && !checker.isMine">未审核</span> |
||||
|
<view v-if="checker.status === 0 && checker.isMine"> |
||||
|
<u-button class="action-btn mr-2" @click="showScore(checker.checkId, 1)" size="mini" shape="circle" type="primary"> |
||||
|
通过 |
||||
|
</u-button> |
||||
|
<u-button class="action-btn" @click="showScore(checker.checkId, 2)" size="mini" shape="circle" type="error">驳回</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="text-gray-400 text-xs mt-1">{{ checker.remark }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<u-empty icon-size="90" mode="history" text="暂未上传交付物" v-else></u-empty> |
||||
|
|
||||
|
<!-- 评分 --> |
||||
|
<uni-popup :maskClick="false" background-color="#fff" ref="popup" type="center"> |
||||
|
<PDeliverCheck :auditStatus="auditStatus" @closeScore="closeScore" @submit="submit"></PDeliverCheck> |
||||
|
</uni-popup> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapGetters } from 'vuex'; |
||||
|
import UniPopup from '../../components/uni-popup/uni-popup.vue'; |
||||
|
import PDeliverCheck from '../p-deliver-check/p-deliver-check.vue'; |
||||
|
|
||||
|
export default { |
||||
|
name: 'p-delivery-history', |
||||
|
props: { task: { type: Object, default: null } }, |
||||
|
components: { PDeliverCheck, UniPopup }, |
||||
|
data() { |
||||
|
return { |
||||
|
lists: [], |
||||
|
show: false, |
||||
|
options: null, |
||||
|
loading: true, // 是否显示骨架屏组件 |
||||
|
auditStatus: 1, // 审核状态 1 通过 2 驳回 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: mapGetters('project', ['projectId']), |
||||
|
|
||||
|
mounted() { |
||||
|
this.getDeliverOfTask(); |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
async getDeliverOfTask() { |
||||
|
try { |
||||
|
const { projectId, task } = this; |
||||
|
const params = { projectId, taskSubId: task.id }; |
||||
|
const data = await this.$u.api.queryDeliverOfTask(params); |
||||
|
data.forEach(item => { |
||||
|
if (item.filePath) { |
||||
|
item.content = item.filePath; |
||||
|
} |
||||
|
}); |
||||
|
this.lists = data; |
||||
|
} catch (error) { |
||||
|
console.error('p-delivery-history.vue getDeliverOfTask error: ', error); |
||||
|
this.$t.ui.showToast(error.msg || '提交失败'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
showScore(checkId, status) { |
||||
|
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center'] |
||||
|
this.$refs.popup.open(); |
||||
|
this.options = { checkId, status }; |
||||
|
this.auditStatus = status; |
||||
|
}, |
||||
|
|
||||
|
closeScore() { |
||||
|
this.$refs.popup.close(); |
||||
|
}, |
||||
|
|
||||
|
async submit(remark, score) { |
||||
|
try { |
||||
|
await this.checkDeliver(remark, score); |
||||
|
this.closeScore(); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 检查交付物 |
||||
|
* @param {string} checkId 检查记录id |
||||
|
* @param {string} projectId 项目id |
||||
|
* @param {string} remark 评论 |
||||
|
* @param {number} score 分数 |
||||
|
* @param {number} status 检查状态(1-通过,2-驳回) |
||||
|
*/ |
||||
|
async checkDeliver(remark, score) { |
||||
|
try { |
||||
|
this.show = true; |
||||
|
const { projectId, options } = this; |
||||
|
const { checkId, status } = options; |
||||
|
const params = { checkId, projectId, status, remark, score }; |
||||
|
await this.$u.api.checkDeliver(params); |
||||
|
this.$t.ui.showToast('交付物检查成功'); |
||||
|
this.options = null; |
||||
|
this.getDeliverOfTask(); |
||||
|
} catch (error) { |
||||
|
console.error('p-delivery-history.vue checkDeliver error: ', error); |
||||
|
this.$t.ui.showToast('交付物检查失败,请稍后重试'); |
||||
|
this.options = null; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 判断内容是不是链接 |
||||
|
CheckUrl(url) { |
||||
|
var reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(.)+$/; |
||||
|
if (!reg.test(url)) { |
||||
|
return false; |
||||
|
} else { |
||||
|
return true; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.action-btn { |
||||
|
padding: 0; |
||||
|
width: 80rpx; |
||||
|
height: 40rpx; |
||||
|
line-height: 40rpx; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,140 @@ |
|||||
|
<template> |
||||
|
<!-- 交付物 --> |
||||
|
<view class="mt-3"> |
||||
|
<view v-if="lists && lists.length"> |
||||
|
<view :key="list.id" v-for="list in lists"> |
||||
|
<view class="p-3 mt-3 shadow"> |
||||
|
<view class="text-gray-400 pb-2"> |
||||
|
<span class="mr-4">{{ list.name }}</span> |
||||
|
<span>{{ $moment(+list.time).format('YYYY-MM-DD HH:mm:ss') }}</span> |
||||
|
</view> |
||||
|
<view class="pb-2 flex flex-wrap overflow-hidden" v-if="list.content"> |
||||
|
<a :href="list.content" class="text-blue-500" target="_blank" v-if="CheckUrl(list.content)">{{ list.content }}</a> |
||||
|
<span v-else>{{ list.content }}</span> |
||||
|
</view> |
||||
|
<view :key="checker.checkerId" v-for="checker in list.checkerList" class="mb-2"> |
||||
|
<view class="flex justify-between"> |
||||
|
<view class="font-bold"> |
||||
|
{{ checker.checkerName }} |
||||
|
<span v-if="checker.isMine">(我)</span> |
||||
|
</view> |
||||
|
<view> |
||||
|
<span class="text-blue-500" v-if="checker.status === 1">通过</span> |
||||
|
<span class="text-red-500" v-if="checker.status === 2">驳回</span> |
||||
|
<span class="ml-4" v-if="checker.status !== 0">{{ checker.score }}分</span> |
||||
|
<span class="text-gray-400" v-if="checker.status === 0 && !checker.isMine">未审核</span> |
||||
|
<view v-if="checker.status === 0 && checker.isMine"> |
||||
|
<u-button @click="showScore(checker.checkId, 2)" class="mr-3" plain size="mini" type="error">驳回</u-button> |
||||
|
<u-button @click="showScore(checker.checkId, 1)" plain size="mini" type="primary">通过</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="text-gray-400 text-xs mt-1">{{ checker.remark }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<u-empty icon-size="90" mode="history" text="暂未上传交付物" v-else></u-empty> |
||||
|
|
||||
|
<!-- 评分 --> |
||||
|
<uni-popup :maskClick="false" background-color="#fff" ref="popup" type="bottom"> |
||||
|
<PDeliverCheck @closeScore="closeScore" @submit="submit"></PDeliverCheck> |
||||
|
</uni-popup> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapGetters } from 'vuex'; |
||||
|
import UniPopup from '../../components/uni-popup/uni-popup.vue'; |
||||
|
import PDeliverCheck from '../p-deliver-check/p-deliver-check.vue'; |
||||
|
|
||||
|
export default { |
||||
|
name: 'p-delivery-history', |
||||
|
props: { task: { type: Object, default: null } }, |
||||
|
components: { PDeliverCheck, UniPopup }, |
||||
|
data() { |
||||
|
return { |
||||
|
lists: [], |
||||
|
show: false, |
||||
|
options: null, |
||||
|
loading: true, // 是否显示骨架屏组件 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: mapGetters('project', ['projectId']), |
||||
|
|
||||
|
mounted() { |
||||
|
this.getDeliverOfTask(); |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
async getDeliverOfTask() { |
||||
|
try { |
||||
|
const { projectId, task } = this; |
||||
|
const params = { projectId, taskSubId: task.id }; |
||||
|
const data = await this.$u.api.queryDeliverOfTask(params); |
||||
|
this.lists = data; |
||||
|
} catch (error) { |
||||
|
console.error('p-delivery-history.vue getDeliverOfTask error: ', error); |
||||
|
this.$t.ui.showToast(error.msg || '提交失败'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
showScore(checkId, status) { |
||||
|
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center'] |
||||
|
this.$refs.popup.open('bottom'); |
||||
|
this.options = { checkId, status }; |
||||
|
}, |
||||
|
|
||||
|
closeScore() { |
||||
|
this.$refs.popup.close('bottom'); |
||||
|
}, |
||||
|
|
||||
|
async submit(remark, score) { |
||||
|
try { |
||||
|
await this.checkDeliver(remark, score); |
||||
|
this.closeScore(); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 检查交付物 |
||||
|
* @param {string} checkId 检查记录id |
||||
|
* @param {string} projectId 项目id |
||||
|
* @param {string} remark 评论 |
||||
|
* @param {number} score 分数 |
||||
|
* @param {number} status 检查状态(1-通过,2-驳回) |
||||
|
*/ |
||||
|
async checkDeliver(remark, score) { |
||||
|
try { |
||||
|
this.show = true; |
||||
|
const { projectId, options } = this; |
||||
|
const { checkId, status } = options; |
||||
|
const params = { checkId, projectId, status, remark, score }; |
||||
|
await this.$u.api.checkDeliver(params); |
||||
|
this.$t.ui.showToast('交付物检查成功'); |
||||
|
this.options = null; |
||||
|
this.getDeliverOfTask(); |
||||
|
} catch (error) { |
||||
|
console.error('p-delivery-history.vue checkDeliver error: ', error); |
||||
|
this.$t.ui.showToast('交付物检查失败,请稍后重试'); |
||||
|
this.options = null; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 判断内容是不是链接 |
||||
|
CheckUrl(url) { |
||||
|
var reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(.)+$/; |
||||
|
if (!reg.test(url)) { |
||||
|
return false; |
||||
|
} else { |
||||
|
return true; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style></style> |
@ -0,0 +1,459 @@ |
|||||
|
<template> |
||||
|
<!-- 上传交付物 --> |
||||
|
<view class="pt-2 relative"> |
||||
|
<template v-if="history.length === 0 || currStatus === -1"> |
||||
|
<view class="flex items-center relative" v-if="deliveryType === 1"> |
||||
|
<u-input :border="border" :height="height" :type="type" v-model="content" placeholder="请输入链接" /> |
||||
|
<!-- #ifdef MP-WEIXIN --> |
||||
|
<text class="paste-btn absolute right-0 inline-block text-center bg-blue-500 text-white" @click="getClipboardCon"> 粘贴 </text> |
||||
|
<!-- #endif --> |
||||
|
</view> |
||||
|
|
||||
|
<u-input |
||||
|
v-if="deliveryType === 2" |
||||
|
:border="border" |
||||
|
:height="height" |
||||
|
:disabled="true" |
||||
|
:type="type" |
||||
|
placeholder="上传文件" |
||||
|
v-model="fileData.path" |
||||
|
@click="uploadFile" |
||||
|
/> |
||||
|
|
||||
|
<u-input |
||||
|
v-if="deliveryType === 3" |
||||
|
:border="border" |
||||
|
:height="height" |
||||
|
:disabled="true" |
||||
|
:type="type" |
||||
|
placeholder="拍照上传图片" |
||||
|
v-model="imgFileData.path" |
||||
|
@click="ImgUpload" |
||||
|
/> |
||||
|
|
||||
|
<view class="mt-2"> |
||||
|
<template v-if="currStatus === -1 || currStatus === 2"> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(1)">链接</u-button> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(2)">文件</u-button> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(3)">拍照</u-button> |
||||
|
</template> |
||||
|
</view> |
||||
|
|
||||
|
<view class="to-examine mt-2"> |
||||
|
<view class="examine-title flex justify-between items-center"> |
||||
|
<view class="flex-shrink-0" style="color: #999">审核人</view> |
||||
|
<view class="flex items-center justify-end" style="color: #595959; width: calc(100% - 60px)"> |
||||
|
<view class="examine-people text-right mr-2"> |
||||
|
<text v-if="examinePerpol.length === 0">请选择审核人</text> |
||||
|
<text v-else class="ml-1" :style="{ color: item.style }" v-for="(item, index) in examinePerpol" :key="index"> |
||||
|
{{ item.name }} |
||||
|
</text> |
||||
|
</view> |
||||
|
|
||||
|
<u-icon name="arrow-down" v-if="!isShowMembers" @click="showMembers"></u-icon> |
||||
|
<u-icon name="arrow-up" v-else @click="showMembers"></u-icon> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="examine-con" v-if="isShowMembers"> |
||||
|
<u-checkbox-group @change="checkboxGroupChange"> |
||||
|
<u-checkbox |
||||
|
style="width: 25%" |
||||
|
@change="checkboxChange($event, item)" |
||||
|
v-model="item.checked" |
||||
|
v-for="(item, index) in list" |
||||
|
:key="index" |
||||
|
:name="item.name" |
||||
|
:data-id="item.id" |
||||
|
shape="circle" |
||||
|
> |
||||
|
{{ item.name }} |
||||
|
</u-checkbox> |
||||
|
</u-checkbox-group> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<view class="submit-delivery"> |
||||
|
<u-button class="btn-radius" @click="submit" size="mini" type="primary" v-if="currStatus === -1">提交</u-button> |
||||
|
<text class="mr-2" v-if="currStatus === 0">待审核</text> |
||||
|
<text class="mr-2" v-if="currStatus === 1">已通过</text> |
||||
|
<text class="mr-2 text-red-500" v-if="currStatus === 2">已驳回</text> |
||||
|
<u-button class="btn-radius" @click="submit" size="mini" type="primary" v-if="currStatus === 2">重新提交</u-button> |
||||
|
</view> |
||||
|
|
||||
|
<template v-if="history.length > 0"> |
||||
|
<template v-for="(item, index) in history"> |
||||
|
<view :key="index" v-if="currStatus === 2"> |
||||
|
<u-input :key="index" :border="border" :height="height" :type="type" v-model="item.content" placeholder="请输入链接" /> |
||||
|
|
||||
|
<view class="mt-2"> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(1)">链接</u-button> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(2)">文件</u-button> |
||||
|
<u-button size="mini" class="btn-radius" :custom-style="customStyle" @click="changeDeliveryType(3)">拍照</u-button> |
||||
|
</view> |
||||
|
|
||||
|
<view class="to-examine mt-2"> |
||||
|
<view class="examine-title flex justify-between items-center"> |
||||
|
<view class="flex-shrink-0" style="color: #999">审核人</view> |
||||
|
<view class="flex items-center justify-end" style="color: #595959; width: calc(100% - 60px)"> |
||||
|
<view class="examine-people text-right mr-2"> |
||||
|
<text v-if="examinePerpol.length === 0">请选择审核人</text> |
||||
|
<text v-else class="ml-1" :style="{ color: item.style }" v-for="(item, index) in examinePerpol" :key="index"> |
||||
|
{{ item.name }} |
||||
|
</text> |
||||
|
</view> |
||||
|
|
||||
|
<u-icon name="arrow-down" v-if="!isShowMembers" @click="showMembers"></u-icon> |
||||
|
<u-icon name="arrow-up" v-else @click="showMembers"></u-icon> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="examine-con" v-if="isShowMembers"> |
||||
|
<u-checkbox-group @change="checkboxGroupChange"> |
||||
|
<u-checkbox |
||||
|
style="width: 25%" |
||||
|
@change="checkboxChange($event, item)" |
||||
|
v-model="item.checked" |
||||
|
v-for="(item, index) in list" |
||||
|
:key="index" |
||||
|
:name="item.name" |
||||
|
:data-id="item.id" |
||||
|
shape="circle" |
||||
|
> |
||||
|
{{ item.name }} |
||||
|
</u-checkbox> |
||||
|
</u-checkbox-group> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="to-examine py-1 flex flex-wrap overflow-hidden break-all" :key="index" v-if="item.content && currStatus !== 2"> |
||||
|
<a :href="item.content" class="text-blue-500 u-font-12 font-thin" target="_blank" v-if="CheckUrl(item.content)"> |
||||
|
{{ item.content ? item.content : item.filePath }} |
||||
|
</a> |
||||
|
<span v-else>{{ item.content }}</span> |
||||
|
</view> |
||||
|
|
||||
|
<view :class="index === 0 ? 'mt-4' : 'mt-3'" v-for="(checker, index) in item.checkerList" :key="index"> |
||||
|
<view class="flex justify-between"> |
||||
|
<view class="leading-none flex items-center"> |
||||
|
{{ checker.checkerName }} |
||||
|
<span class="leading-none" v-if="checker.isMine">(我)</span> |
||||
|
</view> |
||||
|
<view class="flex items-center"> |
||||
|
<span class="text-blue-500" v-if="checker.status === 1">通过</span> |
||||
|
<span class="text-red-500" v-if="checker.status === 2">驳回</span> |
||||
|
<span class="ml-4" v-if="checker.status !== 0">{{ checker.score }}分</span> |
||||
|
<span class="text-gray-400 leading-none" v-if="checker.status === 0 && !checker.isMine">未审核</span> |
||||
|
<view v-if="checker.status === 0 && checker.isMine"> |
||||
|
<u-button @click="showScore(checker.checkId, 2)" class="mr-3" plain size="mini" type="error">驳回</u-button> |
||||
|
<u-button @click="showScore(checker.checkId, 1)" plain size="mini" type="primary">通过</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="text-gray-400 text-xs mt-1">{{ checker.remark }}</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</template> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapState, mapGetters } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
name: 'p-upload-deliverable', |
||||
|
props: { task: { type: Object, default: null } }, |
||||
|
data() { |
||||
|
return { |
||||
|
content: '', |
||||
|
type: 'text', |
||||
|
border: true, |
||||
|
height: 60, |
||||
|
checkerList: [], |
||||
|
list: [], |
||||
|
examinePerpol: [], |
||||
|
isShowMembers: false, // 是否显示成员列表 |
||||
|
currStatus: -1, // 当前状态 |
||||
|
history: [], |
||||
|
customStyle: { |
||||
|
borderColor: '#1890FF', |
||||
|
color: '#1890FF', |
||||
|
marginRight: '16px', |
||||
|
}, |
||||
|
deliveryType: 1, |
||||
|
// 上传 |
||||
|
fileData: { |
||||
|
fileId: '', |
||||
|
name: '', |
||||
|
path: '', |
||||
|
}, |
||||
|
imgFileData: { |
||||
|
fileId: '', |
||||
|
name: '', |
||||
|
path: '', |
||||
|
}, |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
...mapState('role', ['members']), |
||||
|
...mapState('user', ['token']), |
||||
|
...mapGetters('project', ['projectId']), |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
if (this.members.length > 0) { |
||||
|
this.list = []; |
||||
|
if (this.members.length) { |
||||
|
this.members.forEach(member => { |
||||
|
const item = { id: member.memberId, name: member.name, checked: false }; |
||||
|
this.list.push(item); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this.getDeliverOfTask(); |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 获取剪切板内容 |
||||
|
getClipboardCon() { |
||||
|
uni.getClipboardData({ |
||||
|
success: function (res) { |
||||
|
this.content = res.data; |
||||
|
}, |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 改变交付物类型 |
||||
|
changeDeliveryType(data) { |
||||
|
this.deliveryType = data; |
||||
|
}, |
||||
|
|
||||
|
// 选中某个复选框时,由checkbox时触发 |
||||
|
checkboxChange(e, data) { |
||||
|
if (e.value) { |
||||
|
this.checkerList.push(data.id); |
||||
|
} else { |
||||
|
const index = this.checkerList.findIndex(checker => checker === data.id); |
||||
|
this.checkerList.splice(index, 1); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 选中任一checkbox时,由checkbox-group触发 |
||||
|
checkboxGroupChange(e) { |
||||
|
this.examinePerpol = []; |
||||
|
if (e.length > 0) { |
||||
|
e.forEach(item => { |
||||
|
let obj = { name: item, style: '#595959' }; |
||||
|
this.examinePerpol.push(obj); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 是否展开成员面板 |
||||
|
showMembers() { |
||||
|
this.isShowMembers = !this.isShowMembers; |
||||
|
}, |
||||
|
|
||||
|
// 上传文件 |
||||
|
async uploadFile() { |
||||
|
try { |
||||
|
const data = await this.$u.api.fileUpload(); |
||||
|
this.fileData = data; |
||||
|
} catch (error) { |
||||
|
this.$t.ui.showToast('error', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 上传图片 |
||||
|
async ImgUpload() { |
||||
|
try { |
||||
|
const data = await this.$u.api.ImgUpload(); |
||||
|
this.imgFileData = data; |
||||
|
} catch (error) { |
||||
|
this.$t.ui.showToast('error', error); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 提交交付物 |
||||
|
async submit() { |
||||
|
try { |
||||
|
const { content, checkerList, projectId, task } = this; |
||||
|
let file = null; |
||||
|
if (this.deliveryType === 2) { |
||||
|
file = this.fileData; |
||||
|
} else if (this.deliveryType === 3) { |
||||
|
file = this.imgFileData; |
||||
|
} |
||||
|
|
||||
|
if (this.deliveryType === 1 && !content) { |
||||
|
this.$t.ui.showToast('请填写链接'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (this.deliveryType === 2 && !file) { |
||||
|
this.$t.ui.showToast('请上传文件'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (this.deliveryType === 3 && !file.fileId) { |
||||
|
this.$t.ui.showToast('请拍照上传图片'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!this.checkerList.length) { |
||||
|
this.$t.ui.showToast('请选择检查人'); |
||||
|
return; |
||||
|
} |
||||
|
const params = { content, checkerList, projectId, taskSubId: task.id, fileId: file.fileId, filePath: file.path }; |
||||
|
await this.$u.api.saveDeliver(params); |
||||
|
this.$t.ui.showToast('交付物提交成功'); |
||||
|
this.currStatus = 0; |
||||
|
this.getDeliverOfTask(); |
||||
|
} catch (error) { |
||||
|
console.error('p-upload-deliverable.vue submit error: ', error); |
||||
|
this.$t.ui.showToast('交付物提交失败,请稍后重试'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
async getDeliverOfTask() { |
||||
|
try { |
||||
|
const { projectId, task } = this; |
||||
|
const params = { projectId, taskSubId: task.id }; |
||||
|
const data = await this.$u.api.queryDeliverOfTask(params); |
||||
|
|
||||
|
if (data.length > 0) { |
||||
|
let flag = -1; |
||||
|
this.examinePerpol = []; |
||||
|
data.forEach(item => { |
||||
|
if (item.filePath) { |
||||
|
item.content = item.filePath; |
||||
|
} |
||||
|
|
||||
|
item.checkerList.forEach(v => { |
||||
|
let style = '#595959'; |
||||
|
if (v.status === 0) { |
||||
|
style = '#595959'; |
||||
|
} else if (v.status === 1) { |
||||
|
style = '#52C41A'; |
||||
|
} else if (v.status === 2) { |
||||
|
style = '#FF2121'; |
||||
|
} |
||||
|
|
||||
|
let obj = { name: v.checkerName, style: style }; |
||||
|
this.examinePerpol.push(obj); |
||||
|
|
||||
|
this.list.forEach(item => { |
||||
|
if (item.id === v.checkerId) { |
||||
|
item.checked = true; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if (flag === 2) { |
||||
|
this.currStatus = 2; // 已驳回 |
||||
|
} |
||||
|
|
||||
|
if (flag < 2 && v.status === 0) { |
||||
|
this.currStatus = 0; // 待审核 |
||||
|
flag = 0; |
||||
|
} |
||||
|
|
||||
|
if (flag === 1 && v.status === 1) { |
||||
|
this.currStatus = 1; // 待审核 |
||||
|
flag = 1; |
||||
|
} |
||||
|
|
||||
|
if (v.status === 2) { |
||||
|
this.currStatus = 2; // 已驳回 |
||||
|
flag = 2; |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
this.history = data; |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('p-delivery-history.vue getDeliverOfTask error: ', error); |
||||
|
this.$t.ui.showToast(error.msg || '提交失败'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 判断内容是不是链接 |
||||
|
CheckUrl(url) { |
||||
|
var reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(.)+$/; |
||||
|
if (!reg.test(url)) { |
||||
|
return false; |
||||
|
} else { |
||||
|
return true; |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.paste-btn { |
||||
|
width: 100rpx; |
||||
|
height: 64rpx; |
||||
|
line-height: 64rpx; |
||||
|
font-size: 12px; |
||||
|
border-top-right-radius: 4rpx; |
||||
|
border-bottom-right-radius: 4rpx; |
||||
|
} |
||||
|
|
||||
|
.to-examine { |
||||
|
padding-left: 20rpx; |
||||
|
padding-right: 20rpx; |
||||
|
border: 2rpx solid #dcdfe6; |
||||
|
border-radius: 8rpx; |
||||
|
|
||||
|
.examine-title { |
||||
|
height: 60rpx; |
||||
|
} |
||||
|
|
||||
|
.examine-people { |
||||
|
width: calc(100% - 22px); |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.examine-con { |
||||
|
margin: 10rpx 0 20rpx; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-checkbox__label { |
||||
|
font-size: 24rpx !important; |
||||
|
color: #999999 !important; |
||||
|
margin-left: 16rpx !important; |
||||
|
margin-right: 0 !important; |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-checkbox__icon-wrap { |
||||
|
width: 20rpx !important; |
||||
|
height: 20rpx !important; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
::v-deep .u-icon__icon.uicon-checkbox-mark { |
||||
|
transform: scale(0.5); |
||||
|
} |
||||
|
|
||||
|
.btn-radius, |
||||
|
.btn-radius:after { |
||||
|
border-radius: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.btn-radius.u-btn--default, |
||||
|
.btn-radius.u-btn--default:after { |
||||
|
border-radius: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.submit-delivery { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
top: -25px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,94 @@ |
|||||
|
<template> |
||||
|
<!-- 上传交付物 --> |
||||
|
<view class="py-2"> |
||||
|
<u-input :auto-height="autoHeight" :border="border" :height="height" :type="type" v-model="content" width="100" /> |
||||
|
|
||||
|
<!-- 选择检查人 --> |
||||
|
<ChooseChecker ref="checker" :checkerList="checkerList" @setCheckerList="setCheckerList"></ChooseChecker> |
||||
|
|
||||
|
<view class="flex justify-between"> |
||||
|
<u-button @click="submit" class="m-0" size="mini" type="primary">提交</u-button> |
||||
|
<u-icon @click="changeShowHistory" name="arrow-up" v-if="showHistory"></u-icon> |
||||
|
<u-icon @click="changeShowHistory" name="arrow-down" v-else></u-icon> |
||||
|
</view> |
||||
|
|
||||
|
<p-delivery-history :task="task" v-if="showHistory" /> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import ChooseChecker from '@/components/ChooseChecker/ChooseChecker.vue'; |
||||
|
import { mapState, mapGetters } from 'vuex'; |
||||
|
|
||||
|
export default { |
||||
|
name: 'p-upload-deliverable', |
||||
|
components: { ChooseChecker }, |
||||
|
props: { task: { type: Object, default: null } }, |
||||
|
data() { |
||||
|
return { |
||||
|
content: '', |
||||
|
type: 'textarea', |
||||
|
border: true, |
||||
|
height: 30, |
||||
|
autoHeight: true, |
||||
|
checkerList: [], |
||||
|
showHistory: false, // 展开历史记录 |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
...mapState('role', ['members']), |
||||
|
...mapGetters('project', ['projectId']), |
||||
|
|
||||
|
checkers() { |
||||
|
const arr = []; |
||||
|
if (this.members.length) { |
||||
|
this.members.forEach(member => { |
||||
|
const item = { value: member.memberId, label: member.name }; |
||||
|
arr.push(item); |
||||
|
}); |
||||
|
} |
||||
|
return arr; |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 设置检查人 |
||||
|
setCheckerList(checked, item) { |
||||
|
if (checked) { |
||||
|
this.checkerList.push(item.memberId); |
||||
|
} else { |
||||
|
const index = this.checkerList.findIndex(checker => checker === item.memberId); |
||||
|
this.checkerList.splice(index, 1); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 展开合上历史记录 |
||||
|
changeShowHistory() { |
||||
|
this.showHistory = !this.showHistory; |
||||
|
}, |
||||
|
|
||||
|
// 提交交付物 |
||||
|
async submit() { |
||||
|
try { |
||||
|
const { content, checkerList, projectId, task } = this; |
||||
|
if (!this.checkerList.length) { |
||||
|
this.$t.ui.showToast('请选择检查人'); |
||||
|
return; |
||||
|
} |
||||
|
const params = { content, checkerList, projectId, taskSubId: task.id }; |
||||
|
await this.$u.api.saveDeliver(params); |
||||
|
this.$t.ui.showToast('交付物提交成功'); |
||||
|
this.content = ''; |
||||
|
this.checkerList = []; |
||||
|
this.$refs.checker.clearChecked(); |
||||
|
} catch (error) { |
||||
|
console.error('p-upload-deliverable.vue submit error: ', error); |
||||
|
this.$t.ui.showToast('交付物提交失败,请稍后重试'); |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"></style> |
Binary file not shown.
Binary file not shown.
@ -1,12 +1,36 @@ |
|||||
import Vue from 'vue'; |
import Vue from 'vue'; |
||||
import Vuex from 'vuex'; |
import Vuex from 'vuex'; |
||||
import db from './db/index'; |
|
||||
import user from './user/index'; |
|
||||
import messages from './messages/index'; |
import messages from './messages/index'; |
||||
import socket from './socket/index'; |
|
||||
import project from './project/index'; |
import project from './project/index'; |
||||
import role from './role/index'; |
import role from './role/index'; |
||||
|
import socket from './socket/index'; |
||||
import task from './task/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); |
Vue.use(Vuex); |
||||
export default new Vuex.Store({ modules: { db, user, messages, socket, project, role, task } }); |
export default new Vuex.Store({ state, getters, mutations, modules: { user, messages, socket, project, role, task } }); |
||||
|
@ -1,18 +1,3 @@ |
|||||
const actions = { |
const actions = {}; |
||||
/** |
|
||||
* 通过项目id获取项目信息 |
|
||||
* @param {any} commit |
|
||||
* @param {object} params 提交的参数 |
|
||||
*/ |
|
||||
async getProjectById({ commit }, params) { |
|
||||
try { |
|
||||
const data = await uni.$u.api.findProjectById(params); |
|
||||
commit('setProject', data); |
|
||||
return data; |
|
||||
} catch (error) { |
|
||||
throw error || '获取项目信息失败'; |
|
||||
} |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
export default actions; |
export default actions; |
||||
|
@ -1,3 +1,13 @@ |
|||||
const getters = {}; |
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; |
export default getters; |
||||
|
@ -0,0 +1,24 @@ |
|||||
|
import { computeFillPlaceholderTaskCount } from '../../utils/task'; |
||||
|
|
||||
|
describe('computeFillPlaceholderTaskCount', () => { |
||||
|
// 2021/8/17 ~ 2021/8/21
|
||||
|
const tasks = [ |
||||
|
{ id: '99724910037144221455', panel: {}, plugins: [], process: 4, planStart: 1629169800242 }, |
||||
|
{ id: '65053357415671253512', panel: {}, plugins: [], process: 4, planStart: 1629256200242 }, |
||||
|
{ id: '38735454515347179194', panel: {}, plugins: [], process: 4, planStart: 1629342600242 }, |
||||
|
{ id: '49602681534756706607', panel: {}, plugins: [], process: 4, planStart: 1629429000242 }, |
||||
|
{ id: '98860265376222512018', panel: {}, plugins: [], process: 4, planStart: 1629515400242 }, |
||||
|
{ id: '44419041575700334936', panel: {}, plugins: [], process: 4, planStart: 1629601800242 }, |
||||
|
]; |
||||
|
const timeGranularity = 'day'; |
||||
|
|
||||
|
it('超出上限 补齐', () => { |
||||
|
const data = [{ planStart: `${new Date('2021/8/10').getTime()}` }, { planStart: `${new Date('2021/8/11').getTime()}` }]; |
||||
|
expect(computeFillPlaceholderTaskCount({ tasks, data, timeGranularity }).prev.toString()).toMatch(/(7|8)/); |
||||
|
}); |
||||
|
|
||||
|
it('超出下限 补齐', () => { |
||||
|
const data = [{ planStart: `${new Date('2021/8/10').getTime()}` }, { planStart: `${new Date('2021/8/22').getTime()}` }]; |
||||
|
expect(computeFillPlaceholderTaskCount({ tasks, data, timeGranularity }).next.toString()).toMatch(/(1|2)/); |
||||
|
}); |
||||
|
}); |
@ -0,0 +1,344 @@ |
|||||
|
export const filter = { |
||||
|
/** |
||||
|
* 角色 过滤获取到的数据 根据开始截止时间 |
||||
|
* @param {object} data 缓存拿到的数据 |
||||
|
* @returns |
||||
|
*/ |
||||
|
roles(data) { |
||||
|
if (!data || !data.length) return []; |
||||
|
return data; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 定期任务 过滤获取到的数据 根据开始截止时间 |
||||
|
* @param {object} data 缓存拿到的数据 |
||||
|
* @param {number} timeNode 时间基准点 ms |
||||
|
* @param {number} queryNum 颗粒度数量 |
||||
|
* @param {number} timeUnit 时间颗粒度 |
||||
|
* @param {number} queryType 0向上查找 1向下查找(默认) 下查包含自己,上查不包含 |
||||
|
* @returns |
||||
|
*/ |
||||
|
planTask(data, timeNode, queryNum, timeUnit, queryType) { |
||||
|
if (!data || !data.length) return []; |
||||
|
if (queryType === 0) { |
||||
|
// 计算颗粒度 对应的 dayjs add 的单位
|
||||
|
let target = uni.$t.timeConfig.timeUnits.find(item => item.id === timeUnit); |
||||
|
// TODO: 缺少通过时间颗粒度筛选数据 任务没有返回时间颗粒度标签
|
||||
|
let start = uni.$t.time.add(+timeNode, -queryNum, target.granularity).valueOf(); |
||||
|
let arr = []; |
||||
|
arr = data.filter(item => start <= +item.planStart && +timeNode > +item.planEnd); |
||||
|
|
||||
|
if (!arr || !arr.length) { |
||||
|
// 开始时间往前推
|
||||
|
let resultS = []; |
||||
|
let againStart = uni.$t.time.add(start, -1, target.granularity).valueOf(); |
||||
|
let againArr = data.filter(item => againStart >= +item.planStart); |
||||
|
if (againArr && againArr.length) { |
||||
|
let sTime = uni.$t.time.setTimestampToStr(+againArr[0].planStart); |
||||
|
data.forEach(item => { |
||||
|
if (uni.$t.time.isSame(uni.$moment(sTime.date).valueOf(), +item.planStart, target.granularity)) { |
||||
|
resultS.push(item); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
return resultS; |
||||
|
} else { |
||||
|
return arr; |
||||
|
} |
||||
|
} else { |
||||
|
// 计算颗粒度 对应的 dayjs add 的单位
|
||||
|
let target = uni.$t.timeConfig.timeUnits.find(item => item.id === timeUnit); |
||||
|
// TODO: 缺少通过时间颗粒度筛选数据 任务没有返回时间颗粒度标签
|
||||
|
let end = uni.$t.time.add(timeNode, +queryNum - 1, target.granularity).valueOf(); |
||||
|
let arr = []; |
||||
|
arr = data.filter(item => end >= +item.planEnd && +timeNode <= +item.planStart); |
||||
|
|
||||
|
if (!arr || !arr.length) { |
||||
|
// 结束时间往后推
|
||||
|
let resultE = []; |
||||
|
let againEnd = uni.$t.time.add(end, 1, target.granularity).valueOf(); |
||||
|
let againEndArr = data.filter(item => againEnd <= +item.planStart); |
||||
|
if (againEndArr) { |
||||
|
let eTime = uni.$t.time.setTimestampToStr(+againEndArr[againEndArr.length - 1].planStart); |
||||
|
data.forEach(item => { |
||||
|
if (uni.$t.time.isSame(uni.$moment(eTime.date).valueOf(), +item.planEnd, target.granularity)) { |
||||
|
resultE.push(item); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
return resultE; |
||||
|
} else { |
||||
|
return arr; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 永久日常任务 过滤获取到的数据 根据开始截止时间 |
||||
|
* @param {object} data 缓存拿到的数据 |
||||
|
* @returns |
||||
|
*/ |
||||
|
fixedTasks(data) { |
||||
|
if (!data || !data.length) return []; |
||||
|
return data; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 日常任务 过滤获取到的数据 根据开始截止时间 |
||||
|
* @param {object} data 缓存拿到的数据 |
||||
|
* @param {number} timeNode 时间基准点 ms |
||||
|
* @returns |
||||
|
*/ |
||||
|
dailyTask(data, timeNode) { |
||||
|
if (!data || !data.length) return []; |
||||
|
// TODO: 缺少通过时间颗粒度筛选数据 任务没有返回时间颗粒度标签
|
||||
|
return data.filter(item => timeNode <= +item.endTime && timeNode >= +item.startTime); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 插件 过滤获取到的数据 根据插件id |
||||
|
* @param {object} data 缓存拿到的数据 |
||||
|
* @returns |
||||
|
*/ |
||||
|
plugin(data) { |
||||
|
if (!data || !data.id) return null; |
||||
|
return data; |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default { |
||||
|
/** |
||||
|
* 当前显示的角色信息 获取 |
||||
|
* @param {object} params |
||||
|
* @returns |
||||
|
*/ |
||||
|
async getShowRole(projectId) { |
||||
|
try { |
||||
|
const data = await uni.$t.storage.getStorage(`roles_${projectId}`); |
||||
|
return filter.roles(JSON.parse(data)); |
||||
|
} catch (error) { |
||||
|
return null; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 当前显示的角色信息 存 |
||||
|
* @param {array} data |
||||
|
*/ |
||||
|
putShowRole(projectId, data) { |
||||
|
try { |
||||
|
if (!data || !data.visibleList || !data.visibleList.length) return; // 服务端没数据不做操作
|
||||
|
let value = uni.$t.storage.getStorageSync(`roles_${projectId}`); |
||||
|
let locals = value ? JSON.parse(value) : null; |
||||
|
if (!locals || !locals.length) { |
||||
|
// 本地没数据
|
||||
|
locals = data || null; |
||||
|
} else { |
||||
|
// 本地有数据
|
||||
|
data.invisibleList.forEach(item => { |
||||
|
let invisibleListLocalData = locals.invisibleList.find(local => item.id === local.id); |
||||
|
if (invisibleListLocalData) { |
||||
|
// 有相同数据 就用新的data里的数据
|
||||
|
invisibleListLocalData = item; |
||||
|
} else { |
||||
|
// 没有就直接存本地
|
||||
|
locals.invisibleList.push(item); |
||||
|
} |
||||
|
}); |
||||
|
data.visibleList.forEach(item => { |
||||
|
let localData = locals.visibleList.find(local => item.id === local.id); |
||||
|
if (localData) { |
||||
|
// 有相同数据 就用新的data里的数据
|
||||
|
localData = item; |
||||
|
} else { |
||||
|
// 没有就直接存本地
|
||||
|
locals.visibleList.push(item); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
uni.$t.storage.setStorage(`roles_${projectId}`, locals); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$t.storage.setStorage(`roles_${projectId}`, []); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 定期任务 获取 |
||||
|
* @param {number} startTime |
||||
|
* @param {number} endTime |
||||
|
* @returns |
||||
|
*/ |
||||
|
async getStorageRegularTask(params) { |
||||
|
try { |
||||
|
const data = await uni.$t.storage.getStorage(`plan_task_${params.projectId}_${params.roleId}`); |
||||
|
return filter.planTask(JSON.parse(data), params.timeNode, params.queryNum, params.timeUnit, params.queryType); |
||||
|
} catch (error) { |
||||
|
return []; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 定期任务 存 |
||||
|
* @param {array} data |
||||
|
*/ |
||||
|
putStorageRegularTask(params, data) { |
||||
|
try { |
||||
|
if (!data || !data.length) return; // 服务端没数据不做操作
|
||||
|
let value = uni.$t.storage.getStorageSync(`plan_task_${params.projectId}_${params.roleId}`); |
||||
|
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(`plan_task_${params.projectId}_${params.roleId}`, locals); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$t.storage.setStorage(`plan_task_${params.projectId}_${params.roleId}`, []); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 永久的日常任务 获取 |
||||
|
* @param {number} startTime |
||||
|
* @param {number} endTime |
||||
|
* @returns |
||||
|
*/ |
||||
|
async getStoragePermanent(params) { |
||||
|
try { |
||||
|
const data = await uni.$t.storage.getStorage(`fixed_tasks_${params.projectId}_${params.roleId}`); |
||||
|
return filter.fixedTasks(JSON.parse(data)); |
||||
|
} catch (error) { |
||||
|
return []; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 永久的日常任务 存 |
||||
|
* @param {array} data |
||||
|
*/ |
||||
|
putStoragePermanent(params, data) { |
||||
|
try { |
||||
|
if (!data || !data.length) return; // 服务端没数据不做操作
|
||||
|
let value = uni.$t.storage.getStorageSync(`fixed_tasks_${params.projectId}_${params.roleId}`); |
||||
|
let locals = value ? JSON.parse(value) : []; |
||||
|
if (!locals || !locals.length) { |
||||
|
// 本地没数据
|
||||
|
locals = data || []; |
||||
|
} else { |
||||
|
// 本地有数据
|
||||
|
data.forEach((item, index) => { |
||||
|
let localData = locals.find(local => item.detailId === local.detailId); |
||||
|
if (localData) { |
||||
|
// 有相同数据 就用新的data里的数据
|
||||
|
localData = item; |
||||
|
} else { |
||||
|
locals.splice(index, 1); |
||||
|
// 没有就直接存本地
|
||||
|
locals.push(item); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
uni.$t.storage.setStorage(`fixed_tasks_${params.projectId}_${params.roleId}`, locals); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$t.storage.setStorage(`fixed_tasks_${params.projectId}_${params.roleId}`, []); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 日常任务 获取 |
||||
|
* @param {number} timeNode |
||||
|
* @returns |
||||
|
*/ |
||||
|
async getDailyTask(params) { |
||||
|
try { |
||||
|
const data = await uni.$t.storage.getStorage(`variable_tasks_${params.projectId}_${params.roleId}`); |
||||
|
return filter.dailyTask(JSON.parse(data), params.timeNode); |
||||
|
} catch (error) { |
||||
|
return []; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 日常任务 存 |
||||
|
* @param {array} data |
||||
|
*/ |
||||
|
putDailyTask(params, data) { |
||||
|
try { |
||||
|
if (!data || !data.length) return; // 服务端没数据不做操作
|
||||
|
let value = uni.$t.storage.getStorageSync(`variable_tasks_${params.projectId}_${params.roleId}`); |
||||
|
let locals = value ? JSON.parse(value) : []; |
||||
|
if (!locals || !locals.length) { |
||||
|
// 本地没数据
|
||||
|
locals = data || []; |
||||
|
} else { |
||||
|
// 本地有数据
|
||||
|
data.forEach(item => { |
||||
|
let localData = locals.find(local => item.detailId === local.detailId); |
||||
|
if (localData) { |
||||
|
// 有相同数据 就用新的data里的数据
|
||||
|
localData = item; |
||||
|
} else { |
||||
|
// 没有就直接存本地
|
||||
|
locals.push(item); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
uni.$t.storage.setStorage(`variable_tasks_${params.projectId}_${params.roleId}`, locals); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$t.storage.setStorage(`variable_tasks_${params.projectId}_${params.roleId}`, []); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 插件信息 获取 |
||||
|
* @param {string} pluginId |
||||
|
* @returns |
||||
|
*/ |
||||
|
async getPlugin(pluginId) { |
||||
|
try { |
||||
|
const data = await uni.$t.storage.getStorage(`plugin_${pluginId}`); |
||||
|
return filter.plugin(JSON.parse(data)); |
||||
|
} catch (error) { |
||||
|
return null; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 插件信息 存 |
||||
|
* @param {string} pluginId |
||||
|
* @param {object} data |
||||
|
*/ |
||||
|
putPlugin(pluginId, data) { |
||||
|
try { |
||||
|
if (!data || !data.id) return; // 服务端没数据不做操作
|
||||
|
let value = uni.$t.storage.getStorageSync(`plugin_${pluginId}`); |
||||
|
let locals = value ? JSON.parse(value) : null; |
||||
|
if (!locals || !locals.length) { |
||||
|
// 本地没数据
|
||||
|
locals = data || null; |
||||
|
} else { |
||||
|
// 本地有数据
|
||||
|
locals = data; |
||||
|
} |
||||
|
uni.$t.storage.setStorage(`plugin_${pluginId}`, locals); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$t.storage.setStorage(`plugin_${pluginId}`, null); |
||||
|
} |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,164 @@ |
|||||
|
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 { |
||||
|
/** |
||||
|
* 通过项目id获取角色信息 |
||||
|
* @param {object} params 提交的参数 |
||||
|
*/ |
||||
|
findShowRole(params, fn) { |
||||
|
let remote = false; |
||||
|
if (store.getters.useStorage) { |
||||
|
// 有缓存 且 服务端数据未返回 就先返回缓存
|
||||
|
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; |
||||
|
if (store.getters.useStorage) { |
||||
|
// 有缓存 且 服务端数据未返回 就先返回缓存
|
||||
|
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 => { |
||||
|
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; |
||||
|
if (store.getters.useStorage) { |
||||
|
// 有缓存 且 服务端数据未返回 就先返回缓存
|
||||
|
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; |
||||
|
if (store.getters.useStorage) { |
||||
|
// 有缓存 且 服务端数据未返回 就先返回缓存
|
||||
|
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; |
||||
|
if (store.getters.useStorage) { |
||||
|
// 有缓存 且 服务端数据未返回 就先返回缓存
|
||||
|
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)); |
||||
|
}); |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,53 @@ |
|||||
|
import dayjs from 'dayjs'; |
||||
|
|
||||
|
/** |
||||
|
* 设置时间轴空数据 |
||||
|
* @param {number} startTime |
||||
|
* @param {boolean} isUp true 向上加载,false 向下加载 |
||||
|
* @param {string} timeGranularity 颗粒度 |
||||
|
* @param {number} pageCount 加载的颗粒度数量 默认值是10 |
||||
|
*/ |
||||
|
export const setPlaceholderTasks = (startTime, isUp, timeGranularity, pageCount) => { |
||||
|
let result = []; |
||||
|
pageCount = pageCount || uni.$t.task.pageCount; |
||||
|
for (let i = 0; i < pageCount; i++) { |
||||
|
const delta = isUp ? `-${i + 1}` - 0 : i + 1; |
||||
|
let item = { |
||||
|
id: uni.$u.guid(20, false, 10), |
||||
|
panel: {}, |
||||
|
plugins: [], |
||||
|
process: 4, |
||||
|
planStart: uni.$moment(startTime).add(delta, timeGranularity).valueOf(), |
||||
|
}; |
||||
|
// console.log('isup: ', isUp, 'result:', new Date(item.planStart).toLocaleDateString());
|
||||
|
|
||||
|
isUp ? result.unshift(item) : result.push(item); |
||||
|
} |
||||
|
return result; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 超出旧数据上、下限 补齐时间刻度到新数据的起始时间颗粒度 |
||||
|
* @param {object} option |
||||
|
* @param {array} option.tasks 旧的已有的任务书籍 |
||||
|
* @param {array} option.data 新拿到的任务数据 空值已经过滤过了 |
||||
|
* @param {string} option.timeGranularity 颗粒度 |
||||
|
*/ |
||||
|
export const computeFillPlaceholderTaskCount = ({ tasks, data, timeGranularity }) => { |
||||
|
const result = { prev: 0, next: 0 }; |
||||
|
// 新数据的开始时间 < 旧数据的开始时间
|
||||
|
// 超出了上限 补上限的时间刻度
|
||||
|
// 补上 新数据开始时间 到 旧数据开始时间 的刻度
|
||||
|
if (+data[0].planStart < +tasks[0].planStart) { |
||||
|
// 找出来需要补几组颗粒度
|
||||
|
result.prev = dayjs(+tasks[0].planStart).diff(+data[0].planStart, timeGranularity) + 1; |
||||
|
} |
||||
|
|
||||
|
// 新数据的结束时间 > 旧数据的结束时间
|
||||
|
// 超出了下线 补下限的时间刻度
|
||||
|
// 补上 旧数据截止时间 到 新数据截止时间 的刻度
|
||||
|
if (+data[data.length - 1].planStart > +tasks[tasks.length - 1].planStart) { |
||||
|
result.next = dayjs(+data[data.length - 1].planStart).diff(+tasks[tasks.length - 1].planStart, timeGranularity) + 1; |
||||
|
} |
||||
|
return result; |
||||
|
}; |
@ -1,30 +0,0 @@ |
|||||
const colors = require('tailwindcss/colors'); |
|
||||
|
|
||||
module.exports = { |
|
||||
// purge: ['./public/index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
|
||||
darkMode: false, // or 'media' or 'class'
|
|
||||
theme: { |
|
||||
extend: {}, |
|
||||
colors: { |
|
||||
blue: colors.sky, |
|
||||
gray: colors.blueGray, |
|
||||
red: colors.red, |
|
||||
orange: colors.orange, |
|
||||
yellow: colors.yellow, |
|
||||
green: colors.green, |
|
||||
pink: colors.rose, |
|
||||
white: colors.white, |
|
||||
black: '#333', |
|
||||
transparent: 'transparent', |
|
||||
}, |
|
||||
}, |
|
||||
variants: { extend: {} }, |
|
||||
plugins: [], |
|
||||
corePlugins: { |
|
||||
space: false, |
|
||||
divideWidth: false, |
|
||||
divideColor: false, |
|
||||
divideStyle: false, |
|
||||
divideOpacity: false, |
|
||||
}, |
|
||||
}; |
|
Loading…
Reference in new issue