Merge remote-tracking branch 'remotes/origin/master'

# Conflicts:
#	src/api/process/index.ts
This commit is contained in:
yangzhq68909 2025-05-27 14:53:55 +08:00
commit 401101ddd2
7 changed files with 611 additions and 70 deletions

View File

@ -76,10 +76,18 @@ export function taskEntrust(config : Object) { //委托
})
}
export function myApplyProcessListApi(config : object) { //
export function getProcessTaskTransInfo(config : Object) { //ID
return http({
url: '/act/task/myApplyProcessList',
url: '/act/task/getProcessTaskTransInfo',
method: 'GET',
data: config
})
}
export function processComplete(config : Object) { //
return http({
url: '/act/task/processComplete',
method: 'POST',
data: config
})
}

View File

@ -86,3 +86,11 @@ export function getDictItemsApi(dictCode : string) { // 字典标签专用
method: 'GET'
})
}
export function deleteFile(config : object){// by
return http({
url: `/sys/common/deleteFileAndCache`,
method: 'GET',
data: config
})
}

View File

@ -1,18 +1,29 @@
<template>
<view>
<wd-upload accept="all" multiple :file-list="fileList" :action="action" @change="handleChange"
:multiple="multiple"></wd-upload>
<wd-upload :accept="accept" multiple :file-list="fileList" :action="action" @change="handleChange" :disabled="disabled" @fail="fail"
:before-remove="beforeRemove" :multiple="multiple">
<template #preview-cover="{ file,index }">
<!-- 小程序拿不到文件 -->
<view class="preview-cover text-ellipsis" style="color: #0081ff;" @click="onLinePreview(file.name)">
{{ file?.name||`文件${index+1}` }}
</view>
</template>
</wd-upload>
<wd-toast></wd-toast>
<wd-message-box></wd-message-box>
</view>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { useToast, useMessage, useNotify, dayjs } from 'wot-design-uni'
import { deleteFile } from '@/api/system'
import { http } from '@/utils/http'
import {
getEnvBaseUrl
getEnvBaseUrl,
getFileAccessHttpUrl
} from '@/utils/index'
import { init } from 'echarts'
defineOptions({ // by
name: 'Mupload',
options: {
@ -24,23 +35,156 @@
type: String,
default: '',
},
multiple: { //
type: String,
default: false
multiple: { //
type: Boolean,
default: true
},
path: { //path
type: String,
default: ''
},
disabled: { //
type: Boolean,
default: false
},
accept: { //
type: String,
default: 'all'
}
})
const toast = useToast()
const message = useMessage()
const emit = defineEmits(['change', 'update:modelValue'])
const fileList = ref([])
const action = ref('')
const action = ref(getEnvBaseUrl() + '/sys/common/upload?appPath=APP文件/')
const defaultPath = ref(getEnvBaseUrl() + '/sys/common/upload?appPath=')
/**
* 监听value数值
*/
watch(
() => props.modelValue,
(val) => {
if (val) {
initFileList(val); //
}
},
{ immediate: true },
)
watch( //
() => props.path,
(val) => {
if (val) {
action.value = defaultPath.value + val;
}
},
{ immediate: true },
)
const handleChange = (val)=>{ //
const handleChange = (val) => { //
let pathArr = [];
if (val.fileList && val.fileList.length > 0) {
let fileListTemp = val.fileList.map((file) => {
console.log(file)
if (file.response) {
let reUrl = JSON.parse(file.response).message;
pathArr.push(reUrl)
file.url = getFileAccessHttpUrl(reUrl, '')
}
return file;
});
fileList.value = fileListTemp
}
if (pathArr.length > 0) {
emit('change', pathArr.join(","))
emit('update:modelValue', pathArr.join(","))
}
console.log(pathArr)
console.log(val)
console.log(fileList)
}
const uidGenerator = () => {
return '-' + parseInt(Math.random() * 10000 + 1 + '', 10);
}
const getFileName = (path) => {
if (path.lastIndexOf("\\") >= 0) {
let reg = new RegExp("\\\\", "g");
path = path.replace(reg, "/");
}
return path.substring(path.lastIndexOf("/") + 1);
}
const initFileList = (paths) => {
if (!paths || paths.length == 0) {
fileList.value = [];
return;
}
let fileListTemp = [];
let arr = paths.split(",")
for (var a = 0; a < arr.length; a++) {
let url = getFileAccessHttpUrl(arr[a], '');
fileListTemp.push({
uid: uidGenerator(),
name: getFileName(arr[a]),
status: 'success',
url: getFileAccessHttpUrl(arr[a], ''),
response: JSON.stringify({
status: "success",
message: arr[a]
})
})
}
fileList.value = fileListTemp
console.log(fileList)
}
const onLinePreview = (val) => { //线
console.log(val)
let prex = props.path ? props.path : 'APP文件'
let usePath = prex + '/' + val
uni.navigateTo({
url: `/pages/onlinePreview/detail?data=${usePath}`
});
}
const beforeRemove = ({ file, fileList, resolve }) => { //
console.log(file)
if (file) {
message
.confirm({
msg: '是否删除该文件?',
title: '确认删除吗',
})
.then(() => {
deleteFile({ name: file.name, url: file.url }).then(res => {
console.log(res)
if (res.success) {
toast.success(res.message)
resolve(true)
} else {
toast.error(res.message)
}
})
})
}
}
const fail = ({ error, file,formData })=>{ //
toast.error(error)
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.text-ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
width: 100%;
}
</style>

View File

@ -102,6 +102,7 @@
pageNo,
pageSize
}).then((res) => {
console.log(res)
if (res.success) {
list.value = [...list.value,...res.result.records];
}
@ -119,25 +120,27 @@
const handleChange = (data) => {
const rowkey = data.map((item) => item.username).join(',')
// var params = {
// taskId:userTask.value.id,
// taskAssignee:rowkey
// };//
// taskEntrust(params).then(res=>{
// if(res.success){
// toast.success(res.message)
// uni.redirectTo({
// url: './approvalTabbar'
// });
// }else{
// toast.error(res.message)
// }
// })
console.log(rowkey)
var params = {
taskId:userTask.value.id,
taskAssignee:rowkey
};//
taskEntrust(params).then(res=>{
if(res.success){
toast.success(res.message)
uni.redirectTo({
url: './approvalTabbar'
});
}else{
toast.error(res.message)
}
})
}
const goToPage = (item)=>{
//
if(item.taskAssigneeName&&item.taskAssigneeName!=''){
console.log(item)
//
uni.navigateTo({
url:`/pages-process/taskHandle`,

View File

@ -3,12 +3,12 @@
<view class="cu-bar bg-white solid-bottom height">
<view class="action">
当前环节
<text class="text-bold">[部门领导]</text>
<text class="text-bold">[{{resultObj.taskName}}]</text>
</view>
</view>
<view class="margin-top-sm">
<wd-collapse style="width: 100%;" v-model="value">
<wd-collapse style="width: 100%;" v-model="value1">
<wd-collapse-item name="item1">
<template #title="{expanded,disabled, isFirst }">
<view class="header">
@ -64,11 +64,123 @@
<span>上传附件</span>
</text>
</view>
<Mupload></Mupload>
</view>
</view>
<view class="grid col-4 grid-square padding bg-white ">
<Mupload v-model="fileListTemp" :path="usePath"></Mupload>
</view>
<view class="bg-white solid-top">
<radio-group :value="model.processModel" @change="radioChange">
<label class="uni-list-cell uni-list-cell-pd uni-label-pointer">
<!-- 点击的文字 -->
<radio value="1" style="transform: scale(0.7);" :checked="true"></radio>
<view class="margin-left-sm text-sm">单分支模式</view>
</label>
<label class="uni-list-cell uni-list-cell-pd uni-label-pointer" v-if="resultObj.histListSize>0 ">
<!-- 点击的文字 -->
<radio value="3" style="transform: scale(0.7);"></radio>
<view class="margin-left-sm text-sm">驳回</view>
</label>
<label class="uni-list-cell uni-list-cell-pd uni-label-pointer" v-if="model.processModel=='3'">
<wd-picker :columns="rejectColumns" label="单列选项" v-model="model.rejectModelNode"
use-default-slot>
<view>
<text class="text-lg margin-tb-sm">
<span>{{model.rejectModelNode?dictRejctModel(model.rejectModelNode):'选择驳回节点'}}</span>
</text>
</view>
</wd-picker>
</label>
</radio-group>
</view>
</view>
<view class="margin-top-sm">
<wd-collapse style="width: 100%;" v-model="value2">
<wd-collapse-item name="item1">
<template #title="{expanded,disabled, isFirst }">
<view class="header">
<wd-img class="taskImg" src="/static/user27.png" />
<text class="text-collapse">指定下一步操作人</text>
<wd-icon v-if="expanded" style="float: right;color: #d8d8d8;" name="arrow-down"
size="22px"></wd-icon>
<wd-icon v-else style="float: right;color: #d8d8d8;" name="arrow-up" size="22px"></wd-icon>
</view>
</template>
<view
style="position: relative; display: inline-block; min-width: 60px; margin: 2px 5px;text-align: center;">
<wd-img v-if="!model.nextUserName" @click="showSelectuser('show2')"
style="width: 32px; height: 32px; margin: 0px auto;margin-top: 10px;"
src="/static/add.png" />
<view v-if="!model.nextUserName" style="margin-bottom: 10px;">选择</view>
<view @click="reset('show2')">
<wd-img v-if="model.nextUserName"
style="width: 32px; height: 32px; margin: 0px auto;margin-top: 10px;"
:src="getFileAccessHttpUrl(modelShow.avatar2)" />
<view v-if="model.nextUserName" style="margin-bottom: 10px;">
{{modelShow.text2}}
</view>
</view>
<SelectUserModal v-if="modelShow.show2" :selected="model.nextUserName"
@change="(val)=>{show1Change(val,'show2')}" modalTitle="用户选择" :multi="false"
@close="() => (modelShow.show2 = false)"></SelectUserModal>
</view>
</wd-collapse-item>
</wd-collapse>
</view>
<view class="margin-top-sm">
<wd-collapse style="width: 100%;" v-model="value3">
<wd-collapse-item name="item1">
<template #title="{expanded,disabled, isFirst }">
<view class="header">
<wd-img class="taskImg" src="/static/user27.png" />
<text class="text-collapse">指定抄送人</text>
<wd-icon v-if="expanded" style="float: right;color: #d8d8d8;" name="arrow-down"
size="22px"></wd-icon>
<wd-icon v-else style="float: right;color: #d8d8d8;" name="arrow-up" size="22px"></wd-icon>
</view>
</template>
<view
style="position: relative; display: inline-block; min-width: 60px; margin: 2px 5px;text-align: center;">
<wd-img v-if="!model.ccUserIds" @click="showSelectuser('show3')"
style="width: 32px; height: 32px; margin: 0px auto;margin-top: 10px;"
src="/static/add.png" />
<view v-if="!model.ccUserIds" style="margin-bottom: 10px;">选择</view>
<view @click="reset('show3')">
<wd-img v-if="model.ccUserIds"
style="width: 32px; height: 32px; margin: 0px auto;margin-top: 10px;"
:src="getFileAccessHttpUrl(modelShow.avatar3)" />
<view v-if="model.ccUserIds" style="margin-bottom: 10px;">
{{modelShow.text3}}
</view>
</view>
<SelectUserModal v-if="modelShow.show3" :selected="model.ccUserIds"
@change="(val)=>{show1Change(val,'show3')}" modalTitle="用户选择" :multi="false"
@close="() => (modelShow.show3 = false)"></SelectUserModal>
</view>
</wd-collapse-item>
</wd-collapse>
</view>
<view class="padding text-center">
<view v-if="model.processModel==1">
<template v-for="(item,index) in resultObj.transitionList">
<wd-button class="cu-btn" style="margin-bottom: 3px;" @click="finishTask(item.nextnode)">
{{ item.Transition }}
</wd-button>
</template>
</view>
<view v-else>
<wd-button type="primary" @click="handleManyProcessComplete()">确认提交</wd-button>
</view>
</view>
<wd-toast></wd-toast>
<wd-message-box></wd-message-box>
</view>
</template>
@ -78,6 +190,8 @@
import { getFileAccessHttpUrl } from '@/common/uitls'
import { useQueue } from 'wot-design-uni'
import Mupload from '@/components/Mupload/Mupload.vue'
import { getProcessTaskTransInfo, processComplete, taskEntrust } from '@/api/process'
import { useToast, useMessage, useNotify, dayjs } from 'wot-design-uni'
defineOptions({
name: 'taskDeal',
@ -85,11 +199,25 @@
styleIsolation: 'shared',
},
})
const value = ref([])
const fileListTemp = ref('')
const toast = useToast()
const message = useMessage()
const resultObj = ref({}) //
const rejectColumns = ref([]) //
const value1 = ref([])
const value2 = ref([])
const value3 = ref([])
const modelShow = ref({
show1: false,
text1: '',
avatar1: ''
avatar1: '',
show2: false,
text2: '',
avatar2: '',
show3: false,
text3: '',
avatar3: '',
})
const model = ref({
taskId: '', //taskid
@ -126,8 +254,48 @@
})
const usePath = ref('流程办理附件')
watch( //
() => props.formData,
(val) => {//formdata
if (val) {
console.log(val)
model.value.taskId = val.taskId;
rejectColumns.value = []; //
model.value.rejectModelNode = '';
let tempArr = [];
getProcessTaskTransInfo({ taskId: model.value.taskId }).then(res => {
console.log(res)
if (res.success) {
resultObj.value = res.result;
res.result.histListNode.forEach(item => {
if (item.NAME_ != res.result.taskName) {//
tempArr.push({ label: item.NAME_, value: item.TASK_DEF_KEY_ })
}
})
rejectColumns.value = tempArr; //
}
})
}
},
{ immediate: true, deep: true },
)
const radioChange = (val) => {
model.value.processModel = val.detail.value
if (val.detail.value != 3) {
//
model.value.rejectModelNode = '';
}
}
const showSelectuser = (val : string) => { //
modelShow.value[val] = true;
console.log(props.formData)
}
const show1Change = (val, type) => {
@ -138,6 +306,18 @@
modelShow.value['text1'] = selectUser.realname
modelShow.value['avatar1'] = selectUser.avatar
break;
case 'show2':
model.value.nextUserId = selectUser.username
model.value.nextUserName = selectUser.realname
modelShow.value['text2'] = selectUser.realname
modelShow.value['avatar2'] = selectUser.avatar
break;
case 'show3':
model.value.ccUserIds = selectUser.username
model.value.ccUserRealNames = selectUser.realname
modelShow.value['text3'] = selectUser.realname
modelShow.value['avatar3'] = selectUser.avatar
break;
default:
break;
}
@ -150,10 +330,112 @@
modelShow.value['text1'] = ''
modelShow.value['avatar1'] = ''
break;
case 'show2':
model.value.nextUserName = ''
model.value.nextUserId = ''
modelShow.value['text2'] = ''
modelShow.value['avatar2'] = ''
break;
case 'show3':
model.value.ccUserIds = ''
model.value.ccUserRealNames = '';
modelShow.value['text3'] = ''
modelShow.value['avatar3'] = ''
break;
default:
break;
}
}
const dictRejctModel = (val) => {//
return rejectColumns.value.filter(item => {
return item.value = val
})[0].label;
}
const finishTask = (nextNode) => {//
console.log(nextNode)
if (nextNode) {
handleProcessComplete(nextNode)
return;
}
if (resultObj.value.transitionList.length == 1) {
handleProcessComplete(resultObj.value.transitionList[0].nextnode)
} else {
toast.error("存在多分支,请手动选择分支!")
}
}
const handleProcessComplete = (nextNode) => {
if (!model.value.reason || model.value.reason.length == 0) {
toast.error("请填写处理意见!")
return
}
if (nextNode) { // true
model.value.nextnode = nextNode;
}
if (model.value.entrust) { //
var params = {
taskId: model.value.taskId,
taskAssignee: model.value.entrust
};//
taskEntrust(params).then(res => {
if (res.success) {
toast.success(res.message)
setTimeout(() => { //0.5s
uni.navigateBack()
}, 1000)
} else {
toast.error(res.message)
}
})
return;
}
message
.confirm({
msg: '确认提交审批吗?',
title: '提示',
})
.then(() => {
console.log(model.value)
model.fileList = JSON.stringify(fileListTemp.value)
processComplete(model.value).then(res => {
if (res.success) {//
toast.success("委托成功!")
setTimeout(() => { //0.5s
uni.navigateBack()
}, 1000)
} else {
toast.error(res.message)
}
})
})
}
const handleManyProcessComplete = () => { //
if (model.value.processModel == 3) {
if (!model.value.rejectModelNode || model.value.rejectModelNode.length == 0) {
toast.error("请选择驳回节点!")
return
}
// else{
// //item.TASK_DEF_KEY_
// //item.TASK_DEF_KEY_
// this.handleProcessComplete();
// }
}
handleProcessComplete('');
}
onMounted(() => {
let yy = new Date().getFullYear();
let mm = new Date().getMonth() + 1;
usePath.value = yy + '-' + mm + '-' + '流程办理附件';
console.log(usePath)
})
</script>
<style lang="scss" scoped>
@ -218,16 +500,21 @@
margin-right: 10px;
vertical-align: -15%
}
.solid-bottom::after {
border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.text-blue, .line-blue, .lines-blue {
.text-blue,
.line-blue,
.lines-blue {
color: #0081ff;
}
.margin-left-sm {
margin-left: 10px;
}
.cu-tag {
font-size: 12px;
vertical-align: middle;
@ -245,6 +532,7 @@
.cu-tag[class*="line-"]::after {
border-radius: 0;
}
.cu-tag[class*="line-"]::after {
content: " ";
width: 200%;
@ -262,4 +550,76 @@
z-index: 1;
pointer-events: none;
}
.grid.grid-square {
overflow: hidden;
}
.bg-white {
background-color: #fff;
color: #666;
}
.padding {
padding: 17px;
display: block;
}
.grid {
display: flex;
flex-wrap: wrap;
}
.text-sm {
font-size: 13px;
}
.uni-list-cell {
position: relative;
display: flex;
-webkit-box-pack: justify;
-webkit-justify-content: flex-start;
justify-content: flex-start;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
border-bottom: 1px solid #f0f0f0;
}
.uni-list-cell-pd {
padding: 8px 15px;
}
.uni-label-pointer {
cursor: pointer;
}
.cu-btn {
position: relative;
border: 0px;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 15px;
font-size: 14px;
height: 32px;
line-height: 1;
text-align: center;
text-decoration: none;
overflow: visible;
margin-left: 0;
-webkit-transform: translate(0px, 0px);
transform: translate(0px, 0px);
margin-right: 0;
}
.text-lg {
font-size: 16px;
}
.margin-tb-sm {
margin-top: 10px;
margin-bottom: 10px;
}
</style>

View File

@ -111,7 +111,7 @@
procInsId:useData.processInstanceId,
tableName:res.result.tableName,
permissionList:res.result.permissionList,
vars:res.result.records
vars:res.result.records,
}
formData.value = data;//

View File

@ -425,3 +425,21 @@ function weatherRequest(params : { lat ?: number; lon ?: number; q ?: string })
export const imgUrl = (url : string) => {
return getEnvBaseUrl() + '/sys/common/static/' + `/${url}`
}
/**
* 获取文件服务访问路径
* @param avatar
* @param subStr
* @returns {*}
*/
export function getFileAccessHttpUrl(avatar,subStr) {
if(!subStr) subStr = 'http'
if(avatar && avatar.startsWith(subStr)){
return avatar;
}else{
if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){
return getEnvBaseUrl()+ "/sys/common/static/" + avatar;
}
}
}