369 lines
8.5 KiB
Vue
369 lines
8.5 KiB
Vue
<template>
|
|
<view class="w-process">
|
|
<view
|
|
:class="{'w-process-node': true, 'w-cmt-node': (node.comment && node.comment.length > 0) || node.signature}"
|
|
v-for="(node, index) in ($props.progress || [])" :key="index">
|
|
<view class="w-process-item-line"></view>
|
|
<view class="w-process-item">
|
|
<view class="w-process-item-avatar">
|
|
<Avatar :size="42" :status="getStatus(node)" :name="node.user.name" :src="getRes(node.user.avatar)"
|
|
:showName="false"></Avatar>
|
|
</view>
|
|
|
|
<view class="w-p-text-info">
|
|
<view>{{node.name}} <text
|
|
v-show="(node.comment && node.comment.length > 0) || node.signature">(添加了评论)</text></view>
|
|
<view>{{node.user.name}}</view>
|
|
</view>
|
|
<text class="w-p-time">
|
|
{{ node.isFuture ? '等待中' : getFinishTime(node.finishTime) }}
|
|
</text>
|
|
</view>
|
|
<view class="w-process-node-content">
|
|
<view class="w-comments" v-show="(node.comment && node.comment.length > 0) || node.signature">
|
|
<view v-if="(node.signature || '') !== ''"
|
|
style="display: flex; align-items: flex-start; margin-bottom: 10rpx;">
|
|
<text>签字:</text>
|
|
<image mode="aspectFit" :src="node.signature" style="width: 150rpx; height: 100rpx;"></image>
|
|
</view>
|
|
<view v-for="cmt in node.comment" :key="cmt.id" class="w-comment">
|
|
<view>{{cmt.text}}</view>
|
|
<template v-if="cmt.attachments.length > 0">
|
|
<view>
|
|
<image mode="aspectFit" :src="img" v-for="(img, i) in filterImages(cmt.attachments)"
|
|
:key="img" @click="previewImg(img, cmt.attachments)"></image>
|
|
</view>
|
|
<view>
|
|
<view class="ellipsis" v-for="(file, i) in filterFiles(cmt.attachments)" :key="file.id">
|
|
<view style="color: #4C87F3;" @click="downloadFile(file.url)">{{file.name}}</view>
|
|
</view>
|
|
<!-- <text v-for="(file, i) in filterFiles(cmt.attachments)" :key="file.id">
|
|
<text v-if="typeIsImg(file.name)" style="color: #4C87F3;"
|
|
@click="previewImgOne(file)">{{file.name}}</text>
|
|
<uni-link v-else :showUnderLine="false" color="#4C87F3" :download="file.name"
|
|
:href="file.url" :text="file.name"></uni-link>
|
|
</text> -->
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="w-process-end w-process-item">
|
|
<!-- :style="{width: 50 / 16 + 'rem', height: 50 / 16 * 0.8 + 'rem'}" -->
|
|
<view :style="{width: 100 + 'rpx', height: 80 + 'rpx'}">
|
|
<uni-icons2 type="more-filled" color="#8b8b8b" class="w-pr-running uni-icons_30"
|
|
v-if="$props.result === 'RUNNING'"></uni-icons2>
|
|
<uni-icons2 type="checkbox-filled" color="#5FB685" class="w-pr-status uni-icons_30"
|
|
v-else-if="$props.result === 'PASS'"></uni-icons2>
|
|
<uni-icons2 type="clear" color="#CE5266" class="w-pr-status uni-icons_30"
|
|
v-else-if="$props.result === 'REFUSE'"></uni-icons2>
|
|
<uni-icons2 type="close" color="#8b8b8b" class="w-pr-status uni-icons_30"
|
|
v-else-if="$props.result === 'CANCEL'"></uni-icons2>
|
|
</view>
|
|
<view>{{$props.status}}</view>
|
|
</view>
|
|
<view class="fixed" :class="{show:showIframe}" v-if="show" @click="show=false">
|
|
<view class="iframeMain" @click.stop="show=true">
|
|
<video v-if="getType(iframeUrl) == 'video'" class="iframe" :src="iframeUrl"></video>
|
|
<image v-else-if="getType(iframeUrl) == 'image'" class="iframe" :src="iframeUrl" mode="aspectFill">
|
|
</image>
|
|
<iframe v-else class="iframe" ref="iframe" :src="iframeUrl" frameborder="0"></iframe>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
<script>
|
|
import {
|
|
getFileSize,
|
|
isVideoLink,
|
|
isImageLink
|
|
} from '@/utils/tool.js'
|
|
import Avatar from './Avatar.vue'
|
|
export default {
|
|
props: {
|
|
progress: Array,
|
|
status: String,
|
|
result: String,
|
|
},
|
|
components: {
|
|
Avatar
|
|
},
|
|
data() {
|
|
return {
|
|
imgViews: [],
|
|
showIframe: false,
|
|
show: false,
|
|
iframeUrl: "",
|
|
}
|
|
},
|
|
computed: {
|
|
//获取文件访问路径
|
|
getRes() {
|
|
return (url) => {
|
|
if (url) {
|
|
const reg = /^(http:|https:).*/gi
|
|
return reg.test(url) ? url : this.url_config + 'image/' + url
|
|
} else {
|
|
return url
|
|
}
|
|
}
|
|
},
|
|
},
|
|
onLoad() {
|
|
|
|
},
|
|
mounted() {
|
|
|
|
},
|
|
onShow() {
|
|
|
|
},
|
|
methods: {
|
|
getFinishTime(time) {
|
|
if (time) {
|
|
return time.substring(5, 16)
|
|
}
|
|
return '处理中'
|
|
},
|
|
filterImages(attachments) {
|
|
return (attachments || []).filter(f => f.isImage).map(f => {
|
|
console.log(f.url);
|
|
return this.getRes(f.url)
|
|
})
|
|
},
|
|
filterFiles(attachments) {
|
|
return (attachments || []).filter(f => !f.isImage).map(f => {
|
|
return {
|
|
...f,
|
|
url: this.getRes(f.url)
|
|
}
|
|
})
|
|
},
|
|
previewImg(img, attachments) {
|
|
console.log(img, attachments);
|
|
const imgs = this.filterImages(attachments)
|
|
console.log(imgs);
|
|
uni.previewImage({
|
|
current: imgs.indexOf(img),
|
|
urls: imgs,
|
|
longPressActions: true
|
|
})
|
|
},
|
|
getType(url) {
|
|
if (isImageLink(url)) {
|
|
return "image"
|
|
} else if (isVideoLink(url)) {
|
|
return "video"
|
|
} else {
|
|
return ''
|
|
}
|
|
},
|
|
downloadFile(url) {
|
|
// 下载所有的文件
|
|
let name = url.substring(url.lastIndexOf('/') + 1);
|
|
console.log(name, "文件名称");
|
|
if (isVideoLink(url) || isImageLink(url)) {
|
|
// 是图片和视频
|
|
this.show = true;
|
|
this.showIframe = true;
|
|
this.iframeUrl = url;
|
|
} else {
|
|
this.show = true;
|
|
this.showIframe = false;
|
|
this.iframeUrl = url;
|
|
}
|
|
return;
|
|
},
|
|
previewImgOne(img) {
|
|
console.log(img);
|
|
this.downloadFile(img.url, Date.now() + ".jpg")
|
|
// uni.previewImage({
|
|
// current: 0,
|
|
// urls: [img.url],
|
|
// longPressActions: true
|
|
// })
|
|
},
|
|
typeIsImg(filename) {
|
|
// 获取文件名称是否为图片
|
|
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp)$/i;
|
|
return imageExtensions.test(filename);
|
|
},
|
|
getStatus(item) {
|
|
if (item.isFuture) {
|
|
return 'waiting'
|
|
} else if (item.finishTime === null) {
|
|
return 'pending'
|
|
} else if (item.nodeType === 'CC') {
|
|
return 'cc'
|
|
} else if (item.result === 'agree') {
|
|
return 'success'
|
|
} else if (item.result === 'refuse') {
|
|
return 'error'
|
|
} else if (item.result === 'comment') {
|
|
return 'comment'
|
|
} else if (item.result === 'transfer') {
|
|
return 'transfer'
|
|
} else if (item.result === 'recall') {
|
|
return 'recall'
|
|
} else if (item.nodeType === 'cancel') {
|
|
return 'cancel'
|
|
} else {
|
|
return undefined
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.fixed {
|
|
position: fixed;
|
|
z-index: 9999;
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, .3);
|
|
display: none;
|
|
|
|
&.show {
|
|
display: initial;
|
|
}
|
|
}
|
|
|
|
.iframeMain {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
width: 650rpx;
|
|
font-size: 0;
|
|
|
|
.iframe {
|
|
width: 100%;
|
|
height: 500rpx;
|
|
}
|
|
}
|
|
|
|
|
|
.w-process {
|
|
font-size: 32rpx;
|
|
|
|
.w-process-node {
|
|
position: relative;
|
|
padding-bottom: 64rpx;
|
|
|
|
//连接线
|
|
.w-process-item-line {
|
|
background-color: #E4E4E4;
|
|
position: absolute;
|
|
width: 6rpx;
|
|
height: 100%;
|
|
left: 40rpx;
|
|
}
|
|
|
|
//节点体
|
|
.w-process-node-content {
|
|
margin-left: 96rpx;
|
|
}
|
|
}
|
|
|
|
.w-process-item {
|
|
display: flex;
|
|
position: relative;
|
|
|
|
.w-process-item-avatar {
|
|
padding: 10rpx 0;
|
|
background-color: white;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.w-p-text-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
margin-left: 16rpx;
|
|
|
|
&>view:first-child {
|
|
font-size: 29rpx;
|
|
color: #8C8C8C;
|
|
}
|
|
|
|
&>view {
|
|
padding: 3rpx;
|
|
}
|
|
}
|
|
|
|
.w-p-time {
|
|
position: absolute;
|
|
color: #8C8C8C;
|
|
font-size: 30rpx;
|
|
top: 10rpx;
|
|
right: 0;
|
|
}
|
|
}
|
|
|
|
.w-process-end {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 3rpx;
|
|
|
|
&>view:first-child {
|
|
display: flex;
|
|
background-color: white;
|
|
}
|
|
|
|
.w-pr-running {
|
|
width: 80%;
|
|
height: 100%;
|
|
background-color: #E4E4E4;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.w-pr-status {
|
|
width: 80%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.w-comments {
|
|
margin-top: 10rpx;
|
|
padding: 16rpx;
|
|
background-color: #F4F5F7;
|
|
border-radius: 0 8px 8px 16rpx;
|
|
|
|
.w-comment {
|
|
image {
|
|
margin: 4rpx;
|
|
width: 112rpx;
|
|
height: 112rpx;
|
|
}
|
|
|
|
&>view:first-child {
|
|
font-size: 29rpx;
|
|
color: #515151;
|
|
margin-bottom: 6rpx;
|
|
}
|
|
|
|
.ellipsis {
|
|
overflow: hidden;
|
|
|
|
>view {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
.w-cmt-node {
|
|
padding-bottom: 16rpx !important;
|
|
}
|
|
</style> |