Browse Source

feat: "交付物"

tall1
xuesinan 4 years ago
parent
commit
ecd6658d15
  1. 3
      CHANGELOG.md
  2. 3
      src/apis/plugin.js
  3. 2
      src/apis/wbs.js
  4. 2
      src/components/Globals/Globals.vue
  5. 78
      src/plugins/p-deliver-check/p-deliver-check.vue
  6. 120
      src/plugins/p-deliver-check/p-deliver-check1.vue
  7. 64
      src/plugins/p-deliver-check/p-deliver-check2.vue
  8. 78
      src/plugins/p-delivery-history/p-delivery-history.vue
  9. 73
      src/plugins/p-delivery-history/p-delivery-history2.vue
  10. 392
      src/plugins/p-upload-deliverable/p-upload-deliverable.vue
  11. 297
      src/plugins/p-upload-deliverable/p-upload-deliverable1.vue
  12. 94
      src/plugins/p-upload-deliverable/p-upload-deliverable2.vue
  13. 3
      src/utils/tall.js
  14. 69
      src/utils/upload.js

3
CHANGELOG.md

@ -1,4 +1,4 @@
# 0.1.0 (2021-12-13)
# 0.1.0 (2021-12-24)
### 🌟 新功能
范围|描述|commitId
@ -33,6 +33,7 @@
- | 设置小红点 | 9316bcb
- | 时间基准线,默认插件 | a33ba1e
- | 时间轴界面 | 33927e9
- | 时间轴时间、交付物新原型 | c57f986
- | 时间轴修改状态时提示框增加 | e841392
- | 适配小程序;小程序登录 | cefc0eb
- | 首页项目样式改变 | 8514c85

3
src/apis/plugin.js

@ -15,6 +15,9 @@ const install = (Vue, vm) => {
vm.$u.api.queryDeliverOfTask = param => vm.$u.post(`${uni.$t.domain}/deliver/queryDeliverOfTask`, param);
// 检查交付物
vm.$u.api.checkDeliver = param => vm.$u.post(`${uni.$t.domain}/deliver/checkDeliver`, param);
// 单文件上传
vm.$u.api.fileUpload = formData => vm.$t.chooseAndUpload(`${uni.$t.domain}/file/upload`, formData);
vm.$u.api.ImgUpload = formData => vm.$t.chooseAndUploadImg(`${uni.$t.domain}/file/upload`, formData, ['camera']);
};
export default { install };

2
src/apis/wbs.js

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

2
src/components/Globals/Globals.vue

@ -62,7 +62,7 @@ export default {
...mapGetters('task', ['globals']),
globalsHeight: function () {
let h = ((this.sysHeight - 44 - 30 - 10) / 5) * 4;
let h = ((this.sysHeight - 44 - 30 - 10) / 5) * 3;
return h;
},
},

78
src/plugins/p-deliver-check/p-deliver-check.vue

@ -1,17 +1,22 @@
<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 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="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 class="examine-btn flex justify-center mt-5">
<u-button @click="submit">提交</u-button>
<u-button @click="$emit('closeScore')">取消</u-button>
</view>
</view>
</template>
@ -19,6 +24,14 @@
<script>
export default {
name: 'p-deliver-check',
props: {
auditStatus: {
type: Number,
default: 1,
},
},
data() {
return {
remark: '',
@ -61,4 +74,47 @@ export default {
};
</script>
<style></style>
<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>

120
src/plugins/p-deliver-check/p-deliver-check1.vue

@ -1,120 +0,0 @@
<template>
<!-- 交付物审核 -->
<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>
<script>
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>
<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>

64
src/plugins/p-deliver-check/p-deliver-check2.vue

@ -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>

78
src/plugins/p-delivery-history/p-delivery-history.vue

@ -3,42 +3,44 @@
<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 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 class="text-gray-400 text-xs mt-1">{{ checker.remark }}</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="bottom">
<PDeliverCheck @closeScore="closeScore" @submit="submit"></PDeliverCheck>
<uni-popup :maskClick="false" background-color="#fff" ref="popup" type="center">
<PDeliverCheck :auditStatus="auditStatus" @closeScore="closeScore" @submit="submit"></PDeliverCheck>
</uni-popup>
</view>
</template>
@ -46,7 +48,7 @@
<script>
import { mapGetters } from 'vuex';
import UniPopup from '../../components/uni-popup/uni-popup.vue';
import PDeliverCheck from '../p-deliver-check/p-deliver-check1.vue';
import PDeliverCheck from '../p-deliver-check/p-deliver-check.vue';
export default {
name: 'p-delivery-history',
@ -58,6 +60,7 @@ export default {
show: false,
options: null,
loading: true, //
auditStatus: 1, // 1 2
};
},
@ -73,6 +76,11 @@ export default {
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);
@ -82,12 +90,13 @@ export default {
showScore(checkId, status) {
// refuni-popup , type ['top','left','bottom','right','center']
this.$refs.popup.open('bottom');
this.$refs.popup.open();
this.options = { checkId, status };
this.auditStatus = status;
},
closeScore() {
this.$refs.popup.close('bottom');
this.$refs.popup.close();
},
async submit(remark, score) {
@ -137,4 +146,11 @@ export default {
};
</script>
<style></style>
<style scoped>
.action-btn {
padding: 0;
width: 80rpx;
height: 40rpx;
line-height: 40rpx;
}
</style>

73
src/plugins/p-delivery-history/p-delivery-history1.vue → src/plugins/p-delivery-history/p-delivery-history2.vue

@ -3,44 +3,42 @@
<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 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 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 :maskClick="false" background-color="#fff" ref="popup" type="bottom">
<PDeliverCheck @closeScore="closeScore" @submit="submit"></PDeliverCheck>
</uni-popup>
</view>
</template>
@ -48,7 +46,7 @@
<script>
import { mapGetters } from 'vuex';
import UniPopup from '../../components/uni-popup/uni-popup.vue';
import PDeliverCheck from '../p-deliver-check/p-deliver-check1.vue';
import PDeliverCheck from '../p-deliver-check/p-deliver-check.vue';
export default {
name: 'p-delivery-history',
@ -60,7 +58,6 @@ export default {
show: false,
options: null,
loading: true, //
auditStatus: 1, // 1 2
};
},
@ -85,13 +82,12 @@ export default {
showScore(checkId, status) {
// refuni-popup , type ['top','left','bottom','right','center']
this.$refs.popup.open();
this.$refs.popup.open('bottom');
this.options = { checkId, status };
this.auditStatus = status;
},
closeScore() {
this.$refs.popup.close();
this.$refs.popup.close('bottom');
},
async submit(remark, score) {
@ -141,11 +137,4 @@ export default {
};
</script>
<style scoped>
.action-btn {
padding: 0;
width: 80rpx;
height: 40rpx;
line-height: 40rpx;
}
</style>
<style></style>

392
src/plugins/p-upload-deliverable/p-upload-deliverable.vue

@ -1,94 +1,426 @@
<template>
<!-- 上传交付物 -->
<view class="py-2">
<u-input :auto-height="autoHeight" :border="border" :height="height" :type="type" v-model="content" width="100" />
<view class="pt-2 relative">
<template v-if="history.length === 0 || currStatus === -1 || currStatus === 2">
<u-input v-if="deliveryType === 1" :border="border" :height="height" :type="type" v-model="content" placeholder="请输入链接" />
<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"
/>
<!-- <u-upload
v-if="deliveryType === 3"
max-count="1"
:source-type="['camera']"
:name="'param'"
:action="action"
:header="header"
></u-upload> -->
<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)">
<text class="examine-people text-right mr-2">{{ examinePerpol }}</text>
<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"
>
{{ 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>
<!-- <u-icon @click="changeShowHistory" name="arrow-right" v-if="!showHistory"></u-icon>
<u-icon @click="changeShowHistory" name="arrow-down" v-else></u-icon> -->
</view>
<template v-if="history.length > 0">
<template v-for="(item, index) in history">
<view class="to-examine mt-2 py-1 flex flex-wrap overflow-hidden break-all" :key="index" v-if="item.content">
<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>
<!-- <template v-if="showHistory"> -->
<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>
</template>
<!-- 选择检查人 -->
<ChooseChecker ref="checker" :checkerList="checkerList" @setCheckerList="setCheckerList"></ChooseChecker>
<!-- <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>
<!-- <view class="mt-2 flex justify-between">
<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" />
<p-delivery-history :task="task" v-if="showHistory" /> -->
</view>
</template>
<script>
import ChooseChecker from '@/components/ChooseChecker/ChooseChecker.vue';
// import ChooseChecker from '@/components/ChooseChecker/ChooseChecker.vue';
import { mapState, mapGetters } from 'vuex';
export default {
name: 'p-upload-deliverable',
components: { ChooseChecker },
// components: { ChooseChecker },
props: { task: { type: Object, default: null } },
data() {
return {
content: '',
type: 'textarea',
type: 'text',
border: true,
height: 30,
autoHeight: true,
height: 64,
checkerList: [],
showHistory: false, //
// showHistory: false, //
list: [],
examinePerpol: '请选择审核人',
isShowMembers: false, //
currStatus: -1, //
history: [],
customStyle: {
borderColor: '#1890FF',
color: '#1890FF',
marginRight: '16px',
},
deliveryType: 1,
//
// action: `${uni.$t.domain}/file/upload`,
fileData: {
fileId: '',
name: '',
path: '',
},
imgFileData: {
fileId: '',
name: '',
path: '',
},
};
},
computed: {
...mapState('role', ['members']),
...mapState('user', ['token']),
...mapGetters('project', ['projectId']),
checkers() {
const arr = [];
// header() {
// return { Authorization: `Bearer ${this.token}` };
// },
},
mounted() {
if (this.members.length > 0) {
this.list = [];
if (this.members.length) {
this.members.forEach(member => {
const item = { value: member.memberId, label: member.name };
arr.push(item);
const item = { id: member.memberId, name: member.name, checked: false };
this.list.push(item);
});
}
return arr;
},
}
this.getDeliverOfTask();
},
methods: {
//
setCheckerList(checked, item) {
if (checked) {
this.checkerList.push(item.memberId);
//
changeDeliveryType(data) {
console.log(11111);
this.deliveryType = data;
},
// checkbox
checkboxChange(e, data) {
if (e.value) {
this.checkerList.push(data.id);
} else {
const index = this.checkerList.findIndex(checker => checker === item.memberId);
const index = this.checkerList.findIndex(checker => checker === data.id);
this.checkerList.splice(index, 1);
}
},
// checkboxcheckbox-group
checkboxGroupChange(e) {
if (e.length > 0) {
this.examinePerpol = e[0];
e.forEach((item, index) => {
if (index > 0) {
this.examinePerpol += ' ' + item;
}
});
} else {
this.examinePerpol = '请选择审核人';
}
},
//
showMembers() {
this.isShowMembers = !this.isShowMembers;
},
//
// 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;
// changeShowHistory() {
// this.showHistory = !this.showHistory;
// },
//
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 };
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.content = '';
this.checkerList = [];
this.$refs.checker.clearChecked();
this.currStatus = 0;
// this.isShowMembers = false;
this.getDeliverOfTask();
// this.content = '';
// this.checkerList = [];
// this.$refs.checker.clearChecked();
} 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;
data.forEach(item => {
if (item.filePath) {
item.content = item.filePath;
}
item.checkerList.forEach(v => {
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"></style>
<style scoped lang="scss">
.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;
color: #999999;
}
::v-deep .u-checkbox__icon-wrap {
width: 20rpx !important;
height: 20rpx !important;
border-radius: 50%;
}
::v-deep .u-checkbox__label {
margin-left: 16rpx;
margin-right: 0;
}
::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>

297
src/plugins/p-upload-deliverable/p-upload-deliverable1.vue

@ -1,297 +0,0 @@
<template>
<!-- 上传交付物 -->
<view class="pt-2 relative">
<template v-if="history.length === 0">
<u-input
:auto-height="autoHeight"
:border="border"
:height="height"
:type="type"
v-model="content"
placeholder="请输入链接/内容"
width="100"
/>
<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)">
<text class="examine-people text-right mr-2">{{ examinePerpol }}</text>
<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
@change="checkboxChange($event, item)"
v-model="item.checked"
v-for="(item, index) in list"
:key="index"
:name="item.name"
:data-id="item.id"
>
{{ item.name }}
</u-checkbox>
</u-checkbox-group>
</view>
</view>
</template>
<template v-else>
<template v-for="(item, index) in history">
<view class="to-examine py-1 flex flex-wrap overflow-hidden break-all" :key="index" v-if="item.content">
<a :href="item.content" class="text-blue-500 u-font-12 font-thin" target="_blank" v-if="CheckUrl(item.content)">
{{ item.content }}
</a>
<span v-else>{{ item.content }}</span>
</view>
<!-- <template v-if="showHistory"> -->
<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>
</template>
<!-- 选择检查人 -->
<!-- <ChooseChecker ref="checker" :checkerList="checkerList" @setCheckerList="setCheckerList"></ChooseChecker> -->
<view class="submit-delivery">
<u-button @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-icon @click="changeShowHistory" name="arrow-right" v-if="!showHistory"></u-icon>
<u-icon @click="changeShowHistory" name="arrow-down" v-else></u-icon> -->
</view>
<!-- <view class="mt-2 flex justify-between">
<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: 40,
autoHeight: true,
checkerList: [],
// showHistory: false, //
list: [],
examinePerpol: '请选择审核人',
isShowMembers: false, //
currStatus: -1, //
history: [],
};
},
computed: {
...mapState('role', ['members']),
...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: {
// 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);
}
},
// checkboxcheckbox-group
checkboxGroupChange(e) {
this.examinePerpol = e.toString();
},
//
showMembers() {
this.isShowMembers = !this.isShowMembers;
},
//
// 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.currStatus = 0;
this.isShowMembers = false;
// this.content = '';
// this.checkerList = [];
// this.$refs.checker.clearChecked();
} 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);
console.log('1111111', data);
if (data.length > 0) {
let flag = -1;
data.forEach(item => {
item.checkerList.forEach(v => {
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">
.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;
color: #999999;
}
::v-deep .u-checkbox__icon-wrap {
width: 20rpx !important;
height: 20rpx !important;
border-radius: 50%;
}
::v-deep .u-checkbox__label {
margin-left: 16rpx;
}
::v-deep .u-icon__icon.uicon-checkbox-mark {
transform: scale(0.5);
}
.submit-delivery {
position: absolute;
right: 0;
top: -25px;
}
</style>

94
src/plugins/p-upload-deliverable/p-upload-deliverable2.vue

@ -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>

3
src/utils/tall.js

@ -3,13 +3,13 @@ import cache from '@/utils/cache.js';
import cacheAndRequest from '@/utils/cacheAndRequest.js';
import plugin from '@/config/plugin.js';
import storage from '@/utils/storage.js';
import task from '@/config/task.js';
import time from '@/utils/time.js';
import timeConfig from '@/config/time';
import ui from '@/utils/ui.js';
import upload from '@/utils/upload.js';
import user from '@/config/user.js';
import zIndex from '@/config/zIndex.js';
import task from '@/config/task.js';
const gateway = process.env.VUE_APP_API_URL;
@ -22,6 +22,7 @@ const $t = {
timeConfig, // 时间相关配置
ui, // ui界面提示相关
chooseAndUpload: upload.chooseAndUpload, // 选择并上传单个文件相关的封装
chooseAndUploadImg: upload.chooseAndUploadImg, // 选择并上传单个图片相关的封装
domain: `${gateway}/defaultwbs`,
cache, // 本地存储相关
$q: cacheAndRequest,

69
src/utils/upload.js

@ -7,7 +7,7 @@ export default {
* @param {string} name
* @returns
*/
chooseAndUpload(url, formData = {}, extension = ['.xls', '.xlsx'], name = 'param') {
chooseAndUpload(url, formData = {}, extension, name = 'param') {
uni.hideLoading();
clearTimeout(timer);
let timer = null;
@ -63,4 +63,71 @@ export default {
});
});
},
/**
* 上传图片
* @param {string} url 服务器地址
* @param {object} formData 上传的其他字段
* @param {array} extension 上传文件类型 扩展名数组
* @param {array} sourceType 来源 ['album', 'camera']
* @param {string} name
* @returns
*/
chooseAndUploadImg(url, formData = {}, sourceType, extension, name = 'param') {
uni.hideLoading();
clearTimeout(timer);
let timer = null;
return new Promise((resolve, reject) => {
const token = uni.$t.storage.getStorageSync(uni.$t.app.tokenKey);
if (!token) {
return reject('用户未登录,请登录后重试');
}
uni.chooseImage({
count: 1, //默认100
extension,
sourceType: sourceType,
success: res => {
if (!timer) {
timer = setTimeout(() => {
uni.$t.ui.showLoading('正在上传...');
timer = null;
}, 800);
}
// 开始上传
uni.uploadFile({
url,
filePath: res.tempFilePaths[0],
name,
formData,
header: { Authorization: `Bearer ${token}` },
success: ({ data, statusCode }) => {
clearTimeout(timer);
uni.hideLoading();
if (statusCode === 200 && data) {
const { code, msg } = JSON.parse(data);
if (code !== 200) {
reject(msg);
} else {
resolve(JSON.parse(data).data);
}
} else {
reject('上传失败');
}
},
fail: error => {
clearTimeout(timer);
uni.hideLoading();
reject(error);
},
});
},
fail: error => {
clearTimeout(timer);
uni.hideLoading();
reject(error);
},
});
});
},
};

Loading…
Cancel
Save