master
cody 2 weeks ago
parent ee64421275
commit 0bc5fe1c9c

@ -2,9 +2,9 @@
ENV = 'development'
# base api
VUE_APP_BASE_API='https://cz-hjjc-test.115.langye.net/'
VUE_APP_BASE_API='http://127.0.0.1:8000'
#VUE_APP_BASE_API='http://czemc.localhost'
VUE_APP_UPLOAD_API='https://cz-hjjc-test.115.langye.net/api/upload-file'
VUE_APP_UPLOAD_API='http://127.0.0.1:8000/api/upload-file'
VUE_APP_PREVIEW=//view.langye.net/preview/onlinePreview
VUE_APP_MODULE_NAME=oa
VUE_APP_OUTPUT_DIR='../backend/public/oa/'

@ -4,7 +4,7 @@
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>",
"scripts": {
"dev": "vue-cli-service serve",
"dev": "CHOKIDAR_USEPOLLING=true vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",

@ -86,6 +86,14 @@ export function getNextNodeUsers(params,isLoading=false) {
})
}
export function freeAssignPre(flowId, isLoading = false) {
return request({
method: 'get',
url: `/api/oa/flow/free-assign-pre/${flowId}`,
isLoading
})
}
//查看列表相关
export function flowList(type,params,isLoading = false) {
return request({
@ -254,6 +262,33 @@ export function updateFlowTime(params,isLoading=true) {
})
}
export function updateFlowLogMeta(data, isLoading = true) {
return request({
method: 'post',
url: '/api/oa/flow/update-flow-log-meta',
data,
isLoading
})
}
export function deleteFlowLog(data, isLoading = true) {
return request({
method: 'post',
url: '/api/oa/flow/delete-flow-log',
data,
isLoading
})
}
export function insertHistoryLog(data, isLoading = true) {
return request({
method: 'post',
url: '/api/oa/flow/insert-history-log',
data,
isLoading
})
}
export function getOvertimeHoliday(params,isLoading=false) {
return request({

@ -544,7 +544,16 @@
<!-- 审批日志-->
<div v-if="/\/detail/.test($route.path)" style="margin-top: 10px">
<div>流转记录</div>
<div style="display: flex; align-items: center; justify-content: space-between;">
<div>流转记录</div>
<el-button
v-if="canManageFlowLog && $route.query.flow_id"
icon="el-icon-plus"
type="primary"
size="small"
@click="openInsertHistoryLogDialog()"
>新增节点</el-button>
</div>
<vxe-table
style="margin-top: 10px;"
show-footer
@ -642,6 +651,22 @@
<span>{{ diffTime(row.updated_at, row.created_at) }}</span>
</template>
</vxe-column>
<vxe-column
v-if="canManageFlowLog"
fixed="right"
align="center"
title="操作"
width="240"
>
<template #default="{ row }">
<el-button type="text" size="mini" @click="openEditLogDialog(row)"
>编辑</el-button
>
<el-button type="text" size="mini" style="color: #f56c6c" @click="handleDeleteFlowLog(row)"
>删除</el-button
>
</template>
</vxe-column>
</vxe-table>
</div>
@ -720,27 +745,203 @@
></rollback>
<el-backtop></el-backtop>
<!-- 更改时间 -->
<!-- 编辑流转记录 -->
<el-dialog
title="请选择时间"
title="编辑流转记录"
:visible.sync="isShowTime"
:close-on-click-modal="false"
width="30%"
width="720px"
@closed="resetEditFlowLogForm"
>
<!-- 日期时间选择器 -->
<el-date-picker
v-model="selectedDateTime"
type="datetime"
placeholder="选择日期时间"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
:clearable="false"
style="width: 100%"
></el-date-picker>
<el-form
ref="editFlowLogFormRef"
:model="editFlowLogForm"
:rules="editFlowLogRules"
label-width="100px"
>
<el-form-item label="节点名称" prop="flow_node_id">
<el-select
v-model="editFlowLogForm.flow_node_id"
filterable
style="width: 100%"
placeholder="请选择节点名称"
>
<el-option
v-for="item in historyLogNodeOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="办理状态" prop="status">
<el-select
v-model="editFlowLogForm.status"
style="width: 100%"
placeholder="请选择办理状态"
>
<el-option
v-for="item in editFlowLogStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="承办人" prop="user_id">
<el-select
v-model="editFlowLogForm.user_id"
filterable
style="width: 100%"
placeholder="请选择承办人"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="流转时间" prop="created_at">
<el-date-picker
v-model="editFlowLogForm.created_at"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择流转时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="办理时间" prop="updated_at">
<el-date-picker
v-model="editFlowLogForm.updated_at"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择办理时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="退回原因" prop="reason">
<el-input
v-model="editFlowLogForm.reason"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="退回状态时请输入原因"
/>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="editFlowLogForm.sort"
:min="1"
:step="1"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="耗时">
<el-input :value="editFlowLogUseTime" disabled />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="isShowTime = false,timeId='',selectedDateTime='',selectedDateType=''">取消</el-button>
<el-button type="primary" @click="updateTime"></el-button>
<el-button @click="isShowTime = false">取消</el-button>
<el-button type="primary" :loading="editFlowLogSubmitting" @click="submitEditFlowLog"></el-button>
</div>
</el-dialog>
<el-dialog
title="插入流转记录"
:visible.sync="isShowInsertHistoryLog"
:close-on-click-modal="false"
width="520px"
@closed="resetInsertHistoryLogForm"
>
<el-form
ref="insertHistoryLogFormRef"
:model="insertHistoryLogForm"
:rules="insertHistoryLogRules"
label-width="100px"
>
<el-form-item label="插入位置" prop="insert_position">
<el-radio-group v-model="insertHistoryLogForm.insert_position">
<el-radio label="before">参考记录前</el-radio>
<el-radio label="after">参考记录后</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="参考记录" prop="anchor_log_id">
<el-select v-model="insertHistoryLogForm.anchor_log_id" filterable style="width: 100%" placeholder="请选择参考记录">
<el-option
v-for="item in historyLogAnchorOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="节点名称" prop="flow_node_id">
<el-select v-model="insertHistoryLogForm.flow_node_id" filterable style="width: 100%" placeholder="请选择节点">
<el-option
v-for="item in historyLogNodeOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="承办人员" prop="user_id">
<el-select v-model="insertHistoryLogForm.user_id" filterable style="width: 100%" placeholder="请选择承办人员">
<el-option
v-for="item in allUserOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="流转时间" prop="created_at">
<el-date-picker
v-model="insertHistoryLogForm.created_at"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择流转时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="办理状态" prop="status">
<el-select
v-model="insertHistoryLogForm.status"
style="width: 100%"
placeholder="请选择办理状态"
>
<el-option
v-for="item in flowLogStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="办理意见" prop="remark">
<el-input
v-model="insertHistoryLogForm.remark"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="可选"
/>
</el-form-item>
<el-form-item v-if="insertHistoryLogForm.status < 0" label="退回原因" prop="reason">
<el-input
v-model="insertHistoryLogForm.reason"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="请输入退回原因"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="isShowInsertHistoryLog = false">取消</el-button>
<el-button type="primary" @click="submitInsertHistoryLog"></el-button>
</div>
</el-dialog>
<!-- 更改承办人员 -->
@ -1018,9 +1219,13 @@ import {
create,
deal,
fieldConfig, flowList,
deleteFlowLog,
freeAssignPre,
insertHistoryLog,
preConfig,
preDeal,
updateNodeTime,
updateFlowLogMeta,
view,
} from "@/api/flow";
import { getPaymentsByFlowId, getPaymentsByContractId, getBudgetContractDetail, getPlannedExpenditure, getPlannedExpenditureTemplatesByCategory, getPaymentCategoryTemplateElements, getDetailTableFields, getOaFlowDetails, getTemplateElementDetail } from "@/api/payment";
@ -1054,10 +1259,35 @@ export default {
isShowTime: false,
selectedDateTime: '',
selectedDateType: '',
editFlowLogSubmitting: false,
editFlowLogForm: {
id: '',
flow_id: '',
flow_node_id: '',
user_id: '',
status: 1,
created_at: '',
updated_at: '',
sort: 1,
reason: '',
},
isShowUserDialog: false,
selectedUserId: '',
userList: [],
currentRowId: '',
flowLogNodeOptions: [],
isShowInsertHistoryLog: false,
insertHistoryLogSubmitting: false,
insertHistoryLogForm: {
insert_position: 'after',
anchor_log_id: '',
flow_node_id: '',
user_id: '',
created_at: '',
status: 1,
remark: '',
reason: '',
},
info: [],
config: {},
writeableFields: [],
@ -2515,6 +2745,7 @@ export default {
}
}
this.form = Object.assign({}, this.form);
await this.loadFlowLogNodeOptions();
loading.close();
//
@ -2557,6 +2788,7 @@ export default {
this.form = Object.assign({}, this.form);
// fill_flow_title watcher default_json
this.setupFillFlowTitleWatcher(fields);
await this.loadFlowLogNodeOptions();
loading.close();
} catch (err) {
console.error(err);
@ -2638,6 +2870,7 @@ export default {
}
}
this.form = Object.assign({}, this.form);
await this.loadFlowLogNodeOptions();
loading.close();
//
@ -2795,33 +3028,185 @@ export default {
async cellDblclickEvent({ row, column }) {
// if(this.$store.state.user.username !== 'admin') return
if(!this.$store.state.user.roles.includes("全局流程监管")) return
if(column.field === 'created_at' || column.field === 'updated_at') {
this.timeId = row.id
this.selectedDateType = column.field
this.selectedDateTime = row[column.field]
this.isShowTime = true
if (!this.canManageFlowLog) return
if (['created_at', 'updated_at', 'user.name', 'node.name', 'status', 'reason'].includes(column.field)) {
this.openEditLogDialog(row)
}
},
resetInsertHistoryLogForm(defaults = {}) {
const normalizedDefaults = {
...defaults,
anchor_log_id: defaults.anchor_log_id === '' || defaults.anchor_log_id === undefined || defaults.anchor_log_id === null ? '' : Number(defaults.anchor_log_id),
flow_node_id: defaults.flow_node_id === '' || defaults.flow_node_id === undefined || defaults.flow_node_id === null ? '' : Number(defaults.flow_node_id),
user_id: defaults.user_id === '' || defaults.user_id === undefined || defaults.user_id === null ? '' : Number(defaults.user_id),
status: defaults.status === '' || defaults.status === undefined || defaults.status === null ? 1 : Number(defaults.status),
};
this.insertHistoryLogSubmitting = false;
this.insertHistoryLogForm = {
insert_position: 'after',
anchor_log_id: normalizedDefaults.anchor_log_id || this.historyLogAnchorOptions[0]?.id || '',
flow_node_id: normalizedDefaults.flow_node_id || this.historyLogNodeOptions[0]?.id || '',
user_id: normalizedDefaults.user_id || this.allUserOptions[0]?.id || '',
created_at: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
status: normalizedDefaults.status,
remark: '',
reason: '',
...normalizedDefaults,
};
if (this.$refs.insertHistoryLogFormRef) {
this.$refs.insertHistoryLogFormRef.clearValidate();
}
if(column.field === "user.name"){
this.currentRowId = row.id
this.selectedUserId = row.user ? row.user.id : ''
this.isShowUserDialog = true
this.getUserList()
},
openInsertHistoryLogDialog(row = null) {
if (!this.historyLogAnchorOptions.length || !this.historyLogNodeOptions.length) {
this.$message.warning('当前流程缺少可补录的参考记录、节点或承办人员');
return;
}
const openDialog = () => {
this.resetInsertHistoryLogForm({
anchor_log_id: row?.id || this.historyLogAnchorOptions[0]?.id || '',
});
this.isShowInsertHistoryLog = true;
};
if (this.allUserOptions.length) {
openDialog();
return;
}
this.getUserList().then(openDialog);
},
resetEditFlowLogForm(defaults = {}) {
const normalizedDefaults = {
...defaults,
id: defaults.id === '' || defaults.id === undefined || defaults.id === null ? '' : Number(defaults.id),
flow_id: defaults.flow_id === '' || defaults.flow_id === undefined || defaults.flow_id === null ? '' : Number(defaults.flow_id),
flow_node_id: defaults.flow_node_id === '' || defaults.flow_node_id === undefined || defaults.flow_node_id === null ? '' : Number(defaults.flow_node_id),
user_id: defaults.user_id === '' || defaults.user_id === undefined || defaults.user_id === null ? '' : Number(defaults.user_id),
status: defaults.status === '' || defaults.status === undefined || defaults.status === null ? 1 : Number(defaults.status),
sort: defaults.sort === '' || defaults.sort === undefined || defaults.sort === null ? 1 : Number(defaults.sort),
};
this.editFlowLogSubmitting = false;
this.editFlowLogForm = {
id: '',
flow_id: '',
flow_node_id: '',
user_id: '',
status: 1,
created_at: '',
updated_at: '',
sort: 1,
reason: '',
...normalizedDefaults,
};
if (this.$refs.editFlowLogFormRef) {
this.$refs.editFlowLogFormRef.clearValidate();
}
},
async openEditLogDialog(row) {
if (!this.userList.length) {
await this.getUserList();
}
const latestRow = (this.config.logs || []).find((item) => Number(item.id) === Number(row.id)) || row;
this.resetEditFlowLogForm({
id: latestRow.id,
flow_id: latestRow.flow_id || this.$route.query.flow_id || '',
flow_node_id: latestRow.flow_node_id || '',
user_id: latestRow.user?.id || latestRow.user_id || '',
status: latestRow.status,
created_at: latestRow.created_at,
updated_at: latestRow.updated_at,
sort: latestRow.sort || 1,
reason: latestRow.reason || '',
});
this.isShowTime = true;
},
updateTime() {
updateNodeTime({
id: this.timeId,
date: this.selectedDateTime,
date_type: this.selectedDateType
}).then(_ => {
this.$message.success('更新成功')
this.timeId = ''
this.selectedDateTime = ''
this.selectedDateType = ''
this.isShowTime = false
this.getConfig()
})
async handleDeleteFlowLog(row) {
try {
await this.$confirm('确认删除这条流转记录吗?删除后会重新整理排序。', '提示', {
type: 'warning',
closeOnClickModal: false,
});
} catch (err) {
return;
}
try {
await deleteFlowLog({ id: row.id });
this.$message.success('删除成功');
this.getConfig();
} catch (err) {
console.error(err);
}
},
async submitEditFlowLog() {
if (this.editFlowLogSubmitting) return;
try {
await this.$refs.editFlowLogFormRef.validate();
} catch (err) {
return;
}
const createdAt = this.$moment(this.editFlowLogForm.created_at);
const updatedAt = this.$moment(this.editFlowLogForm.updated_at);
if (updatedAt.isBefore(createdAt)) {
this.$message.warning('办理时间不能早于流转时间');
return;
}
this.editFlowLogSubmitting = true;
try {
const res = await updateFlowLogMeta({
id: Number(this.editFlowLogForm.id),
flow_id: Number(this.editFlowLogForm.flow_id || this.$route.query.flow_id),
flow_node_id: Number(this.editFlowLogForm.flow_node_id),
user_id: Number(this.editFlowLogForm.user_id),
status: Number(this.editFlowLogForm.status),
created_at: this.editFlowLogForm.created_at,
updated_at: this.editFlowLogForm.updated_at,
sort: Number(this.editFlowLogForm.sort),
reason: this.editFlowLogForm.status < 0 ? (this.editFlowLogForm.reason || '') : '',
});
if (Array.isArray(res?.logs)) {
this.config = {
...this.config,
logs: res.logs,
};
}
this.$message.success('编辑流转记录成功');
this.isShowTime = false;
await this.getConfig();
} catch (err) {
console.error(err);
} finally {
this.editFlowLogSubmitting = false;
}
},
async submitInsertHistoryLog() {
if (this.insertHistoryLogSubmitting) return;
try {
await this.$refs.insertHistoryLogFormRef.validate();
} catch (err) {
return;
}
this.insertHistoryLogSubmitting = true;
try {
await insertHistoryLog({
flow_id: Number(this.$route.query.flow_id),
anchor_log_id: Number(this.insertHistoryLogForm.anchor_log_id),
insert_position: this.insertHistoryLogForm.insert_position,
flow_node_id: Number(this.insertHistoryLogForm.flow_node_id),
user_id: Number(this.insertHistoryLogForm.user_id),
created_at: this.insertHistoryLogForm.created_at,
status: Number(this.insertHistoryLogForm.status),
remark: this.insertHistoryLogForm.remark || '',
reason: this.insertHistoryLogForm.status < 0 ? this.insertHistoryLogForm.reason : '',
});
this.$message.success('插入流转记录成功');
this.isShowInsertHistoryLog = false;
this.getConfig();
} catch (err) {
console.error(err);
} finally {
this.insertHistoryLogSubmitting = false;
}
},
async getUserList() {
try {
@ -2835,6 +3220,31 @@ export default {
this.$message.error('获取用户列表失败')
}
},
async loadFlowLogNodeOptions() {
if (!this.$route.query.flow_id) {
this.flowLogNodeOptions = [];
return;
}
try {
const res = await freeAssignPre(this.$route.query.flow_id);
const nodes = Array.isArray(res?.nodes) ? res.nodes : [];
this.flowLogNodeOptions = nodes
.map((node) => ({
id: Number(node.id),
key: node.key === '' || node.key === undefined || node.key === null ? null : Number(node.key),
name: node.name || node.title || `节点${node.id}`,
}))
.filter((node) => !!node.id)
.sort((a, b) => {
const keyA = a.key === null || Number.isNaN(a.key) ? Number.MAX_SAFE_INTEGER : a.key;
const keyB = b.key === null || Number.isNaN(b.key) ? Number.MAX_SAFE_INTEGER : b.key;
return keyA - keyB || a.id - b.id;
});
} catch (err) {
console.error(err);
this.flowLogNodeOptions = [];
}
},
updateUser() {
if (!this.selectedUserId) {
this.$message.warning('请选择承办人员')
@ -2853,6 +3263,16 @@ export default {
},
},
computed: {
canManageFlowLog() {
const globalRoles = this.$store.state.user.roles || [];
const moduleRoles = this.$store.state.user.moduleRoles?.oa || [];
const adminId = Number(this.$store.state.user.adminId);
const username = this.$store.state.user.username;
return adminId === 1
|| username === 'admin'
|| globalRoles.includes('全局流程监管')
|| moduleRoles.includes('全局流程监管');
},
device() {
return this.$store.state.app.device;
},
@ -2905,6 +3325,122 @@ export default {
isFirstNode() {
return this.config?.logs?.length === 0 || this.config?.currentNode?.category === 'start'
},
historyLogAnchorOptions() {
return (this.config.logs || []).map((log) => ({
id: Number(log.id),
label: `${log.node?.name || '节点已调整'} / ${log.user?.name || '未知人员'} / ${this.$moment(log.created_at).format('YYYY-MM-DD HH:mm:ss')}`,
}));
},
historyLogNodeOptions() {
const nodeMap = new Map();
(this.flowLogNodeOptions || []).forEach((node) => {
const id = Number(node.id);
if (!id) return;
nodeMap.set(id, {
id,
name: node.name || `节点${node.id}`,
});
});
//
// el-select ID
(this.config.logs || []).forEach((log) => {
const id = Number(log.flow_node_id);
if (!id || nodeMap.has(id)) return;
nodeMap.set(id, {
id,
key: log.node?.key === '' || log.node?.key === undefined || log.node?.key === null ? null : Number(log.node.key),
name: log.node?.name || `节点${id}`,
});
});
return Array.from(nodeMap.values()).sort((a, b) => {
const keyA = a.key === null || Number.isNaN(a.key) ? Number.MAX_SAFE_INTEGER : a.key;
const keyB = b.key === null || Number.isNaN(b.key) ? Number.MAX_SAFE_INTEGER : b.key;
return keyA - keyB || a.id - b.id;
});
},
allUserOptions() {
return (this.userList || [])
.map((user) => ({
id: Number(user.id),
name: user.name || `用户${user.id}`,
}))
.filter((user) => !!user.id);
},
flowLogStatusOptions() {
return [
{ value: 1, label: this.myStatus.get(1) },
{ value: 0, label: this.myStatus.get(0) },
{ value: -1, label: this.myStatus.get(-1) },
{ value: -2, label: this.myStatus.get(-2) },
];
},
editFlowLogStatusOptions() {
return this.flowLogStatusOptions;
},
editFlowLogUseTime() {
const createdAt = this.editFlowLogForm.created_at;
const updatedAt = this.editFlowLogForm.updated_at;
if (!createdAt || !updatedAt) {
return '-';
}
const diff = this.$moment(updatedAt).diff(this.$moment(createdAt));
return this.formatTime(Math.max(0, diff));
},
editFlowLogRules() {
return {
flow_node_id: [{ required: true, message: '请选择节点名称', trigger: 'change' }],
status: [{ required: true, message: '请选择办理状态', trigger: 'change' }],
user_id: [{ required: true, message: '请选择承办人', trigger: 'change' }],
created_at: [{ required: true, message: '请选择流转时间', trigger: 'change' }],
updated_at: [
{ required: true, message: '请选择办理时间', trigger: 'change' },
{
validator: (rule, value, callback) => {
if (!value || !this.editFlowLogForm.created_at) {
callback();
return;
}
if (this.$moment(value).isBefore(this.$moment(this.editFlowLogForm.created_at))) {
callback(new Error('办理时间不能早于流转时间'));
return;
}
callback();
},
trigger: 'change',
},
],
sort: [{ required: true, message: '请输入排序', trigger: 'change' }],
reason: [{
validator: (rule, value, callback) => {
if (this.editFlowLogForm.status >= 0 || (value && String(value).trim())) {
callback();
return;
}
callback(new Error('请输入退回原因'));
},
trigger: 'blur',
}],
};
},
insertHistoryLogRules() {
return {
insert_position: [{ required: true, message: '请选择插入位置', trigger: 'change' }],
anchor_log_id: [{ required: true, message: '请选择参考记录', trigger: 'change' }],
flow_node_id: [{ required: true, message: '请选择节点名称', trigger: 'change' }],
user_id: [{ required: true, message: '请选择承办人员', trigger: 'change' }],
created_at: [{ required: true, message: '请选择流转时间', trigger: 'change' }],
status: [{ required: true, message: '请选择办理状态', trigger: 'change' }],
reason: [{ validator: (rule, value, callback) => {
if (this.insertHistoryLogForm.status >= 0 || (value && String(value).trim())) {
callback();
return;
}
callback(new Error('请输入退回原因'));
}, trigger: 'blur' }],
};
},
isSinglePage() {
// isSinglePage=1
// window.self !== window.top iframe padding//

@ -135,6 +135,25 @@
<span>{{ diffTime(row.updated_at, row.created_at) }}</span>
</template>
</vxe-column>
<vxe-column
v-if="canManageFlowLog"
fixed="right"
align="center"
title="操作"
width="240"
>
<template #default="{ row }">
<el-button type="text" size="mini" @click="openInsertHistoryLogDialog(row)"
>新增节点</el-button
>
<el-button type="text" size="mini" @click="openEditLogTimeDialog(row)"
>编辑</el-button
>
<el-button type="text" size="mini" style="color: #f56c6c" @click="handleDeleteFlowLog(row)"
>删除</el-button
>
</template>
</vxe-column>
</vxe-table>
</div>
@ -178,13 +197,21 @@
</template>
<template v-else>
<el-button
v-if="$store.state.user.adminId === 1 && $route.query.flow_id"
v-if="canManageFlowLog && $route.query.flow_id"
icon="el-icon-arrow-left"
type="danger"
size="small"
@click="isShowRollback = true"
>退回</el-button
>
<el-button
v-if="canManageFlowLog && $route.query.flow_id && historyLogAnchorOptions.length > 0"
icon="el-icon-plus"
type="primary"
size="small"
@click="openInsertHistoryLogDialog"
>插入流转记录</el-button
>
<el-button plain size="small" @click="$router.go(-1)"></el-button>
<el-button plain size="small" @click="print(false)"></el-button>
<!-- <el-button plain size="small" @click="print(true)">()</el-button> -->
@ -212,10 +239,98 @@
:flow="config.flow"
></rollback>
<el-dialog
title="插入流转记录"
:visible.sync="isShowInsertHistoryLog"
:close-on-click-modal="false"
width="520px"
@closed="resetInsertHistoryLogForm"
>
<el-form
ref="insertHistoryLogFormRef"
:model="insertHistoryLogForm"
:rules="insertHistoryLogRules"
label-width="100px"
>
<el-form-item label="插入位置" prop="insert_position">
<el-radio-group v-model="insertHistoryLogForm.insert_position">
<el-radio label="before">参考记录前</el-radio>
<el-radio label="after">参考记录后</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="参考记录" prop="anchor_log_id">
<el-select v-model="insertHistoryLogForm.anchor_log_id" filterable style="width: 100%" placeholder="请选择参考记录">
<el-option
v-for="item in historyLogAnchorOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="节点名称" prop="flow_node_id">
<el-select v-model="insertHistoryLogForm.flow_node_id" filterable style="width: 100%" placeholder="请选择节点">
<el-option
v-for="item in historyLogNodeOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="承办人员" prop="user_id">
<el-select v-model="insertHistoryLogForm.user_id" filterable style="width: 100%" placeholder="请选择承办人员">
<el-option
v-for="item in historyLogUserOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="流转时间" prop="created_at">
<el-date-picker
v-model="insertHistoryLogForm.created_at"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择流转时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="办理状态" prop="status">
<el-radio-group v-model="insertHistoryLogForm.status">
<el-radio :label="1">已完成</el-radio>
<el-radio :label="-1">退回</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="办理意见" prop="remark">
<el-input
v-model="insertHistoryLogForm.remark"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="可选"
/>
</el-form-item>
<el-form-item v-if="insertHistoryLogForm.status === -1" label="退回原因" prop="reason">
<el-input
v-model="insertHistoryLogForm.reason"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="请输入退回原因"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="isShowInsertHistoryLog = false">取消</el-button>
<el-button type="primary" @click="submitInsertHistoryLog"></el-button>
</div>
</el-dialog>
<el-backtop></el-backtop>
<!-- 更改时间 -->
<el-dialog
title="请选择时间"
:title="selectedDateType === 'updated_at' ? '编辑办理时间' : '编辑流转时间'"
:visible.sync="isShowTime"
:close-on-click-modal="false"
width="30%"
@ -251,9 +366,11 @@ import {
create,
deal,
fieldConfig, flowList,
deleteFlowLog,
preConfig,
preDeal,
updateNodeTime,
insertHistoryLog,
view,
} from "@/api/flow";
import { deepCopy } from "@/utils";
@ -275,6 +392,18 @@ export default {
isShowTime:false,
selectedDateTime:'',
selectedDateType:'',
isShowInsertHistoryLog: false,
insertHistoryLogSubmitting: false,
insertHistoryLogForm: {
insert_position: 'after',
anchor_log_id: '',
flow_node_id: '',
user_id: '',
created_at: '',
status: 1,
remark: '',
reason: '',
},
printKey: 0,
isShowRollback: false,
isShowForward: false,
@ -308,6 +437,86 @@ export default {
};
},
methods: {
resetInsertHistoryLogForm(defaults = {}) {
this.insertHistoryLogSubmitting = false;
this.insertHistoryLogForm = {
insert_position: 'after',
anchor_log_id: defaults.anchor_log_id || this.historyLogAnchorOptions[0]?.id || '',
flow_node_id: defaults.flow_node_id || this.historyLogNodeOptions[0]?.id || '',
user_id: defaults.user_id || this.historyLogUserOptions[0]?.id || '',
created_at: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
status: 1,
remark: '',
reason: '',
...defaults,
};
if (this.$refs.insertHistoryLogFormRef) {
this.$refs.insertHistoryLogFormRef.clearValidate();
}
},
openInsertHistoryLogDialog(row = null) {
if (!this.historyLogAnchorOptions.length || !this.historyLogNodeOptions.length || !this.historyLogUserOptions.length) {
this.$message.warning('当前流程缺少可补录的参考记录、节点或承办人员');
return;
}
this.resetInsertHistoryLogForm({
anchor_log_id: row?.id || this.historyLogAnchorOptions[0]?.id || '',
});
this.isShowInsertHistoryLog = true;
},
openEditLogTimeDialog(row) {
this.timeId = row.id;
this.selectedDateType = 'created_at';
this.selectedDateTime = row.created_at;
this.isShowTime = true;
},
async handleDeleteFlowLog(row) {
try {
await this.$confirm(`确认删除这条流转记录吗?删除后会重新整理排序。`, '提示', {
type: 'warning',
closeOnClickModal: false,
});
} catch (err) {
return;
}
try {
await deleteFlowLog({ id: row.id });
this.$message.success('删除成功');
await this.getConfig();
} catch (err) {
console.error(err);
}
},
async submitInsertHistoryLog() {
if (this.insertHistoryLogSubmitting) return;
try {
await this.$refs.insertHistoryLogFormRef.validate();
} catch (err) {
return;
}
this.insertHistoryLogSubmitting = true;
try {
await insertHistoryLog({
flow_id: Number(this.$route.query.flow_id),
anchor_log_id: Number(this.insertHistoryLogForm.anchor_log_id),
insert_position: this.insertHistoryLogForm.insert_position,
flow_node_id: Number(this.insertHistoryLogForm.flow_node_id),
user_id: Number(this.insertHistoryLogForm.user_id),
created_at: this.insertHistoryLogForm.created_at,
status: Number(this.insertHistoryLogForm.status),
remark: this.insertHistoryLogForm.remark || '',
reason: this.insertHistoryLogForm.status === -1 ? this.insertHistoryLogForm.reason : '',
});
this.$message.success('插入流转记录成功');
this.isShowInsertHistoryLog = false;
await this.getConfig();
} catch (err) {
console.error(err);
} finally {
this.insertHistoryLogSubmitting = false;
}
},
// urldefault_json
handleDefaultJSON() {
console.log("123")
@ -839,7 +1048,7 @@ export default {
async cellDblclickEvent({ row, column }) {
// if(this.$store.state.user.username !== 'admin') return
if(!this.$store.state.user.roles.includes("全局流程监管")) return
if (!this.canManageFlowLog) return
if(column.field === 'created_at' || column.field === 'updated_at') {
this.timeId = row.id
this.selectedDateType = column.field
@ -878,6 +1087,63 @@ export default {
},
},
computed: {
canManageFlowLog() {
const globalRoles = this.$store.state.user.roles || [];
const moduleRoles = this.$store.state.user.moduleRoles?.oa || [];
const adminId = Number(this.$store.state.user.adminId);
const username = this.$store.state.user.username;
return adminId === 1
|| username === 'admin'
|| globalRoles.includes('全局流程监管')
|| moduleRoles.includes('全局流程监管');
},
historyLogAnchorOptions() {
return (this.config.logs || []).map((log) => ({
id: log.id,
label: `${log.node?.name || '节点已调整'} / ${log.user?.name || '未知人员'} / ${this.$moment(log.created_at).format('YYYY-MM-DD HH:mm:ss')}`,
}));
},
historyLogNodeOptions() {
const nodeMap = new Map();
(this.config.logs || []).forEach((log) => {
if (log.flow_node_id && log.node?.name && !nodeMap.has(log.flow_node_id)) {
nodeMap.set(log.flow_node_id, {
id: log.flow_node_id,
name: log.node.name,
});
}
});
return Array.from(nodeMap.values());
},
historyLogUserOptions() {
const userMap = new Map();
(this.config.logs || []).forEach((log) => {
if (log.user?.id && log.user?.name && !userMap.has(log.user.id)) {
userMap.set(log.user.id, {
id: log.user.id,
name: log.user.name,
});
}
});
return Array.from(userMap.values());
},
insertHistoryLogRules() {
return {
insert_position: [{ required: true, message: '请选择插入位置', trigger: 'change' }],
anchor_log_id: [{ required: true, message: '请选择参考记录', trigger: 'change' }],
flow_node_id: [{ required: true, message: '请选择节点名称', trigger: 'change' }],
user_id: [{ required: true, message: '请选择承办人员', trigger: 'change' }],
created_at: [{ required: true, message: '请选择流转时间', trigger: 'change' }],
status: [{ required: true, message: '请选择办理状态', trigger: 'change' }],
reason: [{ validator: (rule, value, callback) => {
if (this.insertHistoryLogForm.status !== -1 || (value && String(value).trim())) {
callback();
return;
}
callback(new Error('请输入退回原因'));
}, trigger: 'blur' }],
};
},
device() {
return this.$store.state.app.device;
},

Loading…
Cancel
Save