This commit is contained in:
那些花儿
2025-07-29 14:25:33 +08:00
parent 72546696fa
commit 9d8002ec93
40 changed files with 1410 additions and 13555 deletions
@@ -665,7 +665,6 @@ td.no-b {
.flow-task-form .el-descriptions-item__label.is-bordered-label {
color: rgb(102, 102, 102) !important;
font-weight: bold !important;
background: rgb(248, 249, 250) !important;
padding: 8px 12px !important;
border: 1px solid rgb(221, 221, 221) !important;
@@ -1,6 +1,7 @@
const initTableMixins = {
data() {
return {
pageDataUrl: "",
submitLoading: false,
searchMore: false,
tableSize: "",
@@ -32,7 +33,7 @@ const initTableMixins = {
}
},
methods: {
dropdownCommand({action, value}) {
dropdownCommand({ action, value }) {
if (action) action(value)
},
columnChange(val) {
@@ -64,8 +65,8 @@ const initTableMixins = {
this.pageForm.pageSize = val
this.pageData()
},
pageData(url = null, data = null) {
const address = url ? url : loc() + "/pageData"
pageData(data = null) {
const address = this.pageDataUrl ? this.pageDataUrl : loc() + "/pageData"
this.tableLoading = true
this.$axios.post(address, data ? data : this.pageForm).then((res) => {
this.tableLoading = false
@@ -1,6 +1,7 @@
const initTableMixins = {
data() {
return {
pageDataUrl: "",
submitLoading: false,
searchMore: false,
tableSize: "",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -6,13 +6,13 @@
<div class="title-section">
<h2 class="page-title">{{ pageTitle }}</h2>
<div class="page-breadcrumb">
<span>工作流管理</span>
<span class="separator">></span>
<!-- <span>工作流管理</span>-->
<!-- <span class="separator">></span>-->
<span>{{ isNewApplication ? "发起申请" : "任务处理" }}</span>
</div>
</div>
<div class="status-section">
<span class="status-label">状态</span>
<span class="status-label">流程状态</span>
<span class="status-badge" :class="statusClass">{{ processStatusText }}</span>
</div>
</div>
@@ -69,7 +69,7 @@
<!-- 历史办理过程面板 -->
<div v-if="shouldShowHistoryProcess" class="history-panel">
<div class="panel-header">
<h3 class="panel-title">办理过程</h3>
<h3 class="panel-title">详细办理过程</h3>
</div>
<div class="panel-content">
<div id="history-process-container" class="form-content">
@@ -330,7 +330,6 @@ module.exports = {
// 加载申请表单
async loadApplicationForm() {
debugger
if (!this.defineKey || !this.processDefinition.instanceUrl) return
this.pjaxLoading.apply = true
@@ -401,23 +400,25 @@ module.exports = {
// 加载历史办理过程
async loadHistoryProcess() {
if (!this.businessId) return
const { instanceViewUrl } = this.processInstance.jsonObject
this.pjaxLoading.historyProcess = true
$.pjax({
url: `/platform/article/common/fullForm?businessId=${this.businessId}`,
container: "#history-process-container",
push: false,
replace: false,
timeout: 10000
})
.done(() => {
this.pjaxLoading.historyProcess = false
})
.fail(() => {
this.pjaxLoading.historyProcess = false
console.log("历史办理过程加载失败")
if (instanceViewUrl) {
$.pjax({
url: `${instanceViewUrl}?businessId=${this.businessId}&instanceId=${this.instanceId}`,
container: "#history-process-container",
push: false,
replace: false,
timeout: 10000
})
.done(() => {
this.pjaxLoading.historyProcess = false
})
.fail(() => {
this.pjaxLoading.historyProcess = false
console.log("历史办理过程加载失败")
})
}
},
// 显示流程图
@@ -1,5 +1,18 @@
<template>
<div class="snaker-task-action" v-if="!loading || taskInfo">
<!-- 指定下一节点处理人 -->
<div class="next-handler-section" v-if="!isFirstTaskNodeOrNew && supportCandidate">
<el-checkbox v-model="specifyNextHandler" @change="onSpecifyNextHandlerChange">指定下一节点处理人</el-checkbox>
<div class="handler-select-wrapper" v-if="specifyNextHandler">
<el-select v-model="selectedHandler" placeholder="请选择处理人" clearable filterable class="handler-select">
<el-option v-for="candidate in candidates" :key="candidate.userId" :label="candidate.userName" :value="candidate.userId">
<span style="float: left">{{ candidate.userName }}({{ candidate.ext?.loginName }})</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ candidate.ext?.unitName }}</span>
</el-option>
</el-select>
</div>
</div>
<!-- 第一个任务节点或新申请显示提交保存草稿取消 -->
<template v-if="isFirstTaskNodeOrNew">
<el-button type="primary" @click="handleSubmit" :loading="actionLoading" icon="el-icon-upload2">提交</el-button>
@@ -75,6 +88,11 @@ module.exports = {
NORMAL: 0, // 普通任务
COUNTERSIGN: 1 // 会签任务
},
// 指定下一节点处理人相关
specifyNextHandler: false, // 是否指定下一节点处理人
selectedHandler: null, // 选中的处理人ID
candidates: [], // 候选人列表
supportCandidate: false,
taskId: GetQueryString("taskId"),
instanceId: GetQueryString("instanceId"),
@@ -104,6 +122,7 @@ module.exports = {
// 只有当有任务ID时才加载任务信息
if (this.taskId) {
this.loadTaskInfo()
this.loadCandidates()
}
},
methods: {
@@ -149,8 +168,8 @@ module.exports = {
handleAction(actionKey) {
if (this.actionLoading || !this.taskInfo) return
// 触发父组件事件,传递操作类型和任务信息
this.$emit("task-action", {
// 构建操作数据
const actionData = {
submitType: this.actionEnum[actionKey],
taskId: this.taskId,
processTaskId: this.taskId,
@@ -158,7 +177,15 @@ module.exports = {
defineId: this.defineId,
defineKey: this.defineKey,
businessId: this.businessId
})
}
// 如果指定了下一节点处理人,添加到操作数据中
if (this.specifyNextHandler && this.selectedHandler) {
actionData.tf_nextNodeOperator = this.selectedHandler
}
// 触发父组件事件,传递操作类型和任务信息
this.$emit("task-action", actionData)
},
// 保存草稿
@@ -168,7 +195,7 @@ module.exports = {
this.$emit("save-draft", {
submitType: this.actionEnum.APPLY,
defineKey: this.defineKey,
defineId: this.defineId,
defineId: this.defineId
})
},
@@ -182,6 +209,25 @@ module.exports = {
if (this.taskId) {
this.loadTaskInfo()
}
},
// 处理指定下一节点处理人勾选框变化
onSpecifyNextHandlerChange(checked) {
if (!checked) {
this.selectedHandler = null
}
},
// 加载候选人列表
loadCandidates() {
$.get("/flow/common/candidate", {
taskId: this.taskId
}).then((res) => {
if (res.code === 0) {
this.candidates = res.data.candidates
this.supportCandidate = res.data.support
}
})
}
}
}
@@ -208,6 +254,25 @@ module.exports = {
min-height: 60px;
}
/* 指定下一节点处理人样式 */
.next-handler-section {
margin-bottom: 20px;
padding: 15px;
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 4px;
text-align: left;
}
.handler-select-wrapper {
margin-top: 10px;
}
.handler-select {
width: 100%;
max-width: 300px;
}
/* 响应式 */
@media (max-width: 768px) {
.snaker-task-action {
@@ -221,5 +286,14 @@ module.exports = {
width: 100%;
margin: 0;
}
.next-handler-section {
margin-bottom: 15px;
padding: 10px;
}
.handler-select {
max-width: 100%;
}
}
</style>
@@ -1,149 +1,173 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>流程设计器</title>
<script src="/assets/platform/plugins/vue/vue.js"></script>
<script src="/assets/platform/plugins/jquery/jquery.js"></script>
<script src="/assets/platform/plugins/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="https://cdn.staticfile.net/element-ui/2.15.14/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/root.css" />
<!-- 引入 core 包和对应 css-->
<script src="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/logic-flow.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/style/index.css" />
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
<style>
#app {
height: 100vh;
}
</style>
</head>
<body>
<div id="app">
<snaker-flow-designer ref="designer"
v-model="flowData"
@on-save="handleSave"
:show-doc="false"
node-render-type="html"
:extend-property-keys="[
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>流程设计器</title>
<script src="/assets/platform/plugins/vue/vue.js"></script>
<script src="/assets/platform/plugins/jquery/jquery.js"></script>
<script src="/assets/platform/plugins/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="https://cdn.staticfile.net/element-ui/2.15.14/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/root.css" />
<!-- 引入 core 包和对应 css-->
<script src="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/logic-flow.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/style/index.css" />
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
<style>
#app {
height: 100vh;
}
</style>
</head>
<body>
<div id="app">
<snaker-flow-designer
ref="designer"
v-model="flowData"
@on-save="handleSave"
:show-doc="false"
node-render-type="html"
:extend-property-keys="[
'candidateUsers',
'candidateGroups',
'candidateHandler',
'assigneeText',
'assigneeMode'
]"
>
<!-- <template v-slot:form-item-task-form="{model,field}">-->
<!-- <el-form-item label="form">-->
<!-- -->
<!-- </el-form-item>-->
<!-- </template>-->
>
<!-- <template v-slot:form-item-task-form="{model,field}">-->
<!-- <el-form-item label="form">-->
<!-- -->
<!-- </el-form-item>-->
<!-- </template>-->
<template v-slot:form-item-task-assignee="{model,field}">
<assignee-form :model="model" :field="field"
:start_node_next_node_ids="startNodeNextNodeIds"></assignee-form>
</template>
<template v-slot:form-item-task-assignee="{model,field}">
<assignee-form :model="model" :field="field" :start_node_next_node_ids="startNodeNextNodeIds"></assignee-form>
</template>
<template v-slot:form-item-task-assignment-handler="{model,field}">
<el-form-item label="参与者处理类">
<el-select v-model="model[field]" style="width: 100%" clearable
:disabled="startNodeNextNodeIds.includes(model.name)">
<el-option v-for="item in assignmentHandlerClassOptions" :key="item.value"
:value="item.value"
:label="item.name">
</el-option>
</el-select>
</el-form-item>
</template>
<template v-slot:form-item-task-assignment-handler="{model,field}">
<el-form-item label="参与者处理类">
<el-select v-model="model[field]" style="width: 100%" clearable :disabled="startNodeNextNodeIds.includes(model.name)">
<el-option
v-for="item in assignmentHandlerClassOptions"
:key="item.value"
:value="item.value"
:label="item.name"
></el-option>
</el-select>
</el-form-item>
</template>
</snaker-flow-designer>
</div>
</body>
<script>
<!--#include('assigneeForm.js'){}#-->
<template v-slot:form-item-task-candidate-handler="{model,field}">
<el-form-item label="候选者处理类">
<el-select v-model="model[field]" style="width: 100%" clearable :disabled="startNodeNextNodeIds.includes(model.name)">
<el-option
v-for="item in candidateHandlerClassOptions"
:key="item.value"
:value="item.value"
:label="item.name"
></el-option>
</el-select>
</el-form-item>
</template>
Vue.use(SnakerflowDesigner.default)
const vue = new Vue({
el: "#app",
components: {
"assignee-form": assigneeForm
},
data() {
return {
id: "${id!}",
designerData: {},
flowData: {},
assignmentHandlerClassOptions: []
}
},
computed: {
startNodeNextNodeIds() {
if (this.$refs.designer && this.$refs.designer.lf) {
const graphData = this.$refs.designer.lf.getGraphData()
if (graphData) {
const { nodes, edges } = graphData
const startNode = nodes.find(v => v.type === "snaker:start")
if (startNode) {
const targetNodeIds = edges.filter(v => v.sourceNodeId === startNode.id).map(v => v.targetNodeId)
return targetNodeIds
<!-- <template v-slot="{model,field}">-->
<!-- <el-form-item label="表单查看URL">-->
<!-- <el-input v-model="model[instanceViewUrl]"></el-input>-->
<!-- </el-form-item>-->
<!-- </template>-->
</snaker-flow-designer>
</div>
</body>
<script>
<!--#include('assigneeForm.js'){}#-->
Vue.use(SnakerflowDesigner.default)
const vue = new Vue({
el: "#app",
components: {
"assignee-form": assigneeForm
},
data() {
return {
id: "${id!}",
designerData: {},
flowData: {},
assignmentHandlerClassOptions: [],
candidateHandlerClassOptions: []
}
},
computed: {
startNodeNextNodeIds() {
if (this.$refs.designer && this.$refs.designer.lf) {
const graphData = this.$refs.designer.lf.getGraphData()
if (graphData) {
const { nodes, edges } = graphData
const startNode = nodes.find((v) => v.type === "snaker:start")
if (startNode) {
const targetNodeIds = edges.filter((v) => v.sourceNodeId === startNode.id).map((v) => v.targetNodeId)
return targetNodeIds
}
}
}
return []
}
return []
}
},
methods: {
handleSave(val) {
const design = {
...this.designerData,
content: val.json
}
$.post("/flow/design/updateContent", { design: JSON.stringify(design) }).then(res => {
if (res.code === 0) {
window.parent.postMessage("success")
} else {
window.parent.postMessage("error")
}
})
},
getDetail() {
$.get("/flow/design/detail", { id: this.id }).then((res) => {
if (res.code === 0) {
this.designerData = res.data
if (res.data.content) {
this.flowData = res.data.content
methods: {
handleSave(val) {
const design = {
...this.designerData,
content: val.json
}
$.post("/flow/design/updateContent", { design: JSON.stringify(design) }).then((res) => {
if (res.code === 0) {
window.parent.postMessage("success")
} else {
this.flowData = {}
window.parent.postMessage("error")
}
}
})
})
},
getDetail() {
$.get("/flow/design/detail", { id: this.id }).then((res) => {
if (res.code === 0) {
this.designerData = res.data
if (res.data.content) {
this.flowData = res.data.content
} else {
this.flowData = {}
}
}
})
},
init() {
$.get("/flow/design/assigmentHandlerClass").then((res) => {
if (res.code === 0) {
this.assignmentHandlerClassOptions = res.data
}
})
$.get("/flow/design/candidateHandlerClass").then((res) => {
if (res.code === 0) {
this.candidateHandlerClassOptions = res.data
}
})
},
getData() {
console.log(this.$refs.designer)
}
},
init() {
$.get("/flow/design/assigmentHandlerClass").then((res) => {
if (res.code === 0) {
this.assignmentHandlerClassOptions = res.data
}
})
created() {
this.init()
},
getData() {
console.log(this.$refs.designer)
mounted() {
if (this.id) {
this.getDetail()
}
}
},
created() {
this.init()
},
mounted() {
if (this.id) {
this.getDetail()
}
}
})
</script>
})
</script>
</html>
@@ -77,6 +77,12 @@ layout("/layouts/platform.html"){
<el-form-item label="手机端发起地址" prop="h5InstanceUrl">
<el-input v-model="formData.h5InstanceUrl" placeholder="请输入手机端发起地址"></el-input>
</el-form-item>
<el-form-item label="电脑端查看地址" prop="instanceViewUrl">
<el-input v-model="formData.instanceViewUrl" placeholder="请输入电脑端发起地址"></el-input>
</el-form-item>
<el-form-item label="手机端查看地址" prop="h5InstanceViewUrl">
<el-input v-model="formData.h5InstanceViewUrl" placeholder="请输入手机端发起地址"></el-input>
</el-form-item>
<el-form-item label="图标" prop="icon">
<el-input v-model="formData.icon" placeholder="请输入图标"></el-input>
</el-form-item>
@@ -0,0 +1,105 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="名称">
<el-input v-model="pageForm.displayName" placeholder="名称" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button type="primary" @click="onAdd" size="small" icon="el-icon-plus">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="标题"></el-table-column>
<el-table-column prop="isDeployed" label="是否启用">
<template slot-scope="{row}">
<el-tag size="mini" v-if="row.enable" type="success"></el-tag>
<el-tag size="mini" v-else type="info"></el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="250px">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onEdit(row)">编辑</el-button>
<el-button type="danger" size="mini" @click="onDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" width="70%">
<el-form :model="formData" ref="formRef" label-width="120px">
<el-form-item label="标题" prop="title" :rules="{ required: true, message: '请输入标题', trigger: 'blur' }">
<el-input v-model="formData.title" placeholder="请输入标题"></el-input>
</el-form-item>
<el-form-item label="封面图" prop="cover" :rules="{ required: true, message: '请上传封面图', trigger: 'blur' }">
<file-upload
:value.sync="formData.cover"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="内容" prop="content" :rules="{ required: true, message: '请输入内容', trigger: 'blur' }">
<text-editor v-model="formData.content"></text-editor>
</el-form-item>
<el-form-item label="是否启用" prop="enable">
<el-switch v-model="formData.enable"></el-switch>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
formData: {}
}
},
methods: {
onAdd() {
this.formData = {}
this.dialogVisible = true
},
onEdit(row) {
this.dialogVisible = true
this.formData = { ...row }
},
onSubmit() {
$.post("/platform/huimin/manage/" + (this.formData.id ? "update" : "insert"), { data: JSON.stringify(this.formData) }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
this.dialogVisible = false
}
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,106 @@
<div id="suggestion-box-apply-form" v-cloak>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">{{formData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{formData.loginName}}</el-descriptions-item>
<el-descriptions-item label="单位">{{formData.unitName}}</el-descriptions-item>
<el-descriptions-item label="工会">{{formData.unionName}}</el-descriptions-item>
<el-descriptions-item label="标题" :span="2">
<el-form-item prop="title" label="标题">
<el-input v-model="formData.title" maxlength="100" show-word-limit placeholder="请输入标题"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="填写意见建议内容" :span="2">
<el-form-item prop="content" label="填写意见建议内容">
<el-input v-model="formData.content" type="textarea" maxlength="500" show-word-limit placeholder="请输入内容"></el-input>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script>
new Vue({
el: "#suggestion-box-apply-form",
store,
data() {
return {
businessId: GetQueryString("businessId"),
formData: {},
formRules: {
title: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
content: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
}
}
},
methods: {
handleTaskAction(val) {
console.log(val)
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios
.post("/flow/common/startInstanceAndExecute", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
window.parent.postMessage({ type: "task-complete" }, "*")
}
})
}
})
},
handleSaveDraft(val) {
this.$refs.formRef.validateField(["title"], (errMsg) => {
if (errMsg) {
this.$message.warning("请填写标题")
return
}
this.$axios
.post("/flow/common/startInstance", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
// 发送完成消息
window.parent.postMessage(
{
type: "task-complete"
},
"*"
)
}
})
})
},
handleCancel() {
// 关闭浏览器窗口
window.close()
},
init() {
if (this.businessId) {
} else {
const { username, loginname, id, unit, union, mobile } = this.$store.state.user
this.formData = {
userName: username,
loginName: loginname,
submitterId: id,
unitId: unit?.id,
unitName: unit?.name,
unionId: union?.id,
unionName: union?.name,
concat: mobile
}
}
}
},
created() {
this.init()
}
})
</script>
@@ -0,0 +1,84 @@
<!--#
layout("/layouts/platform.html"){
#-->
<guava ref="guava">
<div id="app">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度" style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onOpen(row.id)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskKey === 'apply' || !row.instanceId" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="['waiting'].includes(row.flow_status)" size="mini" type="danger" @click="onRevoke(row.id)">撤销</el-button>
<el-button v-if="row.taskKey === 'apply' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
</guava>
<script>
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/suggestionBox2/apply/pageData"
}
},
methods: {
onOpen(id) {},
onEdit(row) {
window.open(
"/flow/common/approval/form?taskId=" +
(row.taskId || "") +
"&instanceId=" +
(row.instanceId || "") +
"&businessId=" +
row.id +
"&defineKey=XWTG"
)
},
onRevoke(id) {},
onDelete(id) {}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,88 @@
<div id="suggestion-box-view">
<!-- <el-form ref="formRef" label-width="0" label-suffix="" class="flow-task-form">-->
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">{{viewData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="单位">{{viewData.unitName}}</el-descriptions-item>
<el-descriptions-item label="工会">{{viewData.unionName}}</el-descriptions-item>
<el-descriptions-item label="标题" :span="2">{{viewData.viewData}}</el-descriptions-item>
<el-descriptions-item label="填写意见建议内容" :span="2">{{viewData.content}}</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="task-panel mt10">
<div class="task-panel-header">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{ task.taskFormData.opinion }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
<!-- </el-form>-->
</div>
<script>
new Vue({
el: "#suggestion-box-view",
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
businessId: GetQueryString("businessId"),
instanceId: GetQueryString("instanceId"),
viewData: {},
doneTasks: []
}
},
methods: {
info() {
this.$axios.post("/platform/suggestionBox/view/info", { id: this.businessId }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", { instanceId: this.instanceId }).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
}
},
created() {
this.info()
this.getDoneTasks()
}
})
</script>
<style>
.task-panel {
background: white;
border-radius: 4px;
overflow: hidden;
}
.task-panel-header {
background: rgb(250, 250, 250);
border: 1px solid rgb(228, 231, 237);
border-bottom: none;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
@@ -0,0 +1,49 @@
<div id="suggestion-box-apply-form" v-cloak>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-form-item label="审批意见" prop="tf_opinion" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
</el-form-item>
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction" @cancel="handleCancel"></snaker-flow-task-form-action>
</div>
<script>
new Vue({
el: "#suggestion-box-apply-form",
store,
data() {
return {
businessId: GetQueryString("businessId"),
formData: {},
formRules: {}
}
},
methods: {
handleTaskAction(val) {
console.log(val)
this.$axios
.post("/flow/common/executeTask", {
data: JSON.stringify({
...val,
...this.formData
})
})
.then((res) => {
if (res.code === 0) {
this.$message.success("操作成功")
// 发送完成消息
window.parent.postMessage(
{
type: "task-complete"
},
"*"
)
}
})
},
handleCancel(val) {
console.log(val)
}
}
})
</script>
@@ -0,0 +1,78 @@
<!--#
layout("/layouts/platform.html"){
#-->
<guava ref="guava">
<div id="app">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度" style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="投稿标题"></el-table-column>
<el-table-column prop="loginName" label="投稿人工号"></el-table-column>
<el-table-column prop="userName" label="投稿人姓名"></el-table-column>
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
<el-table-column prop="taskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="onOpen(row.id)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskState === 10" @click="openApproval(row)" size="mini" type="primary">审核</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
</guava>
<script>
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/suggestionBox2/xgh/pageData",
pageForm: {
approval: false
}
}
},
methods: {
onOpen() {},
openApproval(row) {
window.open("/flow/common/approval/form?taskId=" + row.taskId + "&instanceId=" + row.instanceId + "&businessId=" + row.businessNo)
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->