🐞 fix: 修改一些小问题
This commit is contained in:
@@ -29,4 +29,12 @@ public class HrmFlowInstanceBo extends BaseEntity {
|
||||
private Long startUserId;
|
||||
|
||||
private String remark;
|
||||
|
||||
private String startTime;
|
||||
|
||||
private String endTime;
|
||||
|
||||
private String hours;
|
||||
|
||||
private String bizTitle;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"jsbarcode": "^3.12.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"jspdf": "^2.5.2",
|
||||
"pdfjs-dist": "^3.6.172",
|
||||
"konva": "^10.0.2",
|
||||
"mqtt": "^5.13.3",
|
||||
"nprogress": "0.2.0",
|
||||
|
||||
@@ -54,7 +54,7 @@ export function transferFlowTask(taskId, data) {
|
||||
return request({
|
||||
url: `/hrm/flow/task/${taskId}/transfer`,
|
||||
method: 'post',
|
||||
data
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本" prop="version">
|
||||
<el-input-number v-model="form.version" :min="1" :step="1" controls-position="right" style="width: 100%" />
|
||||
<el-input-number v-model="form.version" :min="1" :step="1" control="false" style="width: 100%" />
|
||||
<div class="hint-text">同一业务可存在多版本,建议先从 v1 开始</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用" prop="enabled">
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
>
|
||||
<el-table-column label="申请类型" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="getTypeTagType(scope.row.procDefKey)">{{ getTypeText(scope.row.procDefKey) }}</el-tag>
|
||||
<el-tag :type="getTypeTagType(scope.row.bizType)">{{ getTypeText(scope.row.bizType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请人" min-width="120">
|
||||
@@ -96,7 +96,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" prop="status" min-width="110">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusType(scope.row.procStatus)">{{ statusText(scope.row.procStatus) }}</el-tag>
|
||||
<el-tag :type="statusType(scope.row.status)">{{ statusText(scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请时间" prop="createTime" min-width="160">
|
||||
@@ -202,12 +202,12 @@ export default {
|
||||
return '-'
|
||||
},
|
||||
statusText(status) {
|
||||
const map = { pending: '审批中', draft: '草稿', approved: '已通过', rejected: '已驳回', finished: '已完成' }
|
||||
const map = { running: '审批中', draft: '草稿', approved: '已通过', rejected: '已驳回', finished: '已完成' }
|
||||
return map[status] || status || '-'
|
||||
},
|
||||
statusType(status) {
|
||||
if (!status) return 'info'
|
||||
const map = { pending: 'warning', draft: 'info', approved: 'success', rejected: 'danger', finished: 'success' }
|
||||
const map = { running: 'warning', draft: 'info', approved: 'success', rejected: 'danger', finished: 'success' }
|
||||
return map[status] || 'info'
|
||||
},
|
||||
formatDate(val) {
|
||||
@@ -244,11 +244,11 @@ export default {
|
||||
}
|
||||
},
|
||||
goDetail(row) {
|
||||
if (!row || !row.businessKey) {
|
||||
if (!row || !row.bizId || !row.bizType) {
|
||||
this.$message.warning('缺少businessKey,无法打开详情')
|
||||
return
|
||||
}
|
||||
const [type, bizId] = row.businessKey.split(':')
|
||||
const { bizId, bizType: type } = row
|
||||
if (!bizId) {
|
||||
this.$message.warning('businessKey格式不正确,无法解析业务ID')
|
||||
return
|
||||
|
||||
@@ -173,8 +173,8 @@
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">提交</div></div>
|
||||
<template v-for="(n, idx) in flowNodes">
|
||||
<div :key="`line-${n.nodeId || idx}`" class="line"></div>
|
||||
<div :key="`node-${n.nodeId || idx}`" class="flow-step">
|
||||
<div class="line"></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot" :class="{ success: idx === flowNodes.length - 1 }"></div>
|
||||
<div class="txt">{{ nodePreviewText(n, idx) }}</div>
|
||||
</div>
|
||||
@@ -223,7 +223,7 @@ export default {
|
||||
flowLoading: false,
|
||||
flowTpl: null,
|
||||
flowNodes: [],
|
||||
approverMode: 'template',
|
||||
approverMode: 'manual',
|
||||
availableTpls: [],
|
||||
tplId: null,
|
||||
assigneeUserId: null,
|
||||
|
||||
@@ -139,8 +139,8 @@
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">提交</div></div>
|
||||
<template v-for="(n, idx) in flowNodes">
|
||||
<div :key="`line-${n.nodeId || idx}`" class="line"></div>
|
||||
<div :key="`node-${n.nodeId || idx}`" class="flow-step">
|
||||
<div class="line"></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot" :class="{ success: idx === flowNodes.length - 1 }"></div>
|
||||
<div class="txt">{{ nodePreviewText(n, idx) }}</div>
|
||||
</div>
|
||||
@@ -190,7 +190,7 @@ export default {
|
||||
flowLoading: false,
|
||||
flowTpl: null,
|
||||
flowNodes: [],
|
||||
approverMode: 'template',
|
||||
approverMode: 'manual',
|
||||
availableTpls: [],
|
||||
tplId: null,
|
||||
assigneeUserId: null,
|
||||
|
||||
@@ -169,8 +169,8 @@
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">提交</div></div>
|
||||
<template v-for="(n, idx) in flowNodes">
|
||||
<div :key="`line-${n.nodeId || idx}`" class="line"></div>
|
||||
<div :key="`node-${n.nodeId || idx}`" class="flow-step">
|
||||
<div class="line"></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot" :class="{ success: idx === flowNodes.length - 1 }"></div>
|
||||
<div class="txt">{{ nodePreviewText(n, idx) }}</div>
|
||||
</div>
|
||||
@@ -221,7 +221,7 @@ export default {
|
||||
flowLoading: false,
|
||||
flowTpl: null,
|
||||
flowNodes: [],
|
||||
approverMode: 'template',
|
||||
approverMode: 'manual',
|
||||
availableTpls: [],
|
||||
tplId: null,
|
||||
assigneeUserId: null,
|
||||
|
||||
@@ -29,15 +29,8 @@
|
||||
<el-row :gutter="14">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="出差类型" prop="travelType">
|
||||
<el-select
|
||||
v-model="form.travelType"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
clearable
|
||||
placeholder="选择或输入(如:客户拜访/项目支持/培训学习)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-select v-model="form.travelType" filterable allow-create default-first-option clearable
|
||||
placeholder="选择或输入(如:客户拜访/项目支持/培训学习)" style="width: 100%">
|
||||
<el-option v-for="t in travelTypeOptions" :key="t" :label="t" :value="t" />
|
||||
</el-select>
|
||||
<div class="hint-text">优先选择;若公司类型未配置,可直接输入</div>
|
||||
@@ -49,12 +42,14 @@
|
||||
<el-row :gutter="14">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker v-model="form.startTime" type="datetime" placeholder="请选择开始时间" style="width: 100%" :picker-options="pickerOptions" />
|
||||
<el-date-picker v-model="form.startTime" type="datetime" placeholder="请选择开始时间" style="width: 100%"
|
||||
:picker-options="pickerOptions" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<el-date-picker v-model="form.endTime" type="datetime" placeholder="请选择结束时间" style="width: 100%" :picker-options="pickerOptions" />
|
||||
<el-date-picker v-model="form.endTime" type="datetime" placeholder="请选择结束时间" style="width: 100%"
|
||||
:picker-options="pickerOptions" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -66,17 +61,13 @@
|
||||
|
||||
<div class="block-title">出差说明</div>
|
||||
<el-form-item label="事由" prop="reason">
|
||||
<el-input v-model="form.reason" type="textarea" :rows="4" placeholder="请说明出差目的、任务目标、预期成果等" show-word-limit maxlength="200" />
|
||||
<el-input v-model="form.reason" type="textarea" :rows="4" placeholder="请说明出差目的、任务目标、预期成果等" show-word-limit
|
||||
maxlength="200" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="交通/住宿/行程附件" prop="accessoryApplyIds">
|
||||
<file-upload
|
||||
v-model="form.accessoryApplyIds"
|
||||
:limit="8"
|
||||
:file-size="50"
|
||||
:file-type="['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']"
|
||||
multiple
|
||||
/>
|
||||
<file-upload v-model="form.accessoryApplyIds" :limit="8" :file-size="50"
|
||||
:file-type="['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']" multiple />
|
||||
<div class="hint-text">上传机票、酒店、行程单等(pdf/jpg/png/doc/docx),便于审批与后续报销</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -93,21 +84,10 @@
|
||||
<div class="approve-row">
|
||||
<div class="k">流程模板</div>
|
||||
<div class="v">
|
||||
<el-select
|
||||
v-model="tplId"
|
||||
size="small"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择流程模板"
|
||||
style="width: 360px"
|
||||
@change="onTplChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="t in availableTpls"
|
||||
:key="t.tplId"
|
||||
:label="`${t.tplName}${t.version ? ' (v' + t.version + ')' : ''}`"
|
||||
:value="t.tplId"
|
||||
/>
|
||||
<el-select v-model="tplId" size="small" clearable filterable placeholder="请选择流程模板"
|
||||
style="width: 360px" @change="onTplChange">
|
||||
<el-option v-for="t in availableTpls" :key="t.tplId"
|
||||
:label="`${t.tplName}${t.version ? ' (v' + t.version + ')' : ''}`" :value="t.tplId" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,13 +110,8 @@
|
||||
</div>
|
||||
|
||||
<el-form-item label="回执附件(可选)" prop="accessoryReceiptIds">
|
||||
<file-upload
|
||||
v-model="form.accessoryReceiptIds"
|
||||
:limit="8"
|
||||
:file-size="50"
|
||||
:file-type="['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']"
|
||||
multiple
|
||||
/>
|
||||
<file-upload v-model="form.accessoryReceiptIds" :limit="8" :file-size="50"
|
||||
:file-type="['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']" multiple />
|
||||
<div class="hint-text">可选:上传回执、发票、盖章回单等(审核/归档使用)</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -170,7 +145,8 @@
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="可选:补充说明、特殊要求等" show-word-limit maxlength="200" />
|
||||
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="可选:补充说明、特殊要求等" show-word-limit
|
||||
maxlength="200" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 提交流程提示:按“真实节点配置 / 手动一次性审批”预览 -->
|
||||
@@ -189,12 +165,18 @@
|
||||
<!-- 模板模式 -->
|
||||
<div v-if="approverMode === 'template'">
|
||||
<div v-if="flowNodes && flowNodes.length" class="flow-steps">
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">填写申请</div></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot"></div>
|
||||
<div class="txt">填写申请</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">提交</div></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot"></div>
|
||||
<div class="txt">提交</div>
|
||||
</div>
|
||||
<template v-for="(n, idx) in flowNodes">
|
||||
<div :key="`line-${n.nodeId || idx}`" class="line"></div>
|
||||
<div :key="`node-${n.nodeId || idx}`" class="flow-step">
|
||||
<div class="line"></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot" :class="{ success: idx === flowNodes.length - 1 }"></div>
|
||||
<div class="txt">{{ nodePreviewText(n, idx) }}</div>
|
||||
</div>
|
||||
@@ -207,11 +189,20 @@
|
||||
|
||||
<!-- 手动审批模式 -->
|
||||
<div v-else class="flow-steps">
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">填写申请</div></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot"></div>
|
||||
<div class="txt">填写申请</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot"></div><div class="txt">提交审批({{ assigneeUserName || '请选择' }})</div></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot"></div>
|
||||
<div class="txt">提交审批({{ assigneeUserName || '请选择' }})</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="flow-step"><div class="dot success"></div><div class="txt">审批结束</div></div>
|
||||
<div class="flow-step">
|
||||
<div class="dot success"></div>
|
||||
<div class="txt">审批结束</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -248,7 +239,7 @@ export default {
|
||||
flowLoading: false,
|
||||
flowTpl: null,
|
||||
flowNodes: [],
|
||||
approverMode: 'template',
|
||||
approverMode: 'manual',
|
||||
availableTpls: [],
|
||||
tplId: null,
|
||||
assigneeUserId: null,
|
||||
@@ -440,6 +431,7 @@ export default {
|
||||
padding: 16px 20px 32px;
|
||||
background: #f8f9fb;
|
||||
}
|
||||
|
||||
.form-card {
|
||||
max-width: 980px;
|
||||
margin: 0 auto;
|
||||
@@ -447,6 +439,7 @@ export default {
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -454,11 +447,16 @@ export default {
|
||||
font-weight: 700;
|
||||
color: #2b2f36;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.metal-form { padding-right: 8px; }
|
||||
|
||||
.metal-form {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.block-title {
|
||||
margin: 20px 0 12px;
|
||||
padding-left: 10px;
|
||||
@@ -466,12 +464,14 @@ export default {
|
||||
color: #2f3440;
|
||||
border-left: 3px solid #9aa3b2;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
color: #8a8f99;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.form-summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -483,20 +483,57 @@ export default {
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
|
||||
}
|
||||
.summary-title { font-size: 16px; font-weight: 800; color: #2b2f36; }
|
||||
.summary-sub { margin-top: 4px; font-size: 12px; color: #8a8f99; }
|
||||
.summary-right { display: flex; gap: 16px; }
|
||||
.summary-item .k { font-size: 12px; color: #8a8f99; }
|
||||
.summary-item .v { margin-top: 2px; font-weight: 700; color: #2b2f36; }
|
||||
|
||||
.summary-title {
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
color: #2b2f36;
|
||||
}
|
||||
|
||||
.summary-sub {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #8a8f99;
|
||||
}
|
||||
|
||||
.summary-right {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.summary-item .k {
|
||||
font-size: 12px;
|
||||
color: #8a8f99;
|
||||
}
|
||||
|
||||
.summary-item .v {
|
||||
margin-top: 2px;
|
||||
font-weight: 700;
|
||||
color: #2b2f36;
|
||||
}
|
||||
|
||||
.approve-mode {
|
||||
padding: 12px;
|
||||
border: 1px solid #e6e8ed;
|
||||
border-radius: 10px;
|
||||
background: #fcfdff;
|
||||
}
|
||||
.approve-panel { margin-top: 12px; }
|
||||
.approve-row { display: flex; align-items: center; gap: 12px; }
|
||||
.approve-row .k { font-size: 14px; color: #606266; }
|
||||
|
||||
.approve-panel {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.approve-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.approve-row .k {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.flow-preview {
|
||||
margin-top: 20px;
|
||||
padding: 12px;
|
||||
@@ -504,8 +541,18 @@ export default {
|
||||
border-radius: 10px;
|
||||
background: #fcfdff;
|
||||
}
|
||||
.flow-title { font-weight: 800; color: #2b2f36; }
|
||||
.flow-sub { margin-top: 4px; font-size: 12px; color: #8a8f99; }
|
||||
|
||||
.flow-title {
|
||||
font-weight: 800;
|
||||
color: #2b2f36;
|
||||
}
|
||||
|
||||
.flow-sub {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #8a8f99;
|
||||
}
|
||||
|
||||
.flow-steps {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
@@ -513,6 +560,7 @@ export default {
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flow-step {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -522,17 +570,40 @@ export default {
|
||||
border: 1px solid #e6e8ed;
|
||||
background: #fff;
|
||||
}
|
||||
.flow-step .dot { width: 8px; height: 8px; border-radius: 50%; background: #9aa3b2; }
|
||||
.flow-step .dot.success { background: #67c23a; }
|
||||
.flow-step .txt { font-size: 12px; color: #2b2f36; font-weight: 600; }
|
||||
.flow-steps .line { width: 26px; height: 1px; background: #e6e8ed; }
|
||||
|
||||
.flow-step .dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #9aa3b2;
|
||||
}
|
||||
|
||||
.flow-step .dot.success {
|
||||
background: #67c23a;
|
||||
}
|
||||
|
||||
.flow-step .txt {
|
||||
font-size: 12px;
|
||||
color: #2b2f36;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.flow-steps .line {
|
||||
width: 26px;
|
||||
height: 1px;
|
||||
background: #e6e8ed;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.summary-right { display: none; }
|
||||
.summary-right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user