feat: base 增加wf ticketd组件可在业务组件里加载
This commit is contained in:
parent
94516f4b47
commit
8dab72dbcd
|
@ -22,6 +22,11 @@
|
|||
--el-color-primary-dark-9: #060f19;
|
||||
--el-border-radius-base: 2px;
|
||||
}
|
||||
|
||||
.el-collapse-item__content {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
.el-tag {
|
||||
--el-tag-border-radius: 2px;
|
||||
}
|
||||
|
|
|
@ -224,6 +224,20 @@ export const actStateEnum = new EnumFactory({
|
|||
5: { text: '已关闭', type: 'info' },
|
||||
})
|
||||
|
||||
export const interveneTypeEnum = new EnumFactory({
|
||||
0: { text: '正常', type: 'primary' },
|
||||
1: { text: '转交', type: 'primary' },
|
||||
2: { text: '加签', type: 'info' },
|
||||
3: { text: '加签处理完成', type: 'primary' },
|
||||
4: { text: '接单', type: 'success' },
|
||||
5: { text: '评论', type: 'info' },
|
||||
6: { text: '删除', type: 'danger' },
|
||||
7: { text: '强制关闭', type: 'danger' },
|
||||
8: { text: '强制修改状态', type: 'danger' },
|
||||
10: { text: '撤回', type: 'danger' },
|
||||
11: { text: '抄送', type: 'info' },
|
||||
})
|
||||
|
||||
export const mCateEnum = new EnumFactory({
|
||||
'list': ['主要辅材','办公辅料','设备维护辅料','包装辅材','标识辅材','防护辅材','其他辅材','常规辅材','医护辅材','检测辅材','倒角辅材','减薄辅材','磨抛辅材','多线切辅材','精雕辅材','扫边辅材','黑化辅材']
|
||||
})
|
|
@ -72,43 +72,28 @@
|
|||
<el-table-column
|
||||
label="工单标题"
|
||||
prop="title"
|
||||
width="180"
|
||||
min-width="180"
|
||||
:show-overflow-tooltip="true"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column label="工作流" prop="title">
|
||||
<el-table-column label="工作流" prop="title" width="160">
|
||||
<template #default="scope">
|
||||
{{ scope.row.workflow_.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所在节点">
|
||||
<el-table-column label="所在节点" width="160">
|
||||
<template #default="scope">
|
||||
{{ scope.row.state_.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="进行状态" prop="sort">
|
||||
<el-table-column label="进行状态" prop="sort" width="120">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="
|
||||
scope.row.act_state === 0
|
||||
? ''
|
||||
: scope.row.act_state === 1
|
||||
? ''
|
||||
: scope.row.act_state === 2
|
||||
? 'danger'
|
||||
: scope.row.act_state === 3
|
||||
? 'danger'
|
||||
: scope.row.act_state === 5
|
||||
? 'danger'
|
||||
: scope.row.act_state === 4
|
||||
? 'success'
|
||||
: ''
|
||||
"
|
||||
>{{ act_states[scope.row.act_state] }}</el-tag
|
||||
>
|
||||
<el-tag :type="actStateEnum[scope.row.act_state]?.type">
|
||||
{{ actStateEnum[scope.row.act_state]?.text }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="可处理人" :show-overflow-tooltip="true">
|
||||
<el-table-column label="可处理人" :show-overflow-tooltip="true" min-width="160">
|
||||
<template #default="scope">
|
||||
<span
|
||||
v-if="
|
||||
|
@ -134,7 +119,6 @@
|
|||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="reStart(scope.row)"
|
||||
v-if="scope.row.script_run_last_result == false"
|
||||
|
@ -144,18 +128,24 @@
|
|||
</el-table-column>
|
||||
</scTable>
|
||||
</el-main>
|
||||
<el-drawer title="工单详情" v-model="drawer" size="80%" destroy-on-close>
|
||||
<component :is="currentComponent" :ticketId="ticketId"></component>
|
||||
<el-drawer v-model="drawer" size="90%" :show-close="false">
|
||||
<template #header="{ close, titleId, titleClass }">
|
||||
<h4 :id="titleId" :class="titleClass">工单详情</h4>
|
||||
<el-button type="danger" @click="close">关闭</el-button>
|
||||
</template>
|
||||
<component :is="currentComponent" :ticketId="ticketId" :modelId="modelId"></component>
|
||||
</el-drawer>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'; // 异步组件加载
|
||||
import { defineAsyncComponent, markRaw } from 'vue'; // 异步组件加载
|
||||
import { actStateEnum, interveneTypeEnum } from "@/utils/enum.js";
|
||||
export default {
|
||||
name: "myticket",
|
||||
data() {
|
||||
return {
|
||||
actStateEnum, interveneTypeEnum,
|
||||
drawer: false,
|
||||
tvalue: "待办",
|
||||
toptions: {
|
||||
|
@ -189,6 +179,7 @@ export default {
|
|||
wfOptions: [],
|
||||
currentComponent: null,
|
||||
ticketId: null,
|
||||
modelId: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -213,7 +204,7 @@ export default {
|
|||
reStart(row) {
|
||||
this.$API.wf.ticket.retryScript.req(row.id).then((res) => {
|
||||
this.$message.success("任务执行下发成功");
|
||||
// this.$refs.table.refresh();
|
||||
row.script_run_last_result = true;
|
||||
});
|
||||
},
|
||||
handleQuery() {
|
||||
|
@ -229,11 +220,12 @@ export default {
|
|||
handleShow(row) {
|
||||
this.drawer = true;
|
||||
this.ticketId = row.id;
|
||||
this.modelId = row.ticket_data.t_id;
|
||||
const viewPath = row.workflow_.view_path;
|
||||
// 动态 import
|
||||
this.currentComponent = defineAsyncComponent(() =>
|
||||
import(`@/views${viewPath}.vue`)
|
||||
)
|
||||
this.currentComponent = markRaw(
|
||||
defineAsyncComponent(() => import(`@/views${viewPath}.vue`))
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,177 @@
|
|||
<template>
|
||||
<el-container>
|
||||
xxx
|
||||
</el-container>
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item title="基本信息" name="1">
|
||||
<el-descriptions :column="1">
|
||||
<el-descriptions-item>
|
||||
<span style="color:darkblue;margin-right: 4px;">({{ ticketDetail.sn }})</span>{{ ticketDetail.title
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="当前:">
|
||||
<el-tag type="info" effect="plain">{{ ticketDetail.state_.name }}</el-tag>
|
||||
<el-tag :type="actStateEnum[ticketDetail.act_state]?.type" effect="plain">
|
||||
{{ actStateEnum[ticketDetail.act_state]?.text }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="操作" name="2" v-if="actionShow">
|
||||
<el-input type="textarea" :rows="2" v-model="handleForm.suggestion" placeholder="处理意见" />
|
||||
<el-row>
|
||||
<el-col :xs="24" :md="12" style="padding: 1px">
|
||||
<el-button :loading="submitLoading" :disabled="submitLoading" v-for="item in transitions"
|
||||
:key="item.id" size="small" :type="item.attribute_type === 2 ? 'danger' : 'primary'
|
||||
" @click="handleTransition(item.id)">
|
||||
{{ item.name }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12" style="text-align: right;padding: 1px">
|
||||
<el-button v-if="ticketDetail.state_.enable_retreat && isOwn" type="danger" size="small"
|
||||
@click="handleRetreat">撤回</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="审批历史" name="3">
|
||||
<div style="padding:1px"><el-timeline>
|
||||
<el-timeline-item v-for="item in ticketLog" :key="item.id" :timestamp="item.create_time"
|
||||
:color="getColor(item)">
|
||||
<div>
|
||||
<strong>{{ item.state_?.name || "未知状态" }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span v-if="item.intervene_type != 0"><el-tag
|
||||
:type="interveneTypeEnum[item.intervene_type]?.type" effect="plain">
|
||||
{{ interveneTypeEnum[item.intervene_type]?.text }}
|
||||
</el-tag></span>
|
||||
<span v-if="item.transition_"
|
||||
:style="{ color: item.transition_.attribute_type === 1 ? '#67C23A' : '#F56C6C' }">
|
||||
{{ item.transition_.name }}
|
||||
</span>
|
||||
<span v-if="item.participant_">-{{ item.participant_.name }}</span>
|
||||
</div>
|
||||
<div v-if="item.suggestion">
|
||||
<el-tooltip v-if="item.suggestion.length > 20" class="box-item" effect="dark"
|
||||
:content="item.suggestion" placement="top">
|
||||
<span>{{ item.suggestion.slice(0, 20) + "..." }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>
|
||||
{{ item.suggestion }}
|
||||
</span>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline></div>
|
||||
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, defineProps, onMounted } from "vue";
|
||||
import { actStateEnum, interveneTypeEnum } from "@/utils/enum.js";
|
||||
import API from '@/api';
|
||||
import TOOL from "@/utils/tool.js";
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
const props = defineProps({
|
||||
ticketId: { type: String, required: true, default: null },
|
||||
ticket_data: { type: Object, default: null },
|
||||
});
|
||||
const currentUser = ref(TOOL.data.get("USER_INFO").id)
|
||||
const actionShow = ref(false);
|
||||
const isOwn = ref(false);
|
||||
const activeNames = ref(['1', '3']);
|
||||
const ticketDetail = ref({
|
||||
state_: {}
|
||||
});
|
||||
const ticketLog = ref([]);
|
||||
const handleForm = ref({
|
||||
suggestion: ""
|
||||
})
|
||||
onMounted(() => {
|
||||
console.log('props.ticketId', props.ticketId)
|
||||
if (props.ticketId) {
|
||||
getTicketDetail();
|
||||
getTicketLog();
|
||||
}
|
||||
});
|
||||
const refreshTicket = async () => {
|
||||
actionShow.value = false
|
||||
isOwn.value = false
|
||||
transitions.value = []
|
||||
handleForm.value.suggestion = ''
|
||||
ticketLog.value = []
|
||||
activeNames.value = ['1', '3'] // 根据需要恢复初始展开项
|
||||
getTicketDetail()
|
||||
getTicketLog()
|
||||
}
|
||||
|
||||
const getTicketDetail = () => {
|
||||
API.wf.ticket.ticketItem.req(props.ticketId).then(res => {
|
||||
ticketDetail.value = res;
|
||||
if (res.create_by === currentUser.value) {
|
||||
isOwn.value = true;
|
||||
actionShow.value = true;
|
||||
if (!activeNames.value.includes('2')) activeNames.value.push('2')
|
||||
}
|
||||
if (res.participant_type == 1 && res.participant === currentUser.value) {
|
||||
actionShow.value = true;
|
||||
if (!activeNames.value.includes('2')) activeNames.value.push('2')
|
||||
getTransitions();
|
||||
}
|
||||
if (res.participant_type == 2 && res.participant.includes(currentUser.value)) {
|
||||
actionShow.value = true;
|
||||
if (!activeNames.value.includes('2')) activeNames.value.push('2')
|
||||
getTransitions();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getTransitions = () => {
|
||||
API.wf.ticket.ticketTransitions.req(props.ticketId).then(res => {
|
||||
transitions.value = res;
|
||||
});
|
||||
}
|
||||
|
||||
const getTicketLog = () => {
|
||||
API.wf.ticket.ticketFlowlogs.req(props.ticketId).then(res => {
|
||||
ticketLog.value = res;
|
||||
})
|
||||
}
|
||||
|
||||
function getColor(item) {
|
||||
if (item.transition_?.attribute_type === 1) return "#67C23A"; // 同意 绿色
|
||||
if (item.transition_?.attribute_type === 2) return "#F56C6C"; // 拒绝 红色
|
||||
return "#909399"; // 默认灰色
|
||||
}
|
||||
|
||||
const handleRetreat = () => {
|
||||
ElMessageBox.confirm("确认撤回吗?", "温馨提示", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}).then(() => {
|
||||
API.wf.ticket.ticketRetreat
|
||||
.req(props.ticketId, handleForm.value)
|
||||
.then((res) => {
|
||||
refreshTicket();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const submitLoading = ref(false);
|
||||
const transitions = ref([]);
|
||||
const handleTransition = (transitionId) => {
|
||||
let params = new Object();
|
||||
params.transition = transitionId;
|
||||
if (props.ticket_data) {
|
||||
params.ticket_data = props.ticket_data;
|
||||
}else{
|
||||
params.ticket_data = {};
|
||||
}
|
||||
params.suggestion = handleForm.value.suggestion;
|
||||
submitLoading.value = true;
|
||||
API.wf.ticket.ticketHandle.req(props.ticketId, params).then((res) => {
|
||||
submitLoading.value = false;
|
||||
refreshTicket();
|
||||
}).catch((e) => {
|
||||
submitLoading.value = false;
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<el-button
|
||||
v-for="item in transitions"
|
||||
:key="item.id"
|
||||
type="primary"
|
||||
:loading="isSaveing"
|
||||
:disabled="isSaveing"
|
||||
@click="submit(item.id)"
|
||||
style="margin-right: 2px"
|
||||
>{{ item.name }}</el-button>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, defineEmits } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import API from '@/api';
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
workflow_key: {type: String, default: null, required: false},
|
||||
ticketId: {type: String, default: null, required: false},
|
||||
t_id: {type: String, default: null, required: true},
|
||||
title: {type: String, default: null, required: false},
|
||||
submit_b_func: {type: Function, default: null, required: false},
|
||||
ticket_data: {type: Object, default: null, required: false},
|
||||
})
|
||||
|
||||
const workflow = ref(null);
|
||||
const transitions = ref([]);
|
||||
onMounted(async () => {
|
||||
if (props.ticketId) {
|
||||
API.wf.ticket.ticketTransitions.req(props.ticketId).then(res => {
|
||||
transitions.value = res;
|
||||
});
|
||||
}else if (props.workflow_key) {
|
||||
let res = await API.wf.workflow.initkey.req(props.workflow_key);
|
||||
transitions.value = res.transitions;
|
||||
workflow.value = res.workflow
|
||||
}else{
|
||||
ElMessage.error("缺少workflow_key或ticketId");
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const isSaveing = ref(false);
|
||||
|
||||
const emit = defineEmits(["success"]);
|
||||
const submit = async (transition_id) => {
|
||||
isSaveing.value = true;
|
||||
if (props.submit_b_func) {
|
||||
await props.submit_b_func();
|
||||
}
|
||||
if (props.ticketId != null) {
|
||||
let params = new Object();
|
||||
params.transition = transition_id;
|
||||
if (props.ticket_data) {
|
||||
params.ticket_data = props.ticket_data;
|
||||
}else{
|
||||
params.ticket_data = {};
|
||||
}
|
||||
try{
|
||||
let res = await API.wf.ticket.ticketHandle.req(props.ticketId, params);
|
||||
isSaveing.value = false;
|
||||
ElMessage.success("提交成功");
|
||||
emit("success", props.ticketId)
|
||||
} catch (e) {
|
||||
isSaveing.value = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let ticket = {};
|
||||
ticket.title = props.title;
|
||||
ticket.workflow = workflow.value;
|
||||
if (props.t_id != null && props.t_id != undefined) {
|
||||
ticket.ticket_data = {
|
||||
t_id: props.t_id,
|
||||
};
|
||||
} else {
|
||||
ElMessage.error("缺少t_id");
|
||||
isSaveing.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ticket.transition = transition_id;
|
||||
try {
|
||||
let res = await API.wf.ticket.create.req(ticket);
|
||||
isSaveing.value = false;
|
||||
ElMessage.success("提交成功");
|
||||
emit("success", res.id)
|
||||
} catch (e) {
|
||||
isSaveing.value = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
|
||||
</el-main>
|
||||
<el-aside width="30%">
|
||||
<ticketd :ticketId="props.ticketId"></ticketd>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, defineProps, onMounted} from "vue";
|
||||
import ticketd from './ticketd.vue'
|
||||
import API from '@/api'
|
||||
const props = defineProps({
|
||||
ticketId: { type: String, required: false, default: null }
|
||||
});
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
</script>
|
Loading…
Reference in New Issue