Files
xgy-oa/klp-ui/src/views/wms/seal/seal.vue
2026-03-18 16:23:54 +08:00

340 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="request-page">
<el-row :gutter="20">
<el-col :span="8">
<el-card class="form-card" shadow="never">
<div slot="header" class="card-header">
<span>用印申请</span>
</div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" size="small" class="metal-form">
<div class="form-summary">
<div class="summary-left">
<div class="summary-title">发起用印</div>
<div class="summary-sub">请完善信息后提交系统会推送部门负责人审批</div>
</div>
<div class="summary-right">
<div class="summary-item">
<div class="k">申请人</div>
<div class="v">{{ currentApplicantText }}</div>
</div>
<div class="summary-item">
<div class="k">用印类型</div>
<div class="v">{{ form.sealType || '-' }}</div>
</div>
</div>
</div>
<el-form-item label="审批部门" prop="deptId">
<el-select v-model="form.deptId" placeholder="请选择审批部门" filterable @change="onDeptChange" style="width: 100%">
<el-option
v-for="item in deptOptions"
:key="item.deptId"
:label="item.deptName + (item.leaderNickName ? '(负责人:' + item.leaderNickName + '' : '(无负责人)')"
:value="item.deptId"
/>
</el-select>
<div class="hint-text">系统将根据部门负责人自动创建审批任务</div>
</el-form-item>
<el-form-item label="用印类型" prop="sealType">
<el-select
v-model="form.sealType"
filterable
allow-create
default-first-option
clearable
placeholder="选择或输入用印类型"
style="width: 100%"
>
<el-option
v-for="dictItem in (dict.type.hrm_stamp_image || [])"
:key="dictItem.value"
:label="dictItem.label"
:value="dictItem.label"
/>
</el-select>
<div class="hint-text">优先从字典选择若字典未配置可直接输入</div>
</el-form-item>
<div class="block-title">用途与材料</div>
<el-form-item label="用途说明" prop="purpose">
<el-input v-model="form.purpose" type="textarea" :rows="4" placeholder="请说明用印用途、对象、份数等" show-word-limit maxlength="200" />
</el-form-item>
<el-form-item label="待盖章PDF" prop="applyFileIds">
<file-upload
v-model="form.applyFileIds"
:limit="1"
:file-size="50"
:file-type="['pdf']"
/>
<div class="hint-text">仅支持 PDF单个文件不超过 50MB</div>
</el-form-item>
<el-form-item label="盖章页码" prop="pageNo" v-if="form.applyFileIds">
<el-input-number
v-model="form.pageNo"
:min="1"
:max="999"
controls-position="right"
placeholder="请输入需要盖章的页码从第1页开始"
style="width: 100%"
/>
<div class="hint-text">请输入需要盖章的页码从第1页开始计数</div>
</el-form-item>
<el-form-item label="需要回执" prop="receiptRequired">
<el-switch v-model="form.receiptRequired" :active-value="1" :inactive-value="0" />
<div class="hint-text">开启后盖章完成通常需要回传回执文件</div>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="可选:补充说明" show-word-limit maxlength="200" />
</el-form-item>
<div class="form-actions">
<el-button @click="$router.back()">取消</el-button>
<el-button type="primary" :loading="submitting" @click="submit">提交申请</el-button>
</div>
</el-form>
</el-card>
</el-col>
<el-col :span="16">
<el-card class="list-card" shadow="never">
<div slot="header" class="card-header">
<span>我的用印申请</span>
<div class="actions">
<el-button size="mini" icon="el-icon-refresh" @click="getList">刷新</el-button>
</div>
</div>
<el-table v-loading="listLoading" :data="sealList" border>
<el-table-column label="状态" align="center" width="100">
<template slot-scope="scope">
<el-tag :type="statusType(scope.row.status)">{{ statusText(scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="用印类型" align="center" prop="sealType" />
<el-table-column label="用途说明" align="center" prop="purpose" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" @click="goDetail(scope.row)">查看</el-button>
<el-button v-if="canPreviewReceipt(scope.row)" size="mini" type="text" @click="previewReceipt(scope.row)">预览</el-button>
<el-button v-if="canPreviewReceipt(scope.row)" size="mini" type="text" @click="downloadReceipt(scope.row)">下载</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import { addSealReq, listSealReq } from '@/api/wms/seal'
import { listDept } from '@/api/wms/dept'
import FileUpload from '@/components/FileUpload'
export default {
name: 'WmsSealRequest',
dicts: ['hrm_stamp_image'],
components: { FileUpload },
data() {
return {
submitting: false,
listLoading: false,
deptOptions: [],
sealList: [],
total: 0,
queryParams: {
pageNum: 1,
pageSize: 10,
createBy: this.$store.getters.name
},
form: {
empId: this.$store.getters.id,
deptId: '',
sealType: '',
purpose: '',
applyFileIds: '',
pageNo: 1,
receiptRequired: 0,
remark: ''
},
rules: {
deptId: [{ required: true, message: '请选择审批部门', trigger: 'change' }],
sealType: [{ required: true, message: '请选择/输入用印类型', trigger: 'change' }],
purpose: [{ required: true, message: '请填写用途说明', trigger: 'blur' }],
applyFileIds: [{ required: true, message: '请上传 PDF 附件', trigger: 'change' }],
pageNo: [{ required: true, message: '请输入盖章页码', trigger: 'blur' }],
receiptRequired: [{ required: true, message: '请选择是否需要回执', trigger: 'change' }]
}
}
},
computed: {
currentApplicantText() {
const user = this.$store?.state?.user || {}
return user.nickName || user.userName || '当前用户'
}
},
created() {
this.loadDeptList()
this.getList()
},
methods: {
async loadDeptList() {
try {
const res = await listDept()
this.deptOptions = res.data || []
} catch (e) {
this.deptOptions = []
}
},
onDeptChange() {},
statusText(status) {
const map = { running: '审批中', draft: '草稿', approved: '已通过', rejected: '已驳回', canceled: '已撤销', pending: '待审批' }
return map[status] || status || '-'
},
statusType(status) {
const map = { running: 'warning', draft: 'info', approved: 'success', rejected: 'danger', canceled: 'info', pending: 'warning' }
return map[status] || 'info'
},
getList() {
this.listLoading = true
listSealReq(this.queryParams)
.then(res => {
this.sealList = res.rows || []
this.total = res.total || 0
})
.finally(() => {
this.listLoading = false
})
},
goDetail(row) {
this.$router.push({ path: '/job/sealDetail', query: { bizId: row.bizId } })
},
canPreviewReceipt(row) {
return row.status === 'approved' && row.receiptFileIds
},
previewReceipt(row) {
if (row.receiptFileIds) {
window.open(row.receiptFileIds, '_blank')
}
},
downloadReceipt(row) {
if (row.receiptFileIds) {
window.open(row.receiptFileIds, '_blank')
}
},
async submit() {
try {
await this.$refs.formRef.validate()
this.submitting = true
let remark = this.form.remark || ''
if (this.form.pageNo) {
remark = remark ? `${remark}\n[盖章页码:第${this.form.pageNo}页]` : `[盖章页码:第${this.form.pageNo}页]`
}
const payload = {
empId: this.form.empId,
deptId: this.form.deptId,
sealType: this.form.sealType,
purpose: this.form.purpose,
applyFileIds: this.form.applyFileIds,
receiptRequired: this.form.receiptRequired,
remark,
status: 'pending'
}
await addSealReq(payload)
this.$message.success('提交成功')
this.getList()
} finally {
this.submitting = false
}
}
}
}
</script>
<style lang="scss" scoped>
.request-page {
padding: 16px 20px 32px;
background: transparent;
}
.form-card {
max-width: 980px;
margin: 0 auto;
border: 1px solid #eef0f4;
border-radius: 10px;
background: #ffffff;
box-shadow: none;
}
.list-card {
border: 1px solid #eef0f4;
border-radius: 10px;
box-shadow: none;
background: #ffffff;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 600;
color: #2b2f36;
}
.actions {
display: flex;
gap: 8px;
}
.metal-form { padding-right: 8px; }
.block-title {
margin: 18px 0 10px;
padding-left: 10px;
font-weight: 600;
color: #2f3440;
border-left: 2px solid #cbd1db;
}
.hint-text {
margin-top: 6px;
font-size: 12px;
color: #8a8f99;
line-height: 1.4;
}
.form-summary {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding: 12px 12px;
margin-bottom: 12px;
border: 1px solid #eef0f4;
border-radius: 10px;
background: transparent;
}
.summary-title { font-size: 15px; font-weight: 700; 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: 600; color: #2b2f36; }
.form-actions {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
}
@media (max-width: 1200px) {
.summary-right { display: none; }
}
</style>