39 changed files with 2003 additions and 1172 deletions
@ -1,149 +0,0 @@ |
|||||
--- |
|
||||
kind: pipeline |
|
||||
type: docker |
|
||||
name: dev |
|
||||
|
|
||||
# 挂载的主机卷,可以映射到docker容器中 |
|
||||
volumes: |
|
||||
# maven构建缓存(宿主机目录) |
|
||||
- name: ssh_key |
|
||||
host: |
|
||||
path: /root/.ssh/ |
|
||||
- name: cache |
|
||||
host: |
|
||||
path: /var/lib/cache |
|
||||
- name: data |
|
||||
host: |
|
||||
path: /var/lib/data |
|
||||
|
|
||||
steps: |
|
||||
# - name: restore-cache |
|
||||
# image: drillster/drone-volume-cache |
|
||||
# volumes: |
|
||||
# - name: cache |
|
||||
# path: /cache |
|
||||
# settings: |
|
||||
# restore: true |
|
||||
# mount: |
|
||||
# - ./node_modules |
|
||||
|
|
||||
- name: build |
|
||||
image: node:latest |
|
||||
pull: if-not-exists # default always |
|
||||
# volumes: |
|
||||
# - name: cache |
|
||||
# path: /root/.m2 |
|
||||
commands: |
|
||||
- npm config set registry http://registry.npm.taobao.org |
|
||||
- npm i |
|
||||
- npm run test |
|
||||
|
|
||||
# - name: rebuild-cache |
|
||||
# image: drillster/drone-volume-cache |
|
||||
# volumes: |
|
||||
# - name: cache |
|
||||
# path: /cache |
|
||||
# settings: |
|
||||
# rebuild: true |
|
||||
# mount: |
|
||||
# - ./node_modules |
|
||||
|
|
||||
- name: deploy-scp |
|
||||
image: appleboy/drone-scp |
|
||||
pull: if-not-exists |
|
||||
volumes: |
|
||||
- name: ssh_key |
|
||||
path: /root/.ssh/ |
|
||||
settings: |
|
||||
host: test.tall.wiki |
|
||||
port: 22 |
|
||||
username: root |
|
||||
key_path: /root/.ssh/id_rsa |
|
||||
rm: true # true则会删除目标目录重建 |
|
||||
target: /home/tall/v4.0.0 |
|
||||
source: dist/* |
|
||||
strip_components: 1 # 去除的目录层数,如果没有该选项,则拷贝过去是 target/xxx.jar,1代表去除target |
|
||||
|
|
||||
# - name: run-ssh |
|
||||
# image: appleboy/drone-ssh |
|
||||
# pull: if-not-exists |
|
||||
# volumes: |
|
||||
# - name: ssh_key |
|
||||
# path: /root/.ssh/ |
|
||||
# settings: |
|
||||
# settings: |
|
||||
# host: test.tall.wiki |
|
||||
# port: 22 |
|
||||
# username: root |
|
||||
# key_path: /root/.ssh/id_rsa |
|
||||
# script_stop: true # stop script after first failure |
|
||||
# #command_timeout: 30s # 30seconds, the maximum amount of time for the execute commands, default is 10 minutes. |
|
||||
# script: |
|
||||
# - cd /home/iacd-platform-drone |
|
||||
# - ./re.sh > /dev/null 2> /dev/null & |
|
||||
|
|
||||
- name: notify-email |
|
||||
image: drillster/drone-email |
|
||||
pull: if-not-exists |
|
||||
settings: |
|
||||
host: smtp.qiye.aliyun.com #例如 smtp.qq.com |
|
||||
port: 465 #例如QQ邮箱端口465 |
|
||||
username: devops@ccsens.com #邮箱用户名 |
|
||||
password: #邮箱密码 |
|
||||
from_secret: orgsecret_password_mail_devops |
|
||||
from: devops@ccsens.com |
|
||||
recipients: weizezhao@ccsens.com #收件人,多个用,隔开 |
|
||||
when: #执行条件 |
|
||||
status: |
|
||||
- success |
|
||||
- changed |
|
||||
- failure |
|
||||
|
|
||||
- name: notify-wechatwork |
|
||||
image: fifsky/drone-wechat-work |
|
||||
pull: if-not-exists |
|
||||
settings: |
|
||||
url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=b2b93e9a-128b-41d4-8dce-12004e3f48b9 |
|
||||
msgtype: markdown |
|
||||
content: | |
|
||||
{{if eq .Status "success" }} |
|
||||
#### 🎉 ${DRONE_REPO} 构建成功 |
|
||||
> Commit: [${DRONE_COMMIT_MESSAGE}](${DRONE_COMMIT_LINK}) |
|
||||
> Author: ${DRONE_COMMIT_AUTHOR} |
|
||||
> [点击查看](${DRONE_BUILD_LINK}) |
|
||||
{{else}} |
|
||||
#### ❌ ${DRONE_REPO} 构建失败 |
|
||||
> Commit: [${DRONE_COMMIT_MESSAGE}](${DRONE_COMMIT_LINK}) |
|
||||
> Author: ${DRONE_COMMIT_AUTHOR} |
|
||||
> 请立即修复!!! |
|
||||
> [点击查看](${DRONE_BUILD_LINK}) |
|
||||
{{end}} |
|
||||
when: |
|
||||
status: |
|
||||
- failure |
|
||||
- success |
|
||||
|
|
||||
trigger: |
|
||||
branch: feat |
|
||||
# - name: notify-dingtalk |
|
||||
# image: lddsb/drone-dingtalk-message |
|
||||
# environment: |
|
||||
# PASSWORD: |
|
||||
# from_secret: password_mail_devops |
|
||||
# settings: |
|
||||
# token: your-dingtalk-robot-access-token |
|
||||
# type: markdown |
|
||||
# message_color: true |
|
||||
# message_pic: true |
|
||||
# sha_link: true |
|
||||
|
|
||||
# -name: notify-slack |
|
||||
# image: plugins/slack |
|
||||
# webhook: https://hooks.slack.com/ www.dijiuyy.com services/xxx/xxx/xxx |
|
||||
# channel: dev |
|
||||
# template: > |
|
||||
# {{#success build.status}} |
|
||||
# build {{build.number}} succeeded. Good job. |
|
||||
# {{else}} |
|
||||
# build {{build.number}} failed. Fix me please. |
|
||||
# {{/success}} |
|
||||
@ -0,0 +1,10 @@ |
|||||
|
import store from '@/store/index'; |
||||
|
|
||||
|
const fullPath = store.getters['finance/fullPath']; |
||||
|
console.log('fullPath: ', fullPath); |
||||
|
|
||||
|
export function setupFinance(app) { |
||||
|
uni.$u.api = { ...uni.$u.api } || {}; |
||||
|
// 根据任务id获取财务条信息
|
||||
|
uni.$u.api.getFinanceByTask = taskDetailId => uni.$u.post(`${fullPath}/getByTask`, { taskDetailId }); |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
import Config from '@/common/js/config.js'; |
||||
|
|
||||
|
const { apiUrl } = Config; |
||||
|
const defaultwbs = `${apiUrl}/defaultwbs`; |
||||
|
|
||||
|
export function setupMock(app) { |
||||
|
uni.$u.api = { ...uni.$u.api } || {}; |
||||
|
|
||||
|
// 删除交付物
|
||||
|
uni.$u.api.deleteDeliver = param => |
||||
|
new Promise((resolve, reject) => { |
||||
|
setTimeout(() => { |
||||
|
resolve(); |
||||
|
}, 100); |
||||
|
}); |
||||
|
|
||||
|
// uni.$u.api.getFinanceByTask = taskDetailId => new Promise((resolve, reject) => {
|
||||
|
// setTimeout(() => {
|
||||
|
// resolve({
|
||||
|
// financeId: '123',
|
||||
|
// budget: 1000 * 1000,
|
||||
|
// bonus: 200 * 1000,
|
||||
|
// projectExpend: 500 * 1000,
|
||||
|
// dailyExpend: 500 * 1000,
|
||||
|
// });
|
||||
|
// }, 100);
|
||||
|
// });
|
||||
|
} |
||||
@ -1,38 +1,88 @@ |
|||||
// 默认主题文件 |
// 默认主题文件 |
||||
.theme-default { |
.theme-default { |
||||
background-color: #F3F3F3; |
background-color: #f3f3f3; |
||||
background-color: #007aff; |
|
||||
// color: #fff; |
|
||||
.u-card { |
.u-card { |
||||
font-size: 16px !important; |
font-size: 16px !important; |
||||
background-color: #F3F3F3 !important; |
background-color: #f3f3f3 !important; |
||||
.deliverHead{ |
|
||||
align-items: center; |
.mask { |
||||
} |
position: absolute; |
||||
.btns u-button{ |
|
||||
margin: 0 !important; |
|
||||
} |
|
||||
.active{ |
|
||||
background-color: #2979FF; |
|
||||
color: #FFFFFF; |
|
||||
} |
|
||||
.mask{ |
|
||||
position:absolute; |
|
||||
top: 0; |
top: 0; |
||||
left:0; |
left: 0; |
||||
width: 100%; |
width: 100%; |
||||
height: 100%; |
height: 100%; |
||||
z-index: 100; |
z-index: 100; |
||||
} |
} |
||||
} |
} |
||||
.u-navbar { |
// 弹出层 内容盒子 |
||||
background-color: #007aff !important; |
.modal-content-wrap { |
||||
color: #fff; |
position: absolute; |
||||
.uicon-nav-back { |
left: 50rpx; |
||||
color: #fff !important; |
top: 50%; |
||||
|
width: 650rpx; |
||||
|
transform: translate3d(0, -50%, 0); |
||||
|
background-color: #fff; |
||||
|
|
||||
|
.modal-content-head { |
||||
|
text-align: center; |
||||
|
margin-top: 40rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
font-size: 16px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.modal-content-body { |
||||
|
padding: 32rpx; |
||||
|
|
||||
|
// 审核插件 |
||||
|
.common-list { |
||||
|
height: 12.5rem; |
||||
|
overflow-y: scroll; |
||||
|
view { |
||||
|
border-bottom: 1px solid #e5e7eb; |
||||
|
|
||||
|
&:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.modal-content-foot { |
||||
|
display: flex; |
||||
|
border-top: 1px solid #d1d5db; |
||||
|
|
||||
|
.cancel, |
||||
|
.confirm { |
||||
|
flex: 1; |
||||
|
text-align: center; |
||||
|
@extend .leading-12; |
||||
|
} |
||||
|
.cancel { |
||||
|
border-right: 1px solid #d1d5db; |
||||
|
} |
||||
|
.confirm { |
||||
|
@extend .text-blue-700; |
||||
|
} |
||||
|
// .leading-12 flex-1 text-center delete-modal-border |
||||
|
} |
||||
|
|
||||
|
uni-textarea { |
||||
|
width: 596rpx; |
||||
|
height: 140rpx; |
||||
|
box-sizing: border-box !important; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.link-box { |
||||
|
:deep(.u-input__input) { |
||||
|
color: #60a5fa; |
||||
} |
} |
||||
} |
} |
||||
button{ |
|
||||
border: none!important; |
.progress-dot { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
border-radius: 50%; |
||||
|
line-height: 50rpx; |
||||
|
background-color: #fa8c16; |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,13 @@ |
|||||
|
<template> |
||||
|
<view @click="openLink" class="break-all text-blue-400 text-xs my-1"> {{ link }} </view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
const props = defineProps({ link: String }); |
||||
|
|
||||
|
function openLink() { |
||||
|
uni.navigateTo({ |
||||
|
url: `/pages/detailWebview/detailWebview?url=${props.link}`, |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
@ -1,91 +1,66 @@ |
|||||
<template> |
<template> |
||||
<view class="deliverFoot border border-solid border-gray-300 rounded-md mt-3 p-2"> |
<view class="border border-solid border-gray-300 rounded-md mt-3 p-2" @click="collapsed = !collapsed"> |
||||
<view class="top flex justify-between"> |
<view class="top flex justify-between"> |
||||
<view class="mr-3"> |
<view class="mr-3 text-sm">审核人</view> |
||||
审核人 |
|
||||
</view> |
|
||||
<!-- 展示选择的审核人 --> |
<!-- 展示选择的审核人 --> |
||||
<view class="flex approver item-center truncate justify-end flex-1 text-sm" v-show="isUicon"> |
<view class="flex item-center justify-end flex-1 text-sm"> |
||||
<view v-for="item in computedDelivers"> |
<view v-for="item in showCheckers" class="mx-1"> |
||||
<view v-show="item.checked" class="mx-1"> |
<!-- <u-badge :is-dot="true" is-center></u-badge> --> |
||||
{{item.name}} |
{{ item.name }} |
||||
</view> |
|
||||
</view> |
</view> |
||||
|
<view class="mx-1" v-show="checkedCheckers.length > 3">...</view> |
||||
</view> |
</view> |
||||
|
|
||||
<!-- 点击更换图标 --> |
<!-- 点击更换图标 --> |
||||
<view> |
<u-icon :name="collapsed ? 'arrow-down' : 'arrow-up'"></u-icon> |
||||
<u-icon v-if="isUicon" name="arrow-down" @click="changeIcon"></u-icon> |
|
||||
<u-icon v-else="isUicon" name="arrow-up" @click="changeIcon"></u-icon> |
|
||||
</view> |
|
||||
</view> |
</view> |
||||
|
|
||||
<!-- 隐藏的审核人选项 --> |
<!-- 隐藏的审核人选项 --> |
||||
<view v-show="!isUicon" class="foot mt-2 flex flex-wrap"> |
<view v-show="!collapsed" class="foot mt-2 flex flex-wrap"> |
||||
<u-button |
<u-button |
||||
v-for="item in delivers" |
v-for="item in checkers" |
||||
size="mini" class="my-1 mx-2" |
:type="checkedCheckers.find(checker => checker.memberId === item.memberId) ? 'primary' : 'default'" |
||||
@click="item.checked = !item.checked" |
size="mini" |
||||
:class="item.checked ? 'active' : '' " |
class="my-1 mx-2" |
||||
|
@click="handleSelectChecker(item)" |
||||
> |
> |
||||
{{item.name}} |
{{ item.name }} |
||||
</u-button> |
</u-button> |
||||
</view> |
</view> |
||||
</view> |
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
|
import { ref, computed, defineExpose } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
|
||||
import {ref , reactive , computed }from 'vue' |
const store = useStore(); |
||||
// 图标切换 |
// 图标切换 |
||||
let isUicon = ref('true') |
const collapsed = ref(true); |
||||
// 审核人员列表 |
|
||||
const delivers = reactive([ |
|
||||
{ |
|
||||
checked:true, |
|
||||
name:'冯教授' |
|
||||
}, |
|
||||
{ |
|
||||
checked:false, |
|
||||
name:'陈历珺' |
|
||||
}, |
|
||||
{ |
|
||||
checked:false, |
|
||||
name:'张野' |
|
||||
}, |
|
||||
{ |
|
||||
checked:false, |
|
||||
name:'宋瑞芳' |
|
||||
}, |
|
||||
{ |
|
||||
checked:false, |
|
||||
name:'张斌' |
|
||||
}, |
|
||||
{ |
|
||||
checked:false, |
|
||||
name:'孙方圆' |
|
||||
} |
|
||||
]) |
|
||||
|
|
||||
// 显示已选择的审核人 |
// 审核人员列表 从store获取真实的项目成员列表 |
||||
const computedDelivers = computed(()=>{ |
// 项目加载之初 就已经获取了 |
||||
let arr = []; |
const checkers = computed(() => store.state.role.members); |
||||
delivers.forEach((item)=>{ |
|
||||
if(item.checked){ |
|
||||
arr.push(item) |
|
||||
} |
|
||||
if(arr.length>3){ |
|
||||
arr = arr.splice(0,3) |
|
||||
arr[3] = {checked:true,name:'...'} |
|
||||
} |
|
||||
}) |
|
||||
return arr |
|
||||
}) |
|
||||
|
|
||||
// 点击切换箭头图标 |
// 所有选中的审核人 |
||||
function changeIcon(){ |
const checkedCheckers = ref([]); |
||||
isUicon.value = !isUicon.value |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss"> |
// 折叠状态 显示的选中的检查人 |
||||
|
const showCheckers = computed(() => (checkedCheckers.value.length > 3 ? checkedCheckers.value.slice(0, 3) : checkedCheckers.value)); |
||||
|
|
||||
</style> |
defineExpose({ checkedCheckers, collapsed }); |
||||
|
|
||||
|
/** |
||||
|
* 点击成员 切换检查人的选中状态 |
||||
|
* @param {object} member 成员对象 |
||||
|
*/ |
||||
|
function handleSelectChecker(member) { |
||||
|
const target = checkedCheckers.value.find(item => item.memberId === member.memberId); |
||||
|
if (target) { |
||||
|
// 已经选中 将此项移除选中的数组中 |
||||
|
checkedCheckers.value = checkedCheckers.value.filter(item => item.memberId !== member.memberId); |
||||
|
} else { |
||||
|
checkedCheckers.value.push(member); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|||||
@ -0,0 +1,226 @@ |
|||||
|
<template> |
||||
|
<view v-if="showViewToken" class="ring-timing" :style="containerStyles"> |
||||
|
<!-- #ifndef APP-NVUE --> |
||||
|
<view class="ring-timing-half ring-timing-left" :style="leftStyles" @transitionend="onTimingEnd" /> |
||||
|
<view class="ring-timing-half ring-timing-right" :style="rightStyles" /> |
||||
|
<!-- #endif --> |
||||
|
<!-- #ifdef APP-NVUE --> |
||||
|
<view :ref="`leftHalf${showViewToken}`" class="ring-timing-half ring-timing-left" :style="leftStyles" /> |
||||
|
<view :ref="`rightHalf${showViewToken}`" class="ring-timing-half ring-timing-right" :style="rightStyles" /> |
||||
|
<!-- #endif --> |
||||
|
<view class="ring-timing-center" :style="centerStyles"><slot /></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
// #ifdef APP-NVUE |
||||
|
const animation = weex.requireModule('animation') |
||||
|
// #endif |
||||
|
|
||||
|
/** |
||||
|
* zwp-ring-timing 圆环计时器,不使用canvas和定时器,仅css |
||||
|
* @property {String} *mode 模式,可选值:timing定时器,chart当作图表用于展示数据(图表模式仅限看看,真要做图表还是用canvas好) |
||||
|
* @property {String} activeColor 进度条走过的颜色 |
||||
|
* @property {String} defaultColor 进度条底色 |
||||
|
* @property {String} centerBgColor 圆环中间区域的背景色 |
||||
|
* @property {Number} radius 圆形半径或整个组件的一半尺寸(包含了圆环的宽度) |
||||
|
* @property {Number} barWidth 圆环宽度 |
||||
|
* @property {Number} startDeg 进度开始的角度 |
||||
|
* @property {Number} duration timing模式的定时时间 |
||||
|
* @property {Number} value chart模式的值(1~100) |
||||
|
* @event {Function} timingEnd timing模式下定时完成的回调 |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
mode: { |
||||
|
validator: value => ['timing', 'chart'].includes(value), |
||||
|
default: 'timing' |
||||
|
}, |
||||
|
activeColor: { |
||||
|
type: String, |
||||
|
default: '#42b983' |
||||
|
}, |
||||
|
defaultColor: { |
||||
|
type: String, |
||||
|
default: '#EEEEEE' |
||||
|
}, |
||||
|
centerBgColor: { |
||||
|
type: String, |
||||
|
default: '#FFFFFF' |
||||
|
}, |
||||
|
radius: { |
||||
|
type: Number, |
||||
|
default: 100 |
||||
|
}, |
||||
|
barWidth: { |
||||
|
type: Number, |
||||
|
default: 10 |
||||
|
}, |
||||
|
startDeg: { |
||||
|
type: Number, |
||||
|
default: 0 |
||||
|
}, |
||||
|
duration: { |
||||
|
type: Number, |
||||
|
default: 1 |
||||
|
}, |
||||
|
value: Number |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
isStart: false, |
||||
|
showViewToken: Date.now() // nvue用来重置进度的 |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
computed: { |
||||
|
containerStyles() { |
||||
|
const { radius, startDeg, activeColor } = this |
||||
|
return { |
||||
|
borderRadius: `${radius}rpx`, |
||||
|
height: `${radius * 2}rpx`, |
||||
|
width: `${radius * 2}rpx`, |
||||
|
transform: `rotate(${startDeg}deg)`, |
||||
|
backgroundColor: activeColor |
||||
|
} |
||||
|
}, |
||||
|
leftStyles() { |
||||
|
const { mode, radius, defaultColor, isStart, duration, value } = this |
||||
|
return { |
||||
|
height: `${radius * 2}rpx`, |
||||
|
width: `${radius}rpx`, |
||||
|
backgroundColor: defaultColor, |
||||
|
borderTopLeftRadius: `${radius}rpx`, |
||||
|
borderBottomLeftRadius: `${radius}rpx`, |
||||
|
...(mode == 'timing' ? { |
||||
|
// #ifndef APP-NVUE |
||||
|
transitionDuration: `${isStart ? duration : 0}s`, |
||||
|
transform: `rotate(${isStart ? 180 : -180}deg)` |
||||
|
// #endif |
||||
|
} : { |
||||
|
transform: `rotate(${-180 + value * 3.6}deg)` |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
rightStyles() { |
||||
|
const { mode, radius, activeColor, defaultColor, isStart, duration, value } = this |
||||
|
return { |
||||
|
height: `${radius * 2}rpx`, |
||||
|
width: `${radius}rpx`, |
||||
|
backgroundColor: defaultColor, |
||||
|
borderTopRightRadius: `${radius}rpx`, |
||||
|
borderBottomRightRadius: `${radius}rpx`, |
||||
|
...(mode == 'timing' ? { |
||||
|
// #ifndef APP-NVUE |
||||
|
backgroundColor: isStart ? activeColor : defaultColor, |
||||
|
transitionDelay: `${isStart ? duration / 2 : 0}s`, |
||||
|
transform: `rotate(${isStart ? 0 : -180}deg)` |
||||
|
// #endif |
||||
|
} : { |
||||
|
backgroundColor: value >= 50 ? activeColor : defaultColor, |
||||
|
transform: `rotate(${value >= 50 ? 0 : -180}deg)`, |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
centerStyles() { |
||||
|
const { radius, centerBgColor, barWidth, startDeg } = this |
||||
|
return { |
||||
|
borderRadius: `${radius - barWidth}rpx`, |
||||
|
height: `${(radius - barWidth) * 2}rpx`, |
||||
|
width: `${(radius - barWidth) * 2}rpx`, |
||||
|
transform: `translate(-50%, -50%) rotate(-${startDeg}deg)`, |
||||
|
backgroundColor: centerBgColor, |
||||
|
left: `${radius}rpx`, |
||||
|
top: `${radius}rpx` |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// #ifdef APP-NVUE |
||||
|
createAnimation(direction, styles, callback = () => {}) { |
||||
|
let { showViewToken, duration } = this |
||||
|
let isLeft = direction == 'left' |
||||
|
animation.transition( |
||||
|
this.$refs[`${direction}Half${showViewToken}`], |
||||
|
{ |
||||
|
styles, |
||||
|
duration: isLeft ? duration * 1000 : 0, |
||||
|
delay: !isLeft ? (duration / 2) * 1000 : 0, |
||||
|
timingFunction: 'linear' |
||||
|
}, |
||||
|
callback |
||||
|
) |
||||
|
}, |
||||
|
// #endif |
||||
|
start() { |
||||
|
if (this.mode == 'chart') return |
||||
|
// #ifndef APP-NVUE |
||||
|
this.isStart = true |
||||
|
// #endif |
||||
|
// #ifdef APP-NVUE |
||||
|
const { createAnimation, activeColor, onTimingEnd } = this |
||||
|
createAnimation('left', { |
||||
|
transform: 'rotate(180deg)' |
||||
|
}, onTimingEnd) |
||||
|
createAnimation('right', { |
||||
|
backgroundColor: activeColor, |
||||
|
transform: 'rotate(0)' |
||||
|
}) |
||||
|
// #endif |
||||
|
}, |
||||
|
end() { |
||||
|
if (this.mode == 'chart') return |
||||
|
// #ifndef APP-NVUE |
||||
|
this.isStart = false |
||||
|
// #endif |
||||
|
// #ifdef APP-NVUE |
||||
|
this.showViewToken = 0 |
||||
|
this.$nextTick(() => { |
||||
|
this.showViewToken = Date.now() |
||||
|
}) |
||||
|
// #endif |
||||
|
}, |
||||
|
onTimingEnd() { |
||||
|
this.$emit('timingEnd') |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.ring-timing { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
position: relative; |
||||
|
} |
||||
|
.ring-timing-half { |
||||
|
flex: 1; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
transition-property: transform, background-color; |
||||
|
transition-timing-function: linear; |
||||
|
/* #endif */ |
||||
|
/* #ifdef APP-NVUE */ |
||||
|
transform: rotate(-180deg); |
||||
|
/* #endif */ |
||||
|
} |
||||
|
.ring-timing-left { |
||||
|
transform-origin: right center; |
||||
|
} |
||||
|
.ring-timing-right { |
||||
|
transform-origin: left center; |
||||
|
} |
||||
|
.ring-timing-center { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
overflow: hidden; |
||||
|
position: absolute; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,8 @@ |
|||||
|
// 上传文件的扩展名
|
||||
|
export const UPLOAD_EXTENSION = ['.xls', '.xlsx', '.zip', '.exe', '.pdf', '.doc', '.docx', '.ppt', '.pptx']; |
||||
|
|
||||
|
// 审核的快捷用语
|
||||
|
export const quickWords = { |
||||
|
RESOLVE: ['加油,再接再厉!', '很棒!', '不错,很详细!', '加油,再接再厉'], // 审核通过常用的审批语
|
||||
|
REJECT: ['不详细', '还有需要改进的地方', '驳回审批1', '驳回审批2'], // 审核驳回常用的审批语
|
||||
|
}; |
||||
@ -0,0 +1,20 @@ |
|||||
|
// 环境 (development|production)
|
||||
|
export const SCENE = 'development'; |
||||
|
|
||||
|
// 一些特殊的API区分生产测试环境
|
||||
|
export const api = { |
||||
|
baseUrl: { |
||||
|
development: 'https://test.tall.wiki', |
||||
|
production: 'https://www.tall.wiki', |
||||
|
}, |
||||
|
msgUrl: { |
||||
|
development: 'wss://test.tall.wiki/websocket/message/v4.0/ws', |
||||
|
production: 'wss://www.tall.wiki/websocket/message/v4.0/ws', |
||||
|
}, |
||||
|
upload: { |
||||
|
development: 'https://test.tall.wiki/filedeal/file/upload/multiple', |
||||
|
production: 'http://101.201.226.21/filedeal/file/upload/multiple', |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export const UPLOAD_URL = api.upload[SCENE]; // 多文件上传路径
|
||||
@ -0,0 +1,5 @@ |
|||||
|
<template> |
||||
|
<div class="404">404</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup></script> |
||||
@ -0,0 +1,53 @@ |
|||||
|
<template> |
||||
|
<theme class="pt-1 h-full"> |
||||
|
<view class="h-full overflow-y-scroll bg-white rounded-md p-3 text-gray-400"> |
||||
|
<view v-for="item in checkerList" class="flex justify-between"> |
||||
|
<view> |
||||
|
<view class="mb-1 text-gray-800"> |
||||
|
{{ item.checkerName }} |
||||
|
</view> |
||||
|
<view class="mb-1 text-xs"> |
||||
|
{{ item.remark }} |
||||
|
</view> |
||||
|
<view class="text-xs" v-if="+item.checkTime > 0"> |
||||
|
{{ dayjs(+item.checkTime).format('MM-DD HH:mm') }} |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="flex flex-col justify-center"> |
||||
|
<view class="mb-1 text-green-600" v-if="item.status === 1"> 已通过 </view> |
||||
|
<view class="mb-1 text-red-600" v-if="item.status === 2"> 已驳回 </view> |
||||
|
<view v-if="+item.score > 0"> |
||||
|
<zwp-ring-timing mode="chart" :value="item.score" active-color="#F59E0B" radius="30" bar-width="4"> |
||||
|
<text class="text-yellow-500 font-medium">{{ item.score }}</text> |
||||
|
</zwp-ring-timing> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</theme> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref } from 'vue'; |
||||
|
import { onLoad } from '@dcloudio/uni-app'; |
||||
|
import dayjs from 'dayjs'; |
||||
|
|
||||
|
const checkerList = ref([]); |
||||
|
|
||||
|
onLoad(options => { |
||||
|
getQueryCheckLog(options); |
||||
|
}); |
||||
|
|
||||
|
async function getQueryCheckLog(options) { |
||||
|
try { |
||||
|
const param = { deliverRecordId: options.deliverRecordId }; |
||||
|
const data = await uni.$u.api.queryCheckLog(param); |
||||
|
checkerList.value = data; |
||||
|
} catch (error) { |
||||
|
console.log('error: ', error); |
||||
|
uni.$ui.showToast('获取检查交付物历史失败'); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"></style> |
||||
@ -0,0 +1,25 @@ |
|||||
|
<template> |
||||
|
<web-view :src="src"></web-view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref } from 'vue'; |
||||
|
import { onLoad } from '@dcloudio/uni-app'; |
||||
|
|
||||
|
const src = ref(''); |
||||
|
|
||||
|
onLoad(options => { |
||||
|
if (!options) { |
||||
|
uni.redirectTo({ url: '/pages/404/404' }); |
||||
|
return; |
||||
|
} |
||||
|
if (options.url) { |
||||
|
src.value = options.url; |
||||
|
} |
||||
|
if (options.name) { |
||||
|
uni.setNavigationBarTitle({ |
||||
|
title: options.name || '详情页', |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,68 @@ |
|||||
|
<template> |
||||
|
<theme> |
||||
|
<view class="h-full w-full px-3 pt-1 overflow-y-scroll"> |
||||
|
<view class="bg-white my-2 rounded-md p-3 text-gray-400" v-for="item in listRef"> |
||||
|
<!-- 插件名称和提交时间显示 --> |
||||
|
<view class="flex justify-between mb-2"> |
||||
|
<view class="text-gray-800">{{ deliverName }}</view> |
||||
|
<view class="text-xs">{{ dayjs(+item.submitTime).format('MM-DD HH:mm') }}</view> |
||||
|
</view> |
||||
|
<!-- 提交的链接 --> |
||||
|
<DeliverLink v-if="item.details[0]" :link="item.details[0]" /> |
||||
|
<!-- 该插件物的审核人 --> |
||||
|
<view class="mb-1 mt-3">审核人</view> |
||||
|
<view class="flex justify-between mb-2" v-for="checkItem in item.checkerList"> |
||||
|
<view> |
||||
|
<view class="mb-1 text-gray-800 font-semibold"> |
||||
|
{{ checkItem.checkerName }} |
||||
|
</view> |
||||
|
<view class="mb-1 text-xs"> |
||||
|
{{ checkItem.remark }} |
||||
|
</view> |
||||
|
<view class="mb-1 text-xs" v-if="+checkItem.checkTime > 0"> |
||||
|
{{ dayjs(+checkItem.checkTime).format('MM-DD HH:mm') }} |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="text-center text-xs"> |
||||
|
<view v-if="checkItem.status == null" class="text-gray-400">待审核</view> |
||||
|
<view v-else-if="checkItem.status === 1"> |
||||
|
<view class="text-green-600 mb-1">已通过</view> |
||||
|
|
||||
|
<zwp-ring-timing mode="chart" :value="checkItem.score" active-color="#F59E0B" radius="30" bar-width="4"> |
||||
|
<text class="text-yellow-500 font-medium">{{ checkItem.score }}</text> |
||||
|
</zwp-ring-timing> |
||||
|
</view> |
||||
|
<view class="text-red-600" v-else>已驳回</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</theme> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref } from 'vue'; |
||||
|
import { onLoad } from '@dcloudio/uni-app'; |
||||
|
import dayjs from 'dayjs'; |
||||
|
|
||||
|
const listRef = ref([]); |
||||
|
const deliverName = ref(''); |
||||
|
|
||||
|
onLoad(options => { |
||||
|
// 根据交付物id获取上传记录 |
||||
|
(async function getHistory() { |
||||
|
try { |
||||
|
const param = { deliverId: options.deliverId }; |
||||
|
const data = await uni.$u.api.getDeliverHistory(param); |
||||
|
deliverName.value = data.deliverName; |
||||
|
listRef.value = data.deliverRecordList; |
||||
|
} catch (error) { |
||||
|
console.log('error: ', error); |
||||
|
uni.$ui.showToast('获取交付物历史失败'); |
||||
|
} |
||||
|
})(); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"></style> |
||||
@ -1,26 +0,0 @@ |
|||||
<template> |
|
||||
<theme class="h-full w-full pt-1"> |
|
||||
<view class="bg-white m-5 rounded-md p-3"> |
|
||||
<view class="flex justify-between text-gray-400 mb-2"> |
|
||||
<view>插件名</view> <view>提交时间</view> |
|
||||
</view> |
|
||||
<view class="text-blue-400 mb-2"> |
|
||||
链接 |
|
||||
</view> |
|
||||
<view class="mb-2">审核人</view> |
|
||||
</view> |
|
||||
</theme> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss"> |
|
||||
|
|
||||
</style> |
|
||||
@ -0,0 +1,84 @@ |
|||||
|
<template> |
||||
|
<!-- 审核通过的modal --> |
||||
|
<u-mask :show="data.mode !== 'HIDE'" @click="handleHide"> |
||||
|
<view class="modal-content-wrap" @click.stop> |
||||
|
<!-- 通过modal的标题 --> |
||||
|
<view class="modal-content-head"> {{ data.mode === 'RESOLVE' ? '审核通过' : '审核驳回' }} </view> |
||||
|
|
||||
|
<view class="modal-content-body"> |
||||
|
<!-- 评分 --> |
||||
|
<view class="flex justify-between mb-4" v-show="data.mode === 'RESOLVE'"> |
||||
|
<u-number-box v-model="score" size="30" input-width="50" :max="100" :min="0" :step="1"></u-number-box> |
||||
|
<view class="w-32 pt-4"> |
||||
|
<u-slider v-model="score" active-color="#34D399" :max="100" :min="0" :step="1"></u-slider> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<u-input v-model="commit" type="textarea" :border="true" :auto-height="true" /> |
||||
|
|
||||
|
<view class="common-list"> |
||||
|
<view v-for="item in words" class="leading-12" @click="commit = item"> |
||||
|
{{ item }} |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="modal-content-foot"> |
||||
|
<view class="cancel" @click="handleHide"> 取消 </view> |
||||
|
<view class="confirm" @click="handleSubmit(data.mode)"> 确定 </view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</u-mask> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { quickWords } from '@/config/deliver'; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { type: Object, default: {} }, |
||||
|
}); |
||||
|
const emits = defineEmits(['hide', 'submit-end']); |
||||
|
const store = useStore(); |
||||
|
const words = computed(() => quickWords[props.data.mode]); // 快捷用语 |
||||
|
const projectId = computed(() => store.getters['project/projectId']); |
||||
|
|
||||
|
const commit = ref(''); // 提交的信息 |
||||
|
const score = ref(100); // 评分 |
||||
|
|
||||
|
/** |
||||
|
* 提交评审信息 |
||||
|
* 提交成功后隐藏modal 重置表单控件 |
||||
|
* 给父组件信息 更新值 |
||||
|
* @param {string} mode 'RESOLVE'|'REJECT' |
||||
|
*/ |
||||
|
async function handleSubmit(mode) { |
||||
|
try { |
||||
|
const deliverRecordId = props.data.deliverRecordId(); |
||||
|
const param = { |
||||
|
projectId: projectId.value, |
||||
|
deliverRecordId, |
||||
|
type: mode === 'RESOLVE' ? 1 : 2, |
||||
|
remark: commit.value, |
||||
|
score: mode === 'RESOLVE' ? score.value : '', |
||||
|
}; |
||||
|
await uni.$u.api.checkDeliver(param); |
||||
|
handleHide(); // 隐藏 + 重置 |
||||
|
uni.$ui.showToast('审核信息提交成功'); |
||||
|
// 通知父组件评审成功 更新信息 |
||||
|
emits('submit-end', param); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$ui.showToast('审核信息提交失败, 请稍后重试'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 隐藏及 重置 |
||||
|
function handleHide() { |
||||
|
emits('hide'); |
||||
|
// 重置相关数据 |
||||
|
score.value = 100; |
||||
|
commit.value = ''; |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,225 @@ |
|||||
|
<template> |
||||
|
<!-- 是自己的任务 且该任务有交付物 才显示提交组件 --> |
||||
|
<view class="bg-white px-2 rounded-md relative" @longpress.prevent="showMask = true"> |
||||
|
<!-- 插件名称输入和提交 --> |
||||
|
<view class="flex item-center justify-between py-2"> |
||||
|
<view class="flex-1"> |
||||
|
<text v-if="deliver.deliverName"> |
||||
|
{{ deliver.deliverName }} |
||||
|
</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 提交 --> |
||||
|
<u-button |
||||
|
type="primary" |
||||
|
size="mini" |
||||
|
@click="submit" |
||||
|
class="self-center" |
||||
|
:disabled="submitState" |
||||
|
:ripple="true" |
||||
|
:loading="submitBtnLoading" |
||||
|
> |
||||
|
提交 |
||||
|
</u-button> |
||||
|
|
||||
|
<!-- 查看提交历史的按钮 --> |
||||
|
<u-icon name="arrow-right" class="ml-3" @click="openDeliverHistory"></u-icon> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 插件上传方式 --> |
||||
|
<view> |
||||
|
<view class="link-box"> |
||||
|
<u-input v-model="linkValue" type="text" :border="true" placeholder="请输入交付物地址/链接" class="input"></u-input> |
||||
|
</view> |
||||
|
<view class="mt-3"> |
||||
|
<u-button size="mini" :plain="true" type="primary" class="mr-3" @click="paste">粘贴</u-button> |
||||
|
<u-button size="mini" :plain="true" type="primary" class="mr-3" @click="uploadFile">文件</u-button> |
||||
|
<u-button size="mini" :plain="true" type="primary" class="mr-3" @click="uploadPhoto">拍照</u-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 编辑和删除的遮罩层 --> |
||||
|
<view class="mask flex items-center justify-center bg-grey" v-show="showMask" @click="showMask = false"> |
||||
|
<view class="bg-yellow-500 text-white w-12 h-12 text-center leading-12 rounded-w-12 mx-8" @click.stop="showEditModal = true"> |
||||
|
修改 |
||||
|
</view> |
||||
|
<view class="bg-red-500 text-white w-12 h-12 text-center leading-12 rounded-w-12 mx-8" @click.stop="showDeleteModal = true"> |
||||
|
删除 |
||||
|
</view> |
||||
|
<!-- 删除的二次提示modal --> |
||||
|
<u-modal v-model="showDeleteModal" :content="content" :show-cancel-button="true" @confirm="confirmDelete"></u-modal> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 编辑交付物标题的modal --> |
||||
|
<u-mask :show="showEditModal" @click="showEditModal = false"> |
||||
|
<view class="modal-content-wrap" @click.stop> |
||||
|
<view class="modal-content-head">交付物标题名称</view> |
||||
|
<view class="modal-content-body"> |
||||
|
<u-input :border="true" placeholder="请输入交付物名称" v-model="newInputRef"></u-input> |
||||
|
</view> |
||||
|
|
||||
|
<view class="modal-content-foot"> |
||||
|
<view class="cancel" @click="showEditModal = false">取消</view> |
||||
|
<view class="confirm" @click="confirmEditDeliverName">确定</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</u-mask> |
||||
|
|
||||
|
<!-- 插件审核人员选择 --> |
||||
|
<Reviewer ref="reviewerRef" /> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed, inject } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { UPLOAD_URL } from '@/config/index'; |
||||
|
import { UPLOAD_EXTENSION } from '@/config/deliver'; |
||||
|
|
||||
|
const deliver = inject('deliver'); |
||||
|
const task = inject('task'); |
||||
|
const store = useStore(); |
||||
|
const emits = defineEmits(['upload-success']); |
||||
|
|
||||
|
const reviewerRef = ref(null); |
||||
|
const submitBtnLoading = ref(false); |
||||
|
const linkValue = ref(''); // 链接的值 |
||||
|
const showMask = ref(false); // 编辑和删除页面 |
||||
|
const showEditModal = ref(false); // 编辑交付物标题的modal |
||||
|
const newInputRef = ref(''); // 修改的插件名的值 |
||||
|
const showDeleteModal = ref(false); // 删除二次提示的modal |
||||
|
const content = '是否确定删除'; |
||||
|
const showBadge = ref(false); // u-badge的显示与隐藏 |
||||
|
|
||||
|
// 判断提交按钮的状态 |
||||
|
const submitState = computed(() => !linkValue.value); |
||||
|
const projectId = computed(() => store.getters['project/projectId']); |
||||
|
|
||||
|
// 验证提交的交付物信息格式 |
||||
|
function validateDeliverForm(checkedCheckers) { |
||||
|
const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?$/; |
||||
|
if (!reg.test(linkValue.value)) { |
||||
|
// 显示toast信息 |
||||
|
uni.$ui.showToast('请输入正确的链接'); |
||||
|
return false; |
||||
|
} |
||||
|
// 没有检查人 提示选择检查人 |
||||
|
if (!checkedCheckers || !checkedCheckers.length) { |
||||
|
uni.$ui.showToast('请选择检查人'); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
// 提交交付物信息 |
||||
|
async function submit() { |
||||
|
const { checkedCheckers } = reviewerRef.value; // 拿到选择检查人组件中选中的检查人 |
||||
|
|
||||
|
// 提交前的验证 |
||||
|
if (!validateDeliverForm(checkedCheckers)) return; |
||||
|
submitBtnLoading.value = true; // 显示loading |
||||
|
// 验证成功后进行请求 |
||||
|
try { |
||||
|
const checkerList = []; |
||||
|
checkedCheckers.forEach(item => { |
||||
|
checkerList.push(item.memberId); |
||||
|
}); |
||||
|
const param = { |
||||
|
projectId: projectId.value, |
||||
|
deliverId: deliver.value.deliverId, |
||||
|
fileList: [linkValue.value], |
||||
|
checkerList, |
||||
|
}; |
||||
|
await uni.$u.api.submitDeliverInfo(param); |
||||
|
uni.$ui.showToast('提交交付物信息成功'); |
||||
|
resetControlState(); // 重置控件的初始状态 |
||||
|
emits('upload-success'); |
||||
|
} catch (error) { |
||||
|
console.log('error: ', error); |
||||
|
uni.$ui.showToast('提交交付物信息失败'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 重置控件的初始状态 |
||||
|
function resetControlState() { |
||||
|
submitBtnLoading.value = false; // 隐藏loading |
||||
|
linkValue.value = ''; // 清空输入框内容 |
||||
|
reviewerRef.value.collapsed = true; // 折叠检查人面板 |
||||
|
} |
||||
|
|
||||
|
// 查看历史记录 |
||||
|
function openDeliverHistory() { |
||||
|
const { deliverId } = deliver.value; |
||||
|
// console.log(deliverId) |
||||
|
uni.navigateTo({ url: `/pages/submitLog/submitLog?deliverId=${deliverId}` }); |
||||
|
} |
||||
|
|
||||
|
// 粘贴上传 |
||||
|
function paste() { |
||||
|
uni.getClipboardData({ |
||||
|
success(res) { |
||||
|
linkValue.value = res.data; |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 文件上传 |
||||
|
async function uploadFile() { |
||||
|
try { |
||||
|
const data = await uni.$upload.chooseAndUpload(UPLOAD_URL, {}, UPLOAD_EXTENSION, 'files'); |
||||
|
// console.log(data[0]); |
||||
|
linkValue.value = data[0].visitUrl; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// TODO: 拍照上传 |
||||
|
async function uploadPhoto() { |
||||
|
try { |
||||
|
const data = await uni.$upload.chooseAndUpload(UPLOAD_URL, {}, UPLOAD_EXTENSION, 'files'); |
||||
|
// console.log(data[0]) |
||||
|
linkValue.value = data[0].visitUrl; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 确定修改交付物名称 |
||||
|
async function confirmEditDeliverName() { |
||||
|
// TODO: 发请求 请求成功后更新task里的交付物信息 |
||||
|
if (!newInputRef.value) { |
||||
|
uni.$ui.showToast('输入不能为空'); |
||||
|
} |
||||
|
try { |
||||
|
const param = { |
||||
|
projectId: projectId.value, |
||||
|
taskId: task.id, |
||||
|
deliverName: newInputRef.value, |
||||
|
}; |
||||
|
await uni.$u.api.editDeliverName(param); |
||||
|
// uni.$ui.showToast('修改交付物名称成功'); |
||||
|
// 请求成功 才会清空 请求失败保留 |
||||
|
showEditModal.value = false; |
||||
|
showMask.value = false; |
||||
|
showBadge.value = false; |
||||
|
newInputRef.value = ''; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$ui.showToast('修改交付物名称失败'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 二次确认后删除 |
||||
|
async function confirmDelete() { |
||||
|
try { |
||||
|
showDeleteModal.value = true; |
||||
|
deliverRef.value = false; |
||||
|
await uni.$u.api.deleteDeliver(); |
||||
|
uni.$ui.showToast('删除交付物成功'); |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
uni.$ui.showToast('删除交付物失败'); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,18 @@ |
|||||
|
<template> |
||||
|
<div class="flex justify-around"> |
||||
|
<button class="text-xs bg-blue-500 text-white leading-6" style="width: 250rpx" @click="openAudit">财务审批</button> |
||||
|
<button class="text-xs bg-blue-500 text-white leading-6" style="width: 250rpx" @click="openStatistical">财务统计</button> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
// DEBUG:打开财务审批详情页 |
||||
|
function openAudit() { |
||||
|
uni.$ui.openDetail({ url: 'https://www.taobao.com', name: '财务审批' }); |
||||
|
} |
||||
|
|
||||
|
// DEBUG:打开财务统计详情页 |
||||
|
function openStatistical() { |
||||
|
uni.$ui.openDetail({ url: 'https://www.taobao.com', name: '财务统计' }); |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,73 @@ |
|||||
|
<!-- 财务条内置组件 --> |
||||
|
<template> |
||||
|
<view class="finance-wrap" v-if="data" @click="openFinance"> |
||||
|
<!-- 预算和奖金 --> |
||||
|
<view class="finance-row"> |
||||
|
<view class="finance-item" :style="{ width: `${(data.budget * 100) / (data.budget + data.bonus)}%`, 'background-color': '#93C5FD' }"> |
||||
|
预算{{ data.budget / 100 }} |
||||
|
</view> |
||||
|
<view class="finance-item" :style="{ width: `${(data.bonus * 100) / (data.budget + data.bonus)}%`, 'background-color': '#12c77e' }"> |
||||
|
奖金{{ data.bonus / 100 }} |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 项目采购日常采购 --> |
||||
|
<view class="finance-row"> |
||||
|
<view |
||||
|
class="finance-item" |
||||
|
:style="{ width: `${(data.projectExpend * 100) / (data.projectExpend + data.dailyExpend)}%`, 'background-color': '#FBBF24' }" |
||||
|
> |
||||
|
项目采购{{ data.dailyExpend / 100 }} |
||||
|
</view> |
||||
|
<view |
||||
|
class="finance-item" |
||||
|
:style="{ width: `${(data.dailyExpend * 100) / (data.projectExpend + data.dailyExpend)}%`, 'background-color': '#a1fd93' }" |
||||
|
> |
||||
|
日常采购{{ data.dailyExpend / 100 }} |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, inject } from 'vue'; |
||||
|
|
||||
|
const task = inject('task'); |
||||
|
const data = ref(null); |
||||
|
|
||||
|
// 查询任务上的财务条数据 |
||||
|
async function getFinanceByTaskData() { |
||||
|
try { |
||||
|
console.log('task: ', task); |
||||
|
const detailId = task.detailId; |
||||
|
data.value = await uni.$u.api.getFinanceByTask(detailId); |
||||
|
} catch (error) { |
||||
|
console.log('getFinanceByTaskData error: ', error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
getFinanceByTaskData(); |
||||
|
|
||||
|
// 打开详情页 |
||||
|
function openFinance() { |
||||
|
// DEBUG: 假数据 换成财务条详情页的地址 |
||||
|
uni.$ui.openDetail({ url: 'http://www.baidu.com', name: '财务' }); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.finance-wrap { |
||||
|
.finance-row { |
||||
|
display: flex; |
||||
|
|
||||
|
.finance-item { |
||||
|
margin: 3rpx 5rpx; |
||||
|
font-size: 12px; |
||||
|
text-align: center; |
||||
|
border-radius: 8rpx; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
overflow-x: visible; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,11 @@ |
|||||
|
<!-- 资源管理 --> |
||||
|
<template> |
||||
|
<button class="text-xs bg-blue-500 text-white leading-6" style="width: 500rpx" @click="openSourceManage">资源管理</button> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
function openSourceManage() { |
||||
|
// DEBUG: 假数据 换成财务条 资源管理的地址 |
||||
|
uni.$ui.openDetail({ url: 'http://m.jd.com', name: '资源管理' }); |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,108 @@ |
|||||
|
@url=https://test.tall.wiki/gateway/defaultwbs |
||||
|
@type=content-type: application/json |
||||
|
@token=eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2NDI0MDU2ODcsInN1YiI6IjEyMTc2NDc2ODY1OTgxMzU4MDgiLCJhdXRoSWQiOiIxMTc3MTU4ODQ4ODg1MTY2MDgwIiwiZXhwIjoxNjQyNDkyMDg3fQ.GDHzvVN6kAF3mVanxYTxBBlZP1I08lCD4_zbazLX7AQ |
||||
|
|
||||
|
### login |
||||
|
# @name login |
||||
|
POST https://test.tall.wiki/gateway/tall3/v3.0/users/signin |
||||
|
{{type}} |
||||
|
|
||||
|
{ |
||||
|
"client": 1, |
||||
|
"data": { |
||||
|
"credential": "123456", |
||||
|
"identifier": "zy11" |
||||
|
}, |
||||
|
"type": 3 |
||||
|
} |
||||
|
|
||||
|
### 查看成员 |
||||
|
POST {{url}}/deliver/queryChecker |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"projectId": "1418109550141382656" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 修改编辑交付物名称 |
||||
|
POST {{url}}/deliver/saveDeliver |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"projectId": "1418109550141382656", |
||||
|
"taskId": "1418109566541111296", |
||||
|
"deliverName":"测试交付物1" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 查询交付物 |
||||
|
POST {{url}}/deliver/getDeliver |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"taskId": "1418109566541111296" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 提交交付物信息 |
||||
|
POST {{url}}/deliver/submitDeliver |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"projectId": "1418109550141382656", |
||||
|
"deliverId": "1482975132598411264", |
||||
|
"fileList": [ |
||||
|
"asdasd" |
||||
|
], |
||||
|
"checkerList":[ |
||||
|
"1418109552909623296", |
||||
|
"1418109555648503808" |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 检查交付物 |
||||
|
POST {{url}}/deliver/checkDeliver |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"deliverRecordId": "1482980930758123520", |
||||
|
"projectId": "1418109550141382656", |
||||
|
"type": "2", |
||||
|
"remark": "我后悔了", |
||||
|
"score": "10.2" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 查看交付物提交历史 |
||||
|
POST {{url}}/deliver/queryRecord |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"deliverId": "1482975132598411264" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
### 查看检查记录 |
||||
|
POST {{url}}/deliver/queryCheckLog |
||||
|
{{type}} |
||||
|
Authorization: Bearer {{token}} |
||||
|
|
||||
|
{ |
||||
|
"param":{ |
||||
|
"deliverRecordId": "1482980930758123520" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
export default { |
||||
|
namespaced: true, |
||||
|
state: { |
||||
|
deliverRecordId: '', // 交付物记录id
|
||||
|
}, |
||||
|
getters: {}, |
||||
|
mutations: { |
||||
|
/** |
||||
|
* 设置交付物记录id |
||||
|
* @param {object} state |
||||
|
* @param {string} recordId |
||||
|
*/ |
||||
|
setDeliverRecordId(state, recordId) { |
||||
|
state.deliverRecordId = recordId; |
||||
|
}, |
||||
|
}, |
||||
|
actions: {}, |
||||
|
}; |
||||
@ -0,0 +1,25 @@ |
|||||
|
import { SCENE, api } from '@/config/index'; |
||||
|
|
||||
|
export default { |
||||
|
namespaced: true, |
||||
|
state: { |
||||
|
apiPath: '/ptccsens/v1.0/finance', // 财务条apiPath
|
||||
|
}, |
||||
|
getters: { |
||||
|
// 完整路径
|
||||
|
fullPath({ apiPath }) { |
||||
|
return `${api.baseUrl[SCENE]}${apiPath}`; |
||||
|
}, |
||||
|
}, |
||||
|
mutations: { |
||||
|
/** |
||||
|
* 设置apiPath |
||||
|
* @param {object} state |
||||
|
* @param {string} path 路径可能随着业务、项目变化 |
||||
|
*/ |
||||
|
setApiPath(state, path) { |
||||
|
state.apiPath = path; |
||||
|
}, |
||||
|
}, |
||||
|
actions: {}, |
||||
|
}; |
||||
Loading…
Reference in new issue