Merge branch 'developer' of ssh://code.cyweb.top:30033/scj/zhxy/v3/cloud-ui into developer
This commit is contained in:
@@ -128,3 +128,8 @@ const resetQuery = () => {
|
||||
queryRef.value.resetFields();
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
:deep(.el-table__body tr td) {
|
||||
text-align: left !important;
|
||||
}
|
||||
</style>
|
||||
@@ -13,16 +13,21 @@
|
||||
<el-form-item class="role-form-item">
|
||||
<el-radio-group v-model="radio" class="role-radio-group" @change="handleChangeRole">
|
||||
<template v-for="(roles, groupName) in allRoleGroups" :key="groupName">
|
||||
<div class="role-group">
|
||||
<el-divider>{{ groupName }}</el-divider>
|
||||
<el-radio-button
|
||||
v-for="item in roles"
|
||||
:key="item.roleCode"
|
||||
:label="item.roleCode"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</el-radio-button>
|
||||
</div>
|
||||
<el-card class="role-group-card" shadow="hover">
|
||||
<template #header>
|
||||
<span class="group-name">{{ groupName }}</span>
|
||||
</template>
|
||||
<div class="role-group">
|
||||
<el-radio-button
|
||||
v-for="item in roles"
|
||||
:key="item.roleCode"
|
||||
:label="item.roleCode"
|
||||
size="small"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</el-radio-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -121,31 +126,12 @@ defineExpose({
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.role-group {
|
||||
width: 100%;
|
||||
flex: 0 0 100%;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 12px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.group-name {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.role-radio-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
|
||||
/* 每个分组内按钮可换行,分组之间不重叠 */
|
||||
:deep(.el-radio-button) {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -153,9 +139,35 @@ defineExpose({
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid var(--el-border-color) !important;
|
||||
margin-left: 0 !important;
|
||||
line-height: 1.3;
|
||||
}
|
||||
:deep(.el-radio-button.is-active .el-radio-button__inner) {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.role-group-card {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
|
||||
:deep(.el-card__header) {
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
:deep(.el-card__body) {
|
||||
padding: 6px 12px 8px;
|
||||
}
|
||||
}
|
||||
.role-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px 8px;
|
||||
}
|
||||
.group-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
</style>
|
||||
@@ -46,7 +46,8 @@
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
type="primary"
|
||||
@click="formDialogRef.openDialog('add')">
|
||||
@click="formDialogRef.openDialog('add')"
|
||||
v-auth="'purchase_purchasingagent_add'">
|
||||
新增
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
|
||||
@@ -91,14 +92,16 @@
|
||||
<el-button
|
||||
icon="Edit"
|
||||
link
|
||||
type="primary"
|
||||
type="primary"
|
||||
v-auth="'purchase_purchasingagent_edit'"
|
||||
@click="formDialogRef.openDialog('edit', scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="Delete"
|
||||
link
|
||||
type="danger"
|
||||
type="danger"
|
||||
v-auth="'purchase_purchasingagent_del'"
|
||||
@click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
type="primary"
|
||||
type="primary"
|
||||
v-auth="'purchase_purchasingcategory_add'"
|
||||
@click="formDialogRef.openDialog('add')">
|
||||
新增
|
||||
</el-button>
|
||||
@@ -65,14 +66,16 @@
|
||||
<el-button
|
||||
icon="Edit"
|
||||
link
|
||||
type="primary"
|
||||
type="primary"
|
||||
v-auth="'purchase_purchasingcategory_edit'"
|
||||
@click="formDialogRef.openDialog('edit', scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="Delete"
|
||||
link
|
||||
type="danger"
|
||||
type="danger"
|
||||
v-auth="'purchase_purchasingcategory_del'"
|
||||
@click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-table :data="records" stripe v-loading="loading" max-height="400">
|
||||
<el-table-column prop="operateTypeDesc" label="操作类型" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getOperateTypeStyle(scope.row.operateType)">
|
||||
{{ scope.row.operateTypeDesc }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operateRoleDesc" label="操作角色" width="100" />
|
||||
<el-table-column prop="operateByName" label="操作人" width="100" />
|
||||
<el-table-column prop="currentVersion" label="文件版本" width="80" align="center" />
|
||||
<el-table-column prop="remark" label="批注意见" min-width="200" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ scope.row.remark || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operateTime" label="操作时间" width="160" />
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { getAuditRecords } from '/@/api/finance/purchasingdoc'
|
||||
|
||||
const props = defineProps<{
|
||||
applyId: number | string
|
||||
}>()
|
||||
|
||||
const records = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
|
||||
const loadRecords = async () => {
|
||||
if (!props.applyId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getAuditRecords(props.applyId)
|
||||
records.value = res.data || []
|
||||
} catch (e) {
|
||||
records.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
loadRecords()
|
||||
}
|
||||
|
||||
const getOperateTypeStyle = (type: string) => {
|
||||
const styleMap: Record<string, string> = {
|
||||
'UPLOAD': 'primary',
|
||||
'CONFIRM': 'success',
|
||||
'RETURN': 'warning',
|
||||
'COMPLETE': 'success'
|
||||
}
|
||||
return styleMap[type] || 'info'
|
||||
}
|
||||
|
||||
watch(() => props.applyId, () => {
|
||||
loadRecords()
|
||||
}, { immediate: true })
|
||||
|
||||
defineExpose({ refresh })
|
||||
</script>
|
||||
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="采购文件审核"
|
||||
width="900px"
|
||||
destroy-on-close
|
||||
@close="handleClose">
|
||||
<el-tabs v-model="activeTab">
|
||||
<!-- 项目信息 -->
|
||||
<el-tab-pane label="项目信息" name="info">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="采购编号">{{ applyInfo.purchaseNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="项目名称">{{ applyInfo.projectName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="需求部门">{{ applyInfo.deptName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="预算金额">{{ applyInfo.budget ? Number(applyInfo.budget).toLocaleString() + '元' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="招标代理">{{ applyInfo.agentName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核状态">
|
||||
<el-tag :type="getStatusType(applyInfo.docAuditStatus)">
|
||||
{{ getStatusLabel(applyInfo.docAuditStatus) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 采购需求文件 -->
|
||||
<el-tab-pane label="采购需求文件" name="requirement">
|
||||
<el-table :data="requirementFiles" stripe v-loading="requirementLoading">
|
||||
<el-table-column prop="fileTitle" label="文件名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="fileType" label="文件类型" width="120">
|
||||
<template #default="scope">
|
||||
{{ getFileTypeLabel(scope.row.fileType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="Download" @click="handleDownloadRequirement(scope.row)">
|
||||
下载
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 采购文件 -->
|
||||
<el-tab-pane label="采购文件" name="doc">
|
||||
<div class="doc-header">
|
||||
<el-button v-if="canUpload" type="primary" icon="Upload" @click="handleUpload">
|
||||
{{ applyInfo.docAuditStatus === 'RETURNED' ? '重新上传' : '上传文件' }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="docList" stripe v-loading="docLoading">
|
||||
<el-table-column prop="fileName" label="文件名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="version" label="版本" width="80" align="center" />
|
||||
<el-table-column prop="uploadByName" label="上传人" width="100" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="160" />
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="Download" @click="handleDownloadDoc(scope.row)">
|
||||
下载
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 审核记录 -->
|
||||
<el-tab-pane label="审核记录" name="audit">
|
||||
<AuditRecordList :apply-id="applyInfo.id" ref="auditRecordListRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button v-if="canConfirm" type="success" @click="handleConfirm">确认无误</el-button>
|
||||
<el-button v-if="canReturn" type="warning" @click="handleReturn">退回修改</el-button>
|
||||
<el-button v-if="canComplete" type="primary" @click="handleComplete">确认流程结束</el-button>
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 退回原因弹窗 -->
|
||||
<el-dialog v-model="returnDialogVisible" title="退回原因" width="400px" append-to-body>
|
||||
<el-form>
|
||||
<el-form-item label="退回原因">
|
||||
<el-input v-model="returnRemark" type="textarea" :rows="3" placeholder="请输入退回原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="returnDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitReturn">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, defineAsyncComponent } from 'vue'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { getObj, getApplyFiles } from '/@/api/finance/purchasingrequisition'
|
||||
import { getDocList, uploadDoc, reuploadDoc, confirmDoc, returnDoc, completeDoc, getAvailableActions, getDocDownloadUrl } from '/@/api/finance/purchasingdoc'
|
||||
import other from '/@/utils/other'
|
||||
|
||||
const AuditRecordList = defineAsyncComponent(() => import('./AuditRecordList.vue'));
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
const visible = ref(false)
|
||||
const activeTab = ref('info')
|
||||
const applyInfo = ref<any>({})
|
||||
const requirementFiles = ref<any[]>([])
|
||||
const requirementLoading = ref(false)
|
||||
const docList = ref<any[]>([])
|
||||
const docLoading = ref(false)
|
||||
const auditRecordListRef = ref()
|
||||
const availableActions = ref<string[]>([])
|
||||
|
||||
const returnDialogVisible = ref(false)
|
||||
const returnRemark = ref('')
|
||||
|
||||
const canUpload = computed(() => availableActions.value.includes('upload'))
|
||||
const canConfirm = computed(() => availableActions.value.includes('confirm'))
|
||||
const canReturn = computed(() => availableActions.value.includes('return'))
|
||||
const canComplete = computed(() => availableActions.value.includes('complete'))
|
||||
|
||||
const open = async (row: any) => {
|
||||
visible.value = true
|
||||
activeTab.value = 'info'
|
||||
applyInfo.value = {}
|
||||
requirementFiles.value = []
|
||||
docList.value = []
|
||||
returnRemark.value = ''
|
||||
|
||||
// 加载详情
|
||||
try {
|
||||
const res = await getObj(row.id)
|
||||
applyInfo.value = res.data || res
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '加载项目信息失败')
|
||||
return
|
||||
}
|
||||
|
||||
// 加载可执行操作
|
||||
try {
|
||||
const actionsRes = await getAvailableActions(row.id)
|
||||
availableActions.value = actionsRes.data || []
|
||||
} catch (e) {
|
||||
availableActions.value = []
|
||||
}
|
||||
|
||||
// 加载采购需求文件
|
||||
loadRequirementFiles()
|
||||
// 加载采购文件
|
||||
loadDocList()
|
||||
}
|
||||
|
||||
const loadRequirementFiles = async () => {
|
||||
if (!applyInfo.value.id) return
|
||||
requirementLoading.value = true
|
||||
try {
|
||||
const res = await getApplyFiles(applyInfo.value.id)
|
||||
const files = res.data || res || []
|
||||
// 过滤采购需求文件(fileType=120)
|
||||
requirementFiles.value = files.filter((f: any) => f.fileType === '120')
|
||||
} catch (e) {
|
||||
requirementFiles.value = []
|
||||
} finally {
|
||||
requirementLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadDocList = async () => {
|
||||
if (!applyInfo.value.id) return
|
||||
docLoading.value = true
|
||||
try {
|
||||
const res = await getDocList(applyInfo.value.id)
|
||||
docList.value = res.data || []
|
||||
} catch (e) {
|
||||
docList.value = []
|
||||
} finally {
|
||||
docLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpload = () => {
|
||||
// 触发文件上传
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = '*/*'
|
||||
input.onchange = async (e: any) => {
|
||||
const file = e.target.files[0]
|
||||
if (!file) return
|
||||
// TODO: 实现文件上传到OSS,然后调用上传接口
|
||||
useMessage().info('文件上传功能需要配合OSS实现')
|
||||
}
|
||||
input.click()
|
||||
}
|
||||
|
||||
const handleDownloadRequirement = (row: any) => {
|
||||
if (row.remark) {
|
||||
const url = `/purchase/purchasingfiles/download?fileName=${encodeURIComponent(row.remark)}&fileTitle=${encodeURIComponent(row.fileTitle)}`
|
||||
other.downBlobFile(url, {}, row.fileTitle)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDownloadDoc = (row: any) => {
|
||||
const url = getDocDownloadUrl(row.id)
|
||||
other.downBlobFile(url, {}, row.fileName)
|
||||
}
|
||||
|
||||
const handleConfirm = async () => {
|
||||
try {
|
||||
await useMessageBox().confirm('确定要确认该采购文件无误吗?')
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await confirmDoc({ applyId: applyInfo.value.id })
|
||||
useMessage().success('确认成功')
|
||||
emit('refresh')
|
||||
loadDocList()
|
||||
auditRecordListRef.value?.refresh()
|
||||
// 重新加载可执行操作
|
||||
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||
availableActions.value = actionsRes.data || []
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '确认失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleReturn = () => {
|
||||
returnRemark.value = ''
|
||||
returnDialogVisible.value = true
|
||||
}
|
||||
|
||||
const submitReturn = async () => {
|
||||
try {
|
||||
await returnDoc({ applyId: applyInfo.value.id, remark: returnRemark.value })
|
||||
useMessage().success('退回成功')
|
||||
returnDialogVisible.value = false
|
||||
emit('refresh')
|
||||
loadDocList()
|
||||
auditRecordListRef.value?.refresh()
|
||||
// 重新加载可执行操作
|
||||
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||
availableActions.value = actionsRes.data || []
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '退回失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleComplete = async () => {
|
||||
try {
|
||||
await useMessageBox().confirm('确定要确认流程结束吗?')
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await completeDoc(applyInfo.value.id)
|
||||
useMessage().success('流程已结束')
|
||||
emit('refresh')
|
||||
loadDocList()
|
||||
auditRecordListRef.value?.refresh()
|
||||
// 重新加载可执行操作
|
||||
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||
availableActions.value = actionsRes.data || []
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const getStatusType = (status: string) => {
|
||||
const typeMap: Record<string, string> = {
|
||||
'PENDING_UPLOAD': 'info',
|
||||
'ASSET_REVIEWING': 'warning',
|
||||
'DEPT_REVIEWING': 'warning',
|
||||
'AUDIT_REVIEWING': 'warning',
|
||||
'ASSET_CONFIRMING': 'primary',
|
||||
'COMPLETED': 'success',
|
||||
'RETURNED': 'danger'
|
||||
}
|
||||
return typeMap[status] || 'info'
|
||||
}
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
const labelMap: Record<string, string> = {
|
||||
'PENDING_UPLOAD': '待上传',
|
||||
'ASSET_REVIEWING': '资产管理处审核中',
|
||||
'DEPT_REVIEWING': '需求部门审核中',
|
||||
'AUDIT_REVIEWING': '内审部门审核中',
|
||||
'ASSET_CONFIRMING': '资产管理处确认中',
|
||||
'COMPLETED': '已完成',
|
||||
'RETURNED': '已退回'
|
||||
}
|
||||
return labelMap[status] || '-'
|
||||
}
|
||||
|
||||
const getFileTypeLabel = (type: string) => {
|
||||
const labelMap: Record<string, string> = {
|
||||
'120': '采购需求表',
|
||||
'130': '采购文件'
|
||||
}
|
||||
return labelMap[type] || type
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.doc-header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
193
src/views/finance/purchasingrequisition/docAudit/index.vue
Normal file
193
src/views/finance/purchasingrequisition/docAudit/index.vue
Normal file
@@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<div class="modern-page-container">
|
||||
<div class="page-wrapper">
|
||||
<!-- 搜索表单卡片 -->
|
||||
<el-card v-show="showSearch" class="search-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><Search /></el-icon>
|
||||
筛选条件
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.queryForm" ref="searchFormRef" :inline="true" @keyup.enter="getDataList" class="search-form">
|
||||
<el-form-item label="采购编号" prop="purchaseNo">
|
||||
<el-input
|
||||
v-model="state.queryForm.purchaseNo"
|
||||
placeholder="请输入采购编号"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input
|
||||
v-model="state.queryForm.projectName"
|
||||
placeholder="请输入项目名称"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审核状态" prop="docAuditStatus">
|
||||
<el-select
|
||||
v-model="state.queryForm.docAuditStatus"
|
||||
placeholder="请选择审核状态"
|
||||
clearable
|
||||
style="width: 200px">
|
||||
<el-option label="待上传" value="PENDING_UPLOAD" />
|
||||
<el-option label="资产管理处审核中" value="ASSET_REVIEWING" />
|
||||
<el-option label="需求部门审核中" value="DEPT_REVIEWING" />
|
||||
<el-option label="内审部门审核中" value="AUDIT_REVIEWING" />
|
||||
<el-option label="资产管理处确认中" value="ASSET_CONFIRMING" />
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已退回" value="RETURNED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 内容卡片 -->
|
||||
<el-card class="content-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><DocumentChecked /></el-icon>
|
||||
采购文件审核
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
stripe
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
class="modern-table">
|
||||
<el-table-column type="index" label="序号" width="70" align="center">
|
||||
<template #header>
|
||||
<el-icon><List /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchaseNo" label="采购编号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="projectName" label="项目名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="deptName" label="需求部门" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="budget" label="预算金额(元)" width="120" align="right">
|
||||
<template #default="scope">
|
||||
{{ scope.row.budget ? Number(scope.row.budget).toLocaleString() : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="docAuditStatus" label="审核状态" width="140" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusType(scope.row.docAuditStatus)">
|
||||
{{ getStatusLabel(scope.row.docAuditStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="currentDocVersion" label="当前版本" width="100" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.currentDocVersion || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" width="120">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="View" @click="handleAudit(scope.row)">
|
||||
审核
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-if="state.pagination && state.pagination.total && state.pagination.total > 0"
|
||||
:total="state.pagination.total"
|
||||
:current="state.pagination.current"
|
||||
:size="state.pagination.size"
|
||||
@sizeChange="sizeChangeHandle"
|
||||
@currentChange="currentChangeHandle"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 审核弹窗 -->
|
||||
<DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingDocAudit">
|
||||
import { ref, reactive, defineAsyncComponent, onMounted } from 'vue'
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { getPage } from "/@/api/finance/purchasingrequisition";
|
||||
import { Search, DocumentChecked, List } from '@element-plus/icons-vue'
|
||||
|
||||
// 引入组件
|
||||
const DocAuditDialog = defineAsyncComponent(() => import('./DocAuditDialog.vue'));
|
||||
|
||||
const docAuditDialogRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const showSearch = ref(true)
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
pageList: getPage,
|
||||
queryForm: {
|
||||
purchaseNo: '',
|
||||
projectName: '',
|
||||
docAuditStatus: '',
|
||||
},
|
||||
createdIsNeed: true
|
||||
});
|
||||
|
||||
const { getDataList, tableStyle, sizeChangeHandle, currentChangeHandle } = useTable(state);
|
||||
|
||||
const handleReset = () => {
|
||||
searchFormRef.value?.resetFields();
|
||||
getDataList();
|
||||
};
|
||||
|
||||
const getStatusType = (status: string) => {
|
||||
const typeMap: Record<string, string> = {
|
||||
'PENDING_UPLOAD': 'info',
|
||||
'ASSET_REVIEWING': 'warning',
|
||||
'DEPT_REVIEWING': 'warning',
|
||||
'AUDIT_REVIEWING': 'warning',
|
||||
'ASSET_CONFIRMING': 'primary',
|
||||
'COMPLETED': 'success',
|
||||
'RETURNED': 'danger'
|
||||
};
|
||||
return typeMap[status] || 'info';
|
||||
};
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
const labelMap: Record<string, string> = {
|
||||
'PENDING_UPLOAD': '待上传',
|
||||
'ASSET_REVIEWING': '资产管理处审核中',
|
||||
'DEPT_REVIEWING': '需求部门审核中',
|
||||
'AUDIT_REVIEWING': '内审部门审核中',
|
||||
'ASSET_CONFIRMING': '资产管理处确认中',
|
||||
'COMPLETED': '已完成',
|
||||
'RETURNED': '已退回'
|
||||
};
|
||||
return labelMap[status] || '-';
|
||||
};
|
||||
|
||||
const handleAudit = (row: any) => {
|
||||
docAuditDialogRef.value?.open(row);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 页面加载时的初始化逻辑
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/@/assets/styles/modern-page.scss';
|
||||
</style>
|
||||
@@ -235,52 +235,7 @@
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fileFlowStatus" label="文件审批状态" width="110" align="center">
|
||||
<template #header>
|
||||
<el-icon><DocumentChecked /></el-icon>
|
||||
<span style="margin-left: 4px">文件审批状态</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.fileFlowInstId">
|
||||
<el-tooltip content="点击查看审批过程" placement="top">
|
||||
<el-tag
|
||||
v-if="scope.row.fileFlowStatus === '-2'"
|
||||
type="info"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">撤回</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.fileFlowStatus === '-1'"
|
||||
type="warning"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">暂存</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.fileFlowStatus === '0'"
|
||||
type="primary"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">运行中</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.fileFlowStatus === '1'"
|
||||
type="success"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">完成</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.fileFlowStatus === '2'"
|
||||
type="danger"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">作废</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.fileFlowStatus === '3'"
|
||||
type="info"
|
||||
class="status-tag-clickable"
|
||||
@click="handleShowFileFlowComment(scope.row)">终止</el-tag>
|
||||
<span v-else class="status-tag-clickable" @click="handleShowFileFlowComment(scope.row)">-</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span style="color: #909399;">—</span>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" fixed="right" width="150">
|
||||
<template #default="scope">
|
||||
<div class="op-cell">
|
||||
@@ -391,6 +346,9 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 采购文件审核弹窗 -->
|
||||
<DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -412,6 +370,7 @@ const ImplementForm = defineAsyncComponent(() => import('./implementForm.vue'));
|
||||
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'));
|
||||
const PurchasingAcceptModal = defineAsyncComponent(() => import('./accept/PurchasingAcceptModal.vue'));
|
||||
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
|
||||
const DocAuditDialog = defineAsyncComponent(() => import('./docAudit/DocAuditDialog.vue'));
|
||||
|
||||
// 字典数据和品目树数据
|
||||
const dictData = ref({
|
||||
@@ -431,6 +390,7 @@ const formDialogRef = ref()
|
||||
const acceptModalRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const showSearch = ref(true)
|
||||
const docAuditDialogRef = ref()
|
||||
/** 审批过程弹窗:是否显示、当前行对应的流程 job(供 Comment 组件用)、类型(申请单/文件) */
|
||||
const showFlowComment = ref(false)
|
||||
const currFlowJob = ref<{ id?: number; flowInstId?: number } | null>(null)
|
||||
@@ -599,6 +559,11 @@ const handleImplement = (row: any) => {
|
||||
implementFormRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
/** 打开采购文件审核 */
|
||||
const handleDocAudit = (row: any) => {
|
||||
docAuditDialogRef.value?.open(row);
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除当前行
|
||||
* @param row - 当前行数据
|
||||
@@ -611,7 +576,7 @@ const handleDelete = async (row: any) => {
|
||||
}
|
||||
|
||||
try {
|
||||
await delObj(row.id);
|
||||
await delObj({id:row.id});
|
||||
useMessage().success('删除成功');
|
||||
getDataList();
|
||||
} catch (err: any) {
|
||||
@@ -692,6 +657,12 @@ const getActionMenuItems = (row: any) => {
|
||||
icon: Collection,
|
||||
visible: () => row?.purchaseMode === '2' || (row?.purchaseMode === '0' && row?.purchaseType === '4'),
|
||||
},
|
||||
{
|
||||
command: 'docAudit',
|
||||
label: '采购文件审核',
|
||||
icon: DocumentChecked,
|
||||
visible: () => row?.implementType === '2' && row?.agentId,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@@ -725,6 +696,9 @@ const handleMoreCommand = (command: string, row: any) => {
|
||||
case 'assignAgent':
|
||||
openAssignAgentDialog(row);
|
||||
break;
|
||||
case 'docAudit':
|
||||
handleDocAudit(row);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
271
src/views/finance/purchasingtemplate/index.vue
Normal file
271
src/views/finance/purchasingtemplate/index.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<template>
|
||||
<div class="modern-page-container">
|
||||
<div class="page-wrapper">
|
||||
<el-card class="content-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="FolderAdd"
|
||||
@click="openUploadDialog()"
|
||||
v-auth="'purchase_template_add'">
|
||||
新增模板
|
||||
</el-button>
|
||||
<el-alert type="info" :closable="false" class="mb3 mt-3" show-icon>
|
||||
此处模版中的模版编码对应用户端下载模版匹配,请勿随意修改或删除。正常情况下如有发生模版变化,重新上传即可。如有新增模版,请联系管理员进行处理。
|
||||
</el-alert>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="tableData" v-loading="loading" stripe class="modern-table">
|
||||
<el-table-column type="index" label="序号" width="70" align="center">
|
||||
<template #header>
|
||||
<el-icon><List /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="templateTitle" label="模板类型名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="templateType" label="模板类型编码" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="templateName" label="模板名称" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column prop="updateTime" label="更新时间" width="180" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="260" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Download"
|
||||
@click="handleDownload(row)"
|
||||
v-auth="'purchase_template_view'">
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="UploadFilled"
|
||||
@click="openUploadDialog(row)"
|
||||
v-auth="'purchase_template_add'">
|
||||
重新上传
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Edit"
|
||||
@click="openEditDialog(row)"
|
||||
v-auth="'purchase_template_add'">
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="uploadDialogVisible" title="上传模板" width="450px" destroy-on-close>
|
||||
<el-form :model="uploadForm" label-width="100px">
|
||||
<el-form-item label="模板类型编码" required>
|
||||
<el-input
|
||||
v-model="uploadForm.templateType"
|
||||
placeholder="例如: business_negotiation, inquiry"
|
||||
:disabled="!!uploadForm.lockType"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板类型名称">
|
||||
<el-input
|
||||
v-model="uploadForm.templateTitle"
|
||||
placeholder="例如: 部门采购询价模版"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板文件" required>
|
||||
<el-upload
|
||||
class="upload-block"
|
||||
:auto-upload="false"
|
||||
:limit="1"
|
||||
:file-list="fileList"
|
||||
:on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove"
|
||||
>
|
||||
<el-button type="primary" icon="UploadFilled">选择文件</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">支持 doc、docx 等 Word 模板文件,上传后前端下载将使用该文件。</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="uploadDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" :loading="uploading" @click="handleUploadConfirm">上 传</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="editDialogVisible" title="编辑模板" width="420px" destroy-on-close>
|
||||
<el-form :model="editForm" label-width="100px">
|
||||
<el-form-item label="模板类型编码">
|
||||
<el-input v-model="editForm.templateType" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板类型名称" required>
|
||||
<el-input v-model="editForm.templateTitle" placeholder="请输入模板类型名称" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="editDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" :loading="editing" @click="handleEditConfirm">保 存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingTemplateManage">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { Document, List, UploadFilled, Download, Edit } from '@element-plus/icons-vue';
|
||||
import { listTemplates, uploadTemplate, getTemplateDownloadUrl, updateTemplateTitle } from '/@/api/finance/purchasingtemplate';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
|
||||
const loading = ref(false);
|
||||
const tableData = ref<any[]>([]);
|
||||
|
||||
const uploadDialogVisible = ref(false);
|
||||
const uploading = ref(false);
|
||||
const uploadForm = reactive<{
|
||||
templateType: string;
|
||||
templateTitle: string;
|
||||
lockType?: boolean;
|
||||
}>({
|
||||
templateType: '',
|
||||
templateTitle: '',
|
||||
lockType: false,
|
||||
});
|
||||
const editDialogVisible = ref(false);
|
||||
const editing = ref(false);
|
||||
const editForm = reactive<{
|
||||
id: number | null;
|
||||
templateType: string;
|
||||
templateTitle: string;
|
||||
}>({
|
||||
id: null,
|
||||
templateType: '',
|
||||
templateTitle: '',
|
||||
});
|
||||
|
||||
const fileList = ref<any[]>([]);
|
||||
const currentFile = ref<File | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await listTemplates();
|
||||
tableData.value = (res && res.data) || [];
|
||||
} catch (e) {
|
||||
tableData.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(fetchData);
|
||||
|
||||
const openUploadDialog = (row?: any) => {
|
||||
uploadDialogVisible.value = true;
|
||||
uploadForm.templateType = row?.templateType || '';
|
||||
uploadForm.templateTitle = row?.templateTitle || '';
|
||||
uploadForm.lockType = !!row?.templateType;
|
||||
fileList.value = [];
|
||||
currentFile.value = null;
|
||||
};
|
||||
|
||||
const handleFileChange = (file: any, files: any[]) => {
|
||||
fileList.value = files.slice(-1);
|
||||
currentFile.value = file.raw || null;
|
||||
};
|
||||
|
||||
const handleFileRemove = () => {
|
||||
fileList.value = [];
|
||||
currentFile.value = null;
|
||||
};
|
||||
|
||||
const handleUploadConfirm = async () => {
|
||||
if (!uploadForm.templateType || !uploadForm.templateType.trim()) {
|
||||
useMessage().error('请填写模板类型编码');
|
||||
return;
|
||||
}
|
||||
if (!currentFile.value) {
|
||||
useMessage().error('请选择要上传的模板文件');
|
||||
return;
|
||||
}
|
||||
uploading.value = true;
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('type', uploadForm.templateType.trim());
|
||||
if (uploadForm.templateTitle && uploadForm.templateTitle.trim()) {
|
||||
formData.append('title', uploadForm.templateTitle.trim());
|
||||
}
|
||||
formData.append('file', currentFile.value);
|
||||
await uploadTemplate(formData);
|
||||
useMessage().success('模板上传成功');
|
||||
uploadDialogVisible.value = false;
|
||||
await fetchData();
|
||||
} catch (e) {
|
||||
useMessage().error('模板上传失败');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async (row: any) => {
|
||||
if (!row?.templateType) {
|
||||
useMessage().error('缺少模板类型编码');
|
||||
return;
|
||||
}
|
||||
const url = getTemplateDownloadUrl(row.templateType);
|
||||
const fileName = row.templateName || row.templateTitle || row.templateType;
|
||||
try {
|
||||
await (window as any).other?.downBlobFile?.(url, {}, fileName) ||
|
||||
// 兼容直接使用工具函数
|
||||
(await import('/@/utils/other')).default.downBlobFile(url, {}, fileName);
|
||||
} catch (e) {
|
||||
// 如果工具函数不可用,则退回 window.open
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
const openEditDialog = (row: any) => {
|
||||
editDialogVisible.value = true;
|
||||
editForm.id = row?.id ?? null;
|
||||
editForm.templateType = row?.templateType || '';
|
||||
editForm.templateTitle = row?.templateTitle || '';
|
||||
};
|
||||
|
||||
const handleEditConfirm = async () => {
|
||||
if (!editForm.id) {
|
||||
useMessage().error('缺少模板ID');
|
||||
return;
|
||||
}
|
||||
if (!editForm.templateTitle || !editForm.templateTitle.trim()) {
|
||||
useMessage().error('请输入模板类型名称');
|
||||
return;
|
||||
}
|
||||
editing.value = true;
|
||||
try {
|
||||
await updateTemplateTitle({
|
||||
id: editForm.id,
|
||||
templateTitle: editForm.templateTitle.trim(),
|
||||
});
|
||||
useMessage().success('保存成功');
|
||||
editDialogVisible.value = false;
|
||||
await fetchData();
|
||||
} catch (e) {
|
||||
useMessage().error('保存失败');
|
||||
} finally {
|
||||
editing.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.upload-block {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><Document /></el-icon>
|
||||
业务分管部门及人员
|
||||
业务分管处室及人员
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
|
||||
182
src/views/purchase/purchasingBusinessLeader/form.vue
Normal file
182
src/views/purchase/purchasingBusinessLeader/form.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="form.id ? '编辑' : '新增'"
|
||||
v-model="visible"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
draggable>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="form"
|
||||
:rules="dataRules"
|
||||
label-width="120px"
|
||||
v-loading="loading">
|
||||
<el-form-item label="选取用户" prop="userId">
|
||||
<org-selector
|
||||
v-model:orgList="userList"
|
||||
type="user"
|
||||
:multiple="false"
|
||||
@update:orgList="handleUserChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
placeholder="选择用户后自动填充"
|
||||
readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户工号" prop="username">
|
||||
<el-input
|
||||
v-model="form.username"
|
||||
placeholder="选择用户后自动填充"
|
||||
readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingBusinessLeaderForm">
|
||||
import { reactive, ref, nextTick } from 'vue'
|
||||
import { getObj, addObj, putObj } from '/@/api/purchase/purchasingBusinessLeader';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import orgSelector from '/@/components/OrgSelector/index.vue';
|
||||
|
||||
// 定义子组件向父组件传值/事件
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
// 定义变量内容
|
||||
const dataFormRef = ref();
|
||||
const userList = ref<any[]>([]);
|
||||
const form = reactive({
|
||||
id: '',
|
||||
userId: '',
|
||||
username: '',
|
||||
name: '',
|
||||
remark: '',
|
||||
});
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const dataRules = ref({
|
||||
userId: [
|
||||
{ required: true, message: '请选取用户', trigger: 'change' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请先选取用户', trigger: 'blur' }
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请先选取用户', trigger: 'blur' }
|
||||
],
|
||||
});
|
||||
|
||||
// 处理用户选择变化
|
||||
const handleUserChange = (list: any[]) => {
|
||||
if (list && list.length > 0) {
|
||||
const user = list[0];
|
||||
form.userId = user.userId || user.id || '';
|
||||
form.username = user.username || user.userName || '';
|
||||
form.name = user.name || user.realName || '';
|
||||
} else {
|
||||
form.userId = '';
|
||||
form.username = '';
|
||||
form.name = '';
|
||||
}
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = async (id?: string) => {
|
||||
visible.value = true;
|
||||
form.id = '';
|
||||
form.userId = '';
|
||||
form.username = '';
|
||||
form.name = '';
|
||||
form.remark = '';
|
||||
userList.value = [];
|
||||
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
if (id) {
|
||||
// 编辑时,先获取详情数据
|
||||
loading.value = true;
|
||||
getObj(id).then((res: any) => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
const data = res.data[0];
|
||||
Object.assign(form, {
|
||||
id: data.id || '',
|
||||
userId: data.userId || '',
|
||||
username: data.username || '',
|
||||
name: data.name || '',
|
||||
remark: data.remark || '',
|
||||
});
|
||||
// 设置用户列表用于回显
|
||||
if (data.userId) {
|
||||
userList.value = [{
|
||||
userId: data.userId,
|
||||
username: data.username,
|
||||
name: data.name,
|
||||
id: data.userId,
|
||||
userName: data.username,
|
||||
realName: data.name,
|
||||
type: 'user',
|
||||
}];
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
}).catch((err: any) => {
|
||||
useMessage().error(err.msg || '获取详情失败');
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 提交
|
||||
const onSubmit = async () => {
|
||||
// 立即设置 loading,防止重复点击
|
||||
if (loading.value) return;
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const valid = await dataFormRef.value.validate().catch(() => {});
|
||||
if (!valid) {
|
||||
loading.value = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (form.id) {
|
||||
await putObj(form);
|
||||
useMessage().success('编辑成功');
|
||||
} else {
|
||||
await addObj(form);
|
||||
useMessage().success('新增成功');
|
||||
}
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || (form.id ? '编辑失败' : '新增失败'));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
240
src/views/purchase/purchasingBusinessLeader/index.vue
Normal file
240
src/views/purchase/purchasingBusinessLeader/index.vue
Normal file
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<div class="modern-page-container">
|
||||
<div class="page-wrapper">
|
||||
<!-- 搜索表单卡片 -->
|
||||
<el-card v-show="showSearch" class="search-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><Search /></el-icon>
|
||||
筛选条件
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList" class="search-form">
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input
|
||||
v-model="state.queryForm.name"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户工号" prop="username">
|
||||
<el-input
|
||||
v-model="state.queryForm.username"
|
||||
placeholder="请输入用户工号"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 内容卡片 -->
|
||||
<el-card class="content-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><User /></el-icon>
|
||||
业务分管校领导
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
type="primary"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'purchasing_bus_leader_add'">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
v-auth="'purchasing_bus_leader_del'"
|
||||
@click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'purchasing_bus_leader_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10"
|
||||
@queryTable="getDataList" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
stripe
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle"
|
||||
class="modern-table">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="70" align="center">
|
||||
<template #header>
|
||||
<el-icon><List /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><User /></el-icon>
|
||||
<span style="margin-left: 4px">姓名</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" label="用户工号" min-width="150" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<span style="margin-left: 4px">用户工号</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="300" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<span style="margin-left: 4px">备注</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="180" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><Clock /></el-icon>
|
||||
<span style="margin-left: 4px">创建时间</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="Delete"
|
||||
link
|
||||
type="danger"
|
||||
v-auth="'purchasing_bus_leader_del'"
|
||||
@click="handleDelete([scope.row.id])">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-if="state.pagination"
|
||||
v-show="state.pagination.total && state.pagination.total > 0"
|
||||
:total="state.pagination.total"
|
||||
:current="state.pagination.current"
|
||||
:size="state.pagination.size"
|
||||
@size-change="sizeChangeHandle"
|
||||
@current-change="currentChangeHandle"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增表单对话框 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingBusinessLeader">
|
||||
import { ref, reactive, defineAsyncComponent } from 'vue'
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/purchase/purchasingBusinessLeader";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { List, User, UserFilled, EditPen, Clock, Search } from '@element-plus/icons-vue'
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const tableRef = ref()
|
||||
const formDialogRef = ref()
|
||||
const queryRef = ref()
|
||||
const showSearch = ref(true)
|
||||
const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
/**
|
||||
* 定义响应式表格数据
|
||||
*/
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
pageList: fetchList,
|
||||
queryForm: {
|
||||
name: '',
|
||||
username: '',
|
||||
},
|
||||
createdIsNeed: true
|
||||
});
|
||||
|
||||
/**
|
||||
* 使用 useTable 定义表格相关操作
|
||||
*/
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state);
|
||||
|
||||
/**
|
||||
* 重置搜索表单
|
||||
*/
|
||||
const resetQuery = () => {
|
||||
queryRef.value?.resetFields();
|
||||
selectObjs.value = [];
|
||||
multiple.value = true;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出Excel文件
|
||||
*/
|
||||
const exportExcel = () => {
|
||||
downBlobFile(
|
||||
'/purchase/purchasingBusinessLeader/export',
|
||||
Object.assign(state.queryForm, { ids: selectObjs.value }),
|
||||
'purchasingBusinessLeader.xlsx'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 表格多选事件处理
|
||||
* @param objs 选中的数据行
|
||||
*/
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除当前行
|
||||
* @param ids - 要删除的ID数组
|
||||
*/
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('确定要删除该记录吗?');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
useMessage().success('删除成功');
|
||||
getDataList();
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || '删除失败');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/@/assets/styles/modern-page.scss';
|
||||
</style>
|
||||
228
src/views/purchase/purchasingPurchaseManager/form.vue
Normal file
228
src/views/purchase/purchasingPurchaseManager/form.vue
Normal file
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="form.id ? '编辑' : '新增'"
|
||||
v-model="visible"
|
||||
width="700px"
|
||||
:close-on-click-modal="false"
|
||||
draggable>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="form"
|
||||
:rules="dataRules"
|
||||
label-width="120px"
|
||||
v-loading="loading">
|
||||
<!-- 新增时先选取用户,选后自动带出姓名、工号 -->
|
||||
<el-form-item label="选取用户" prop="userId">
|
||||
<org-selector
|
||||
v-model:orgList="userList"
|
||||
type="user"
|
||||
:multiple="false"
|
||||
@update:orgList="handleUserChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
placeholder="选择用户后自动填充"
|
||||
readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户工号" prop="username">
|
||||
<el-input
|
||||
v-model="form.username"
|
||||
placeholder="选择用户后自动填充"
|
||||
readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="部门" prop="deptId">
|
||||
<org-selector
|
||||
v-model:orgList="deptList"
|
||||
type="dept"
|
||||
:multiple="false"
|
||||
@update:orgList="handleDeptChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input
|
||||
v-model="form.deptName"
|
||||
placeholder="选择部门后自动填充"
|
||||
readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingPurchaseManagerForm">
|
||||
import { reactive, ref, nextTick } from 'vue'
|
||||
import { getObj, addObj, putObj } from '/@/api/purchase/purchasingPurchaseManager';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import orgSelector from '/@/components/OrgSelector/index.vue';
|
||||
|
||||
// 定义子组件向父组件传值/事件
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
// 定义变量内容
|
||||
const dataFormRef = ref();
|
||||
const deptList = ref<any[]>([]);
|
||||
const userList = ref<any[]>([]);
|
||||
const form = reactive({
|
||||
id: '',
|
||||
deptId: '',
|
||||
deptName: '',
|
||||
userId: '',
|
||||
username: '',
|
||||
name: '',
|
||||
remark: '',
|
||||
});
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const dataRules = ref({
|
||||
userId: [
|
||||
{ required: true, message: '请选取用户(分管负责人)', trigger: 'change' }
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: '请选择部门', trigger: 'change' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请先选取用户', trigger: 'blur' }
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请先选取用户', trigger: 'blur' }
|
||||
],
|
||||
});
|
||||
|
||||
// 处理部门选择变化
|
||||
const handleDeptChange = (list: any[]) => {
|
||||
if (list && list.length > 0) {
|
||||
const dept = list[0];
|
||||
form.deptId = dept.deptId || dept.id || '';
|
||||
form.deptName = dept.name || dept.deptName || '';
|
||||
} else {
|
||||
form.deptId = '';
|
||||
form.deptName = '';
|
||||
}
|
||||
};
|
||||
|
||||
// 处理用户选择变化(选取用户后自动带出姓名、工号)
|
||||
const handleUserChange = (list: any[]) => {
|
||||
if (list && list.length > 0) {
|
||||
const user = list[0];
|
||||
form.userId = user.userId || user.id || '';
|
||||
form.username = user.username || user.userName || '';
|
||||
form.name = user.name || user.realName || '';
|
||||
} else {
|
||||
form.userId = '';
|
||||
form.username = '';
|
||||
form.name = '';
|
||||
}
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = async (id?: string) => {
|
||||
visible.value = true;
|
||||
form.id = '';
|
||||
form.deptId = '';
|
||||
form.deptName = '';
|
||||
form.userId = '';
|
||||
form.username = '';
|
||||
form.name = '';
|
||||
form.remark = '';
|
||||
deptList.value = [];
|
||||
userList.value = [];
|
||||
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
if (id) {
|
||||
// 编辑时,先获取详情数据
|
||||
loading.value = true;
|
||||
getObj(id).then((res: any) => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
const data = res.data[0];
|
||||
Object.assign(form, {
|
||||
id: data.id || '',
|
||||
deptId: data.deptId || '',
|
||||
deptName: data.deptName || '',
|
||||
userId: data.userId || '',
|
||||
username: data.username || '',
|
||||
name: data.name || '',
|
||||
remark: data.remark || '',
|
||||
});
|
||||
// 设置部门列表用于回显
|
||||
if (data.deptId) {
|
||||
deptList.value = [{
|
||||
deptId: data.deptId,
|
||||
name: data.deptName,
|
||||
id: data.deptId,
|
||||
type: 'dept',
|
||||
}];
|
||||
}
|
||||
// 设置用户列表用于回显
|
||||
if (data.userId) {
|
||||
userList.value = [{
|
||||
userId: data.userId,
|
||||
username: data.username,
|
||||
name: data.name,
|
||||
id: data.userId,
|
||||
userName: data.username,
|
||||
realName: data.name,
|
||||
type: 'user',
|
||||
}];
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
}).catch((err: any) => {
|
||||
useMessage().error(err.msg || '获取详情失败');
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 提交
|
||||
const onSubmit = async () => {
|
||||
// 立即设置 loading,防止重复点击
|
||||
if (loading.value) return;
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const valid = await dataFormRef.value.validate().catch(() => {});
|
||||
if (!valid) {
|
||||
loading.value = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (form.id) {
|
||||
await putObj(form);
|
||||
useMessage().success('编辑成功');
|
||||
} else {
|
||||
await addObj(form);
|
||||
useMessage().success('新增成功');
|
||||
}
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || (form.id ? '编辑失败' : '新增失败'));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
254
src/views/purchase/purchasingPurchaseManager/index.vue
Normal file
254
src/views/purchase/purchasingPurchaseManager/index.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<div class="modern-page-container">
|
||||
<div class="page-wrapper">
|
||||
<!-- 搜索表单卡片 -->
|
||||
<el-card v-show="showSearch" class="search-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><Search /></el-icon>
|
||||
筛选条件
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList" class="search-form">
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input
|
||||
v-model="state.queryForm.deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户工号" prop="username">
|
||||
<el-input
|
||||
v-model="state.queryForm.username"
|
||||
placeholder="请输入用户工号"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input
|
||||
v-model="state.queryForm.name"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 内容卡片 -->
|
||||
<el-card class="content-card" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><Document /></el-icon>
|
||||
采购分管领导
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
type="primary"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'purchase_manager_add'">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
v-auth="'purchase_manager_del'"
|
||||
@click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'purchase_manager_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10"
|
||||
@queryTable="getDataList" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
stripe
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle"
|
||||
class="modern-table">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="70" align="center">
|
||||
<template #header>
|
||||
<el-icon><List /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="deptName" label="部门名称" min-width="200" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><OfficeBuilding /></el-icon>
|
||||
<span style="margin-left: 4px">部门名称</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><User /></el-icon>
|
||||
<span style="margin-left: 4px">姓名</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" label="用户工号" min-width="150" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<span style="margin-left: 4px">用户工号</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="300" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<span style="margin-left: 4px">备注</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="180" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><Clock /></el-icon>
|
||||
<span style="margin-left: 4px">创建时间</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="Delete"
|
||||
link
|
||||
type="danger"
|
||||
v-auth="'purchase_manager_del'"
|
||||
@click="handleDelete([scope.row.id])">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-if="state.pagination"
|
||||
v-show="state.pagination.total && state.pagination.total > 0"
|
||||
:total="state.pagination.total"
|
||||
:current="state.pagination.current"
|
||||
:size="state.pagination.size"
|
||||
@size-change="sizeChangeHandle"
|
||||
@current-change="currentChangeHandle"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增表单对话框 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingPurchaseManager">
|
||||
import { ref, reactive, defineAsyncComponent } from 'vue'
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/purchase/purchasingPurchaseManager";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { List, Document, User, UserFilled, EditPen, Clock, Search, OfficeBuilding } from '@element-plus/icons-vue'
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const tableRef = ref()
|
||||
const formDialogRef = ref()
|
||||
const queryRef = ref()
|
||||
const showSearch = ref(true)
|
||||
const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
/**
|
||||
* 定义响应式表格数据
|
||||
*/
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
pageList: fetchList,
|
||||
queryForm: {
|
||||
deptName: '',
|
||||
username: '',
|
||||
name: '',
|
||||
},
|
||||
createdIsNeed: true
|
||||
});
|
||||
|
||||
/**
|
||||
* 使用 useTable 定义表格相关操作
|
||||
*/
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state);
|
||||
|
||||
/**
|
||||
* 重置搜索表单
|
||||
*/
|
||||
const resetQuery = () => {
|
||||
queryRef.value?.resetFields();
|
||||
selectObjs.value = [];
|
||||
multiple.value = true;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出Excel文件
|
||||
*/
|
||||
const exportExcel = () => {
|
||||
downBlobFile(
|
||||
'/purchasingPurchaseManager/export',
|
||||
Object.assign(state.queryForm, { ids: selectObjs.value }),
|
||||
'purchasingPurchaseManager.xlsx'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 表格多选事件处理
|
||||
* @param objs 选中的数据行
|
||||
*/
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除当前行
|
||||
* @param ids - 要删除的ID数组
|
||||
*/
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('确定要删除该记录吗?');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
useMessage().success('删除成功');
|
||||
getDataList();
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || '删除失败');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/@/assets/styles/modern-page.scss';
|
||||
</style>
|
||||
@@ -39,13 +39,15 @@
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon class="title-icon"><User /></el-icon>
|
||||
校领导(党委)管理
|
||||
校党委人员
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
type="primary"
|
||||
@click="formDialogRef.openDialog('add')">
|
||||
@click="formDialogRef.openDialog('add')"
|
||||
v-auth="'purchase_purchasingSchoolLeader_add'"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
|
||||
@@ -103,7 +105,8 @@
|
||||
<el-button
|
||||
icon="Delete"
|
||||
link
|
||||
type="danger"
|
||||
type="danger"
|
||||
v-auth="'purchase_purchasingSchoolLeader_del'"
|
||||
@click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
|
||||
@@ -61,7 +61,8 @@ const uploadRef = ref<{ clearFiles?: () => void }>()
|
||||
const titleMap: Record<string, string> = {
|
||||
R10001: '计划专业导入',
|
||||
R10002: '地区分数导入',
|
||||
R10003: '中招平台数据导入'
|
||||
R10003: '中招平台数据导入',
|
||||
R10004: '学校维护导入',
|
||||
}
|
||||
// 方法
|
||||
const init = (type: any) => {
|
||||
|
||||
@@ -177,7 +177,7 @@ const remoteTeacherByQuery = (query: string) => {
|
||||
serialNumberList.value = []
|
||||
if (query !== '') {
|
||||
setTimeout(() => {
|
||||
getList({ groupId: dataForm.groupId, name: query }).then((response: any) => {
|
||||
getList({ groupId: dataForm.groupId, serialNumber: query }).then((response: any) => {
|
||||
serialNumberList.value = response.data
|
||||
})
|
||||
}, 200)
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
type="warning"
|
||||
link
|
||||
icon="Download"
|
||||
@click="handleExport(scope.row.batchCode, scope.row.groupId)"
|
||||
:loading="btnLoading"
|
||||
@click="handleExport(scope.row)"
|
||||
>
|
||||
导出模拟结果
|
||||
</el-button>
|
||||
@@ -132,6 +133,7 @@ import { BasicTableProps, useTable } from '/@/hooks/table'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { getList } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { delObj, fetchList } from '/@/api/recruit/recruitImitateAdjustBatch'
|
||||
import {exportAdjustExcel} from "/@/api/recruit/recruitfile"
|
||||
|
||||
const TableForm = defineAsyncComponent(() => import('./detaiform.vue'))
|
||||
const MnTable = defineAsyncComponent(() => import('./mnTable.vue'))
|
||||
@@ -204,17 +206,14 @@ const showTable = (batchNo: string, groupId: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
const btnLoading=ref(false)
|
||||
// 导出模拟结果
|
||||
const handleExport = async (code: string, gid: string) => {
|
||||
try {
|
||||
await downBlobFile(
|
||||
'/recruit/recruitImitateAdjustBatch/exportExcel',
|
||||
{ batchNo: code, groupId: gid },
|
||||
'招生模拟统计.xls'
|
||||
)
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '导出失败')
|
||||
}
|
||||
const handleExport = async (data:any) => {
|
||||
btnLoading.value=true
|
||||
exportAdjustExcel(data).then((res:any)=>{
|
||||
messageBox.success('导出后台执行中,请稍后查看下载任务')
|
||||
btnLoading.value=false
|
||||
})
|
||||
}
|
||||
|
||||
// 删除
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
title="模拟列表"
|
||||
:close-on-click-modal="false"
|
||||
v-model="visible"
|
||||
width="80%"
|
||||
width="98%"
|
||||
>
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
@@ -109,6 +109,7 @@
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="200"
|
||||
label="操作">
|
||||
<template #default="scope">
|
||||
<el-button v-if="hasAuth('recruit_recruitImitateAdjustBatch_edit')" type="text" size="small" :icon="Edit" @click="addOrUpdateHandle(scope.row.id)">修改</el-button>
|
||||
|
||||
243
src/views/recruit/recruitPolicyFile/form.vue
Normal file
243
src/views/recruit/recruitPolicyFile/form.vue
Normal file
@@ -0,0 +1,243 @@
|
||||
<template>
|
||||
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
|
||||
:close-on-click-modal="false" draggable>
|
||||
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入标题"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="文件地址" prop="fileUrl">
|
||||
|
||||
<el-upload
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:action="uploadUrl"
|
||||
:file-list="fileList"
|
||||
:on-success="handleUploadSuccess"
|
||||
:accept="'.pdf'"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div style="margin-top: 8px;">
|
||||
<el-tag>仅支持pdf后缀的文件上传</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
|
||||
<!-- <el-upload-->
|
||||
<!-- :action="uploadUrl"-->
|
||||
<!-- class="avatar-uploader"-->
|
||||
<!-- name="file"-->
|
||||
<!-- :headers="headers"-->
|
||||
<!-- :data="uploadData"-->
|
||||
<!-- :file-list="fileList"-->
|
||||
<!-- :before-upload="beforeUpload"-->
|
||||
<!-- :http-request="httpRequest"-->
|
||||
<!-- :limit="1"-->
|
||||
<!-- :accept="['.jpg,.jpeg,.png,.pdf']"-->
|
||||
<!-- :on-success="handleUploadSuccess">-->
|
||||
<!-- <el-button size="small" type="primary">点击上传</el-button>-->
|
||||
<!-- <template #tip>-->
|
||||
<!-- <div style="margin-top: 8px;">-->
|
||||
<!-- <el-tag>仅支持jpg,jpeg,png,pdf后缀的文件上传</el-tag>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-upload>-->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- <el-col :span="12" class="mb20">-->
|
||||
<!-- <el-form-item label="1 资助政策文件" prop="type">-->
|
||||
<!-- <el-input v-model="form.type" placeholder="请输入1 资助政策文件"/>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="RecruitPolicyFileDialog">
|
||||
// ========== 1. 导入语句 ==========
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { getObj, addObj, putObj } from '/@/api/recruit/recruitPolicyFile';
|
||||
import {Plus} from "@element-plus/icons-vue";
|
||||
import {reactive, ref} from "vue";
|
||||
import axios from "axios";
|
||||
import { Session } from '/@/utils/storage'
|
||||
const fileList = ref<any[]>([])
|
||||
|
||||
// ========== 2. 组件定义 ==========
|
||||
// 定义组件事件
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
// ========== 3. 响应式数据定义 ==========
|
||||
// 基础响应式变量
|
||||
const dataFormRef = ref(); // 表单引用
|
||||
const visible = ref(false); // 弹窗显示状态
|
||||
const loading = ref(false); // 加载状态
|
||||
const baseUrl = import.meta.env.VITE_API_URL
|
||||
|
||||
// 表单数据对象
|
||||
const form = reactive({
|
||||
id: '', // 主键
|
||||
fileUrl: '', // 文件地址
|
||||
title: '', // 标题
|
||||
type: '', // 1 资助政策文件
|
||||
});
|
||||
|
||||
const uploadUrl = baseUrl + '/recruit/file/uploadPdf'
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
const uploadData = reactive({})
|
||||
const fileReader = ref<FileReader | null>(null)
|
||||
|
||||
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
const isLt5M = file.size < 10 * 1024 * 1024
|
||||
if (!isLt5M) {
|
||||
useMessage().error('文件大小不能超过10M')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// 通用上传成功回调(单文件 - avatar模式)
|
||||
const handleUploadSuccess = (res:any) => {
|
||||
const fileUrl = res.fileUrl
|
||||
form['fileUrl'] = fileUrl
|
||||
}
|
||||
// ========== 4. 字典数据处理 ==========
|
||||
|
||||
// ========== 5. 表单校验规则 ==========
|
||||
const dataRules = ref({
|
||||
title: [
|
||||
{ required: true, message: '请输入标题', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' },
|
||||
],
|
||||
fileUrl: [
|
||||
{ required: true, message: '请上传文件', trigger: 'blur' },
|
||||
]
|
||||
});
|
||||
|
||||
// ========== 6. 方法定义 ==========
|
||||
// 获取详情数据
|
||||
const getRecruitPolicyFileData = async (id: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const { data } = await getObj({ id: id });
|
||||
// 直接将第一条数据赋值给表单
|
||||
Object.assign(form, data[0]);
|
||||
} catch (error) {
|
||||
useMessage().error('获取数据失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 打开弹窗方法
|
||||
const openDialog = (id: string) => {
|
||||
visible.value = true;
|
||||
form.id = '';
|
||||
|
||||
// 重置表单数据
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
});
|
||||
|
||||
// 获取RecruitPolicyFile信息
|
||||
if (id) {
|
||||
form.id = id;
|
||||
getRecruitPolicyFileData(id);
|
||||
}
|
||||
};
|
||||
|
||||
// 提交表单方法
|
||||
const onSubmit = async () => {
|
||||
loading.value = true; // 防止重复提交
|
||||
|
||||
// 表单校验
|
||||
const valid = await dataFormRef.value.validate().catch(() => {});
|
||||
if (!valid) {
|
||||
loading.value = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据是否有ID判断是新增还是修改
|
||||
form.id ? await putObj(form) : await addObj(form);
|
||||
useMessage().success(form.id ? '修改成功' : '添加成功');
|
||||
visible.value = false;
|
||||
emit('refresh'); // 通知父组件刷新列表
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
// 初始化 FileReader
|
||||
onMounted(() => {
|
||||
if (!window.FileReader) {
|
||||
useMessage().error('您的浏览器不支持 FileReader API!')
|
||||
} else {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
})
|
||||
// ========== 7. 对外暴露 ==========
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//.avatar-uploader {
|
||||
// :deep(.el-upload) {
|
||||
// border: 1px dashed var(--el-border-color);
|
||||
// border-radius: 6px;
|
||||
// cursor: pointer;
|
||||
// position: relative;
|
||||
// overflow: hidden;
|
||||
// transition: var(--el-transition-duration-fast);
|
||||
// width: 148px;
|
||||
// height: 148px;
|
||||
// &:hover {
|
||||
// border-color: var(--el-color-primary);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//.avatar-uploader-icon {
|
||||
// font-size: 28px;
|
||||
// color: #8c939d;
|
||||
// width: 148px;
|
||||
// height: 148px;
|
||||
// line-height: 148px;
|
||||
// text-align: center;
|
||||
//}
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
.avatar {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
232
src/views/recruit/recruitPolicyFile/index.vue
Normal file
232
src/views/recruit/recruitPolicyFile/index.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button
|
||||
icon="folder-add"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'recruit_recruitPolicyFile_add'"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'recruit_recruitPolicyFile_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'recruit_recruitPolicyFile_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10 mr20"
|
||||
style="float: right;"
|
||||
@queryTable="getDataList"
|
||||
/>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格区域 -->
|
||||
<el-table
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column
|
||||
prop="fileUrl"
|
||||
label="文件"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Document"
|
||||
@click="handlePreview(scope.row.fileUrl)"
|
||||
>查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="title"
|
||||
label="标题"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- <el-table-column -->
|
||||
<!-- prop="type" -->
|
||||
<!-- label="1 资助政策文件" -->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- />-->
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'recruit_recruitPolicyFile_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="delete"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'recruit_recruitPolicyFile_del'"
|
||||
@click="handleDelete([scope.row.id])"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
@size-change="sizeChangeHandle"
|
||||
@current-change="currentChangeHandle"
|
||||
v-bind="state.pagination"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增弹窗 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
|
||||
<!-- 导入excel弹窗 (需要在 upms-biz/resources/file 下维护模板) -->
|
||||
<upload-excel
|
||||
ref="excelUploadRef"
|
||||
title="导入"
|
||||
url="/recruit/recruitPolicyFile/import"
|
||||
temp-url="/admin/sys-file/local/file/recruitPolicyFile.xlsx"
|
||||
@refreshDataList="getDataList"
|
||||
/>
|
||||
|
||||
<preview-file v-for="src in imgUrl" :key="src.title" :authSrc="src.url" dialog-title="职称材料" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="systemRecruitPolicyFile">
|
||||
// ========== 导入声明 ==========
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/recruit/recruitPolicyFile";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import {defineAsyncComponent, ref} from "vue";
|
||||
const previewFile = defineAsyncComponent(() => import('/@/components/tools/preview-file.vue'));
|
||||
|
||||
// ========== 组件声明 ==========
|
||||
// 异步加载表单弹窗组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
const baseUrl = import.meta.env.VITE_API_URL
|
||||
|
||||
// ========== 字典数据 ==========
|
||||
|
||||
// ========== 组件引用 ==========
|
||||
const formDialogRef = ref(); // 表单弹窗引用
|
||||
const excelUploadRef = ref(); // Excel上传弹窗引用
|
||||
const queryRef = ref(); // 查询表单引用
|
||||
|
||||
// ========== 响应式数据 ==========
|
||||
const showSearch = ref(true); // 是否显示搜索区域
|
||||
const selectObjs = ref([]) as any; // 表格多选数据
|
||||
const multiple = ref(true); // 是否多选
|
||||
|
||||
// ========== 表格状态 ==========
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {}, // 查询参数
|
||||
pageList: fetchList // 分页查询方法
|
||||
});
|
||||
const imgUrl = ref<Array<{ title: string; url: string }>>([]);
|
||||
|
||||
// ========== Hook引用 ==========
|
||||
// 表格相关Hook
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state);
|
||||
|
||||
// ========== 方法定义 ==========
|
||||
/**
|
||||
* 重置查询条件
|
||||
*/
|
||||
const resetQuery = () => {
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields();
|
||||
// 清空多选
|
||||
selectObjs.value = [];
|
||||
// 重新查询
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出Excel文件
|
||||
*/
|
||||
const exportExcel = () => {
|
||||
downBlobFile(
|
||||
'/recruit/recruitPolicyFile/export',
|
||||
Object.assign(state.queryForm, { ids: selectObjs }),
|
||||
'recruitPolicyFile.xlsx'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 表格多选事件处理
|
||||
* @param objs 选中的数据行
|
||||
*/
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
|
||||
// 预览材料
|
||||
const handlePreview = (url: string) => {
|
||||
imgUrl.value = [];
|
||||
nextTick(() => {
|
||||
imgUrl.value.push({
|
||||
title: '',
|
||||
url: baseUrl+url,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除数据处理
|
||||
* @param ids 要删除的数据ID数组
|
||||
*/
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('此操作将永久删除');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
getDataList();
|
||||
useMessage().success('删除成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
129
src/views/recruit/recruitPreexamPeople/add-form.vue
Normal file
129
src/views/recruit/recruitPreexamPeople/add-form.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="保存审核人员" width="600px" append-to-body @close="handleClose">
|
||||
<el-form :model="{ belongTeacherNos }" label-width="100px">
|
||||
<el-form-item label="选择教师:">
|
||||
<el-select
|
||||
v-model="belongTeacherNos"
|
||||
filterable
|
||||
remote
|
||||
clearable
|
||||
reserve-keyword
|
||||
placeholder="请选择或输入教师姓名"
|
||||
:remote-method="remoteTeacherByQuery"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in teacherList"
|
||||
:key="item.teacherNo"
|
||||
:label="item.realName"
|
||||
:value="item.teacherNo"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="AddExamPeopleForm">
|
||||
import { ref, watch } from 'vue'
|
||||
import {getTeacherInfoCommon} from '/@/api/professional/professionaluser/teacherbase'
|
||||
|
||||
// Props
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
timeRange: string[]
|
||||
}>()
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void
|
||||
(e: 'save', data: { teacherNo: string; startTime: string; endTime: string }): void
|
||||
}>()
|
||||
|
||||
// 弹窗显示状态
|
||||
const dialogVisible = ref(false)
|
||||
const belongTeacherNos = ref('')
|
||||
const teacherList = ref<any[]>([])
|
||||
|
||||
// 监听 visible 变化
|
||||
watch(() => props.visible, (newVal) => {
|
||||
dialogVisible.value = newVal
|
||||
if (newVal) {
|
||||
belongTeacherNos.value = ''
|
||||
teacherList.value = []
|
||||
}
|
||||
})
|
||||
|
||||
// 监听 dialogVisible 变化,同步到父组件
|
||||
watch(dialogVisible, (newVal) => {
|
||||
emit('update:visible', newVal)
|
||||
})
|
||||
|
||||
// 检索教师
|
||||
const remoteTeacherByQuery = (query: string) => {
|
||||
teacherList.value = []
|
||||
if (query !== '') {
|
||||
setTimeout(() => {
|
||||
getTeacherInfoCommon({searchKeywords:query,tied:"0"}).then(response => {
|
||||
teacherList.value = response.data
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭窗口
|
||||
const handleClose = () => {
|
||||
belongTeacherNos.value = ''
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
// 保存
|
||||
const handleSave = () => {
|
||||
if (props.timeRange.length === 0) {
|
||||
emit('save', {
|
||||
teacherNo: belongTeacherNos.value,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
return
|
||||
}
|
||||
emit('save', {
|
||||
teacherNo: belongTeacherNos.value,
|
||||
startTime: props.timeRange[0],
|
||||
endTime: props.timeRange[1]
|
||||
})
|
||||
handleClose()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
225
src/views/recruit/recruitPreexamPeople/index.vue
Normal file
225
src/views/recruit/recruitPreexamPeople/index.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
title="招生审核人员管理"
|
||||
:close-on-click-modal="false"
|
||||
v-model="visible"
|
||||
width="800"
|
||||
:append-to-body="true"
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="dialog-content">
|
||||
<!-- 时间选择器和操作按钮 -->
|
||||
<el-form :inline="true" :model="queryForm">
|
||||
<el-form-item label="审核时间范围:">
|
||||
<el-time-picker
|
||||
is-range
|
||||
v-model="form.time1"
|
||||
format="HH:mm:ss"
|
||||
value-format="HH:mm:ss"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
placeholder="选择时间范围"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="mb15" v-if="hasAuth('recruit_recruitexampeople_add')">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="FolderAdd"
|
||||
@click="handleAdd"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="table-wrapper">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList || []"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
stripe
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
empty-text="暂无数据"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="工号" align="center" prop="teacherNo" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column label="姓名" align="center" prop="teacherName" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="150px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="hasAuth('recruit_recruitexampeople_del')"
|
||||
type="danger"
|
||||
link
|
||||
icon="Delete"
|
||||
@click="handleDel(scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-wrapper">
|
||||
<pagination
|
||||
v-bind="state.pagination"
|
||||
@current-change="currentChangeHandle"
|
||||
@size-change="sizeChangeHandle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 保存审核人员弹窗 -->
|
||||
<add-form
|
||||
v-model:visible="setTeachNoFormVisible"
|
||||
:time-range="form.time1"
|
||||
@save="handleSave"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="recruitexampeople">
|
||||
import { ref, reactive, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { useAuth } from '/@/hooks/auth'
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { addObj, delObj, fetchList } from '/@/api/recruit/recruitPreexamPeople'
|
||||
|
||||
const AddForm = defineAsyncComponent(() => import('./add-form.vue'))
|
||||
const { hasAuth } = useAuth()
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
|
||||
// 弹窗状态
|
||||
const visible = ref(false)
|
||||
const setTeachNoFormVisible = ref(false)
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
time1: [] as string[]
|
||||
})
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive<Record<string, any>>({})
|
||||
|
||||
// 表格状态
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: queryForm,
|
||||
pageList: async (params: any) => {
|
||||
const response = await fetchList(params)
|
||||
return {
|
||||
data: {
|
||||
records: response.data.records || [],
|
||||
total: response.data.total || 0
|
||||
}
|
||||
}
|
||||
},
|
||||
createdIsNeed: false, // 弹窗组件,不在挂载时自动加载数据
|
||||
dataList: [], // 确保 dataList 初始化为空数组
|
||||
loading: false, // 确保 loading 初始化为 false
|
||||
onLoaded: async (state: any) => {
|
||||
// 如果有数据,设置时间范围
|
||||
if (state.dataList && state.dataList.length > 0) {
|
||||
form.time1 = [state.dataList[0].startTime, state.dataList[0].endTime]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 使用 table hook
|
||||
// 注意:useTable 会直接修改传入的 state 对象,所以不需要从返回值中获取 state
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
visible.value = true
|
||||
form.time1 = []
|
||||
// 等待弹窗显示后再加载数据
|
||||
nextTick(() => {
|
||||
getDataList()
|
||||
})
|
||||
}
|
||||
|
||||
// 新增
|
||||
const handleAdd = () => {
|
||||
setTeachNoFormVisible.value = true
|
||||
}
|
||||
|
||||
// 保存审核人员
|
||||
const handleSave = async (data: { teacherNo: string; startTime: string; endTime: string }) => {
|
||||
if (form.time1.length === 0) {
|
||||
message.error('审核时间不能为空')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await addObj({
|
||||
teacherNo: data.teacherNo,
|
||||
startTime: data.startTime,
|
||||
endTime: data.endTime
|
||||
})
|
||||
message.success('添加成功')
|
||||
getDataList()
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '添加失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
const handleDel = async (row: any) => {
|
||||
try {
|
||||
await messageBox.confirm(`是否确认删除工号为${row.teacherNo}的记录?`)
|
||||
await delObj(row.id)
|
||||
message.success('删除成功')
|
||||
getDataList()
|
||||
} catch {
|
||||
// 用户取消
|
||||
}
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
Object.keys(queryForm).forEach(key => {
|
||||
queryForm[key] = ''
|
||||
})
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -79,6 +79,15 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="majorCode" label="专业序号" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="majorName" label="专业名称" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="majorName" label="规范专业名称" align="center" show-overflow-tooltip >
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.standardMajorName">
|
||||
{{ scope.row.standardMajorName+"-"+scope.row.standardMajorTwoName }}
|
||||
</span>
|
||||
<span v-else>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="deptCode" label="学院" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getDeptName(scope.row.deptCode) }}
|
||||
|
||||
@@ -92,7 +92,8 @@
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
<el-button
|
||||
v-auth="'pre_stu_success_export'"
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@@ -102,6 +103,10 @@
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="hasAuth('recruit_preexamPeople_add')" type="primary" plain icon="UserFilled" class="ml10" @click="editExam">
|
||||
审核人员管理
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
@@ -191,6 +196,8 @@
|
||||
:planMajorList="planMajorList"
|
||||
:schoolList="schoolList"
|
||||
/>
|
||||
|
||||
<pre-exam-people-index ref="PreExamPeopleIndexRef"></pre-exam-people-index>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -207,7 +214,11 @@ import { getList } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { listcz } from '/@/api/recruit/recruitstudentplan'
|
||||
import { queryByGroupId as schoolListApi} from '/@/api/recruit/recruitstudentschool'
|
||||
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
|
||||
import {exportPreStuSuccess} from '/@/api/recruit/recruitfile'
|
||||
|
||||
const PreExamPeopleIndex = defineAsyncComponent(() => import('@/views/recruit/recruitPreexamPeople/index.vue'));
|
||||
|
||||
const PreExamPeopleIndexRef=ref()
|
||||
const TableForm = defineAsyncComponent(() => import('./enrolplantemplate-form.vue'))
|
||||
const { hasAuth } = useAuth()
|
||||
// 消息提示 hooks
|
||||
@@ -366,20 +377,30 @@ const resetQuery = () => {
|
||||
|
||||
// 导出
|
||||
const dataExportHandle = async () => {
|
||||
try {
|
||||
exportLoading.value = true
|
||||
await downBlobFile(
|
||||
'/recruit/recruitprestudent/export',
|
||||
queryForm,
|
||||
'预登记导出.xls'
|
||||
)
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '导出失败')
|
||||
} finally {
|
||||
exportLoading.value = true
|
||||
exportPreStuSuccess(queryForm).then((res:any)=>{
|
||||
message.success('导出后台执行中,请稍后查看下载任务')
|
||||
exportLoading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 编辑审核人员
|
||||
const editExam = () => {
|
||||
// 如果组件已经加载,立即初始化
|
||||
if (PreExamPeopleIndexRef.value && typeof PreExamPeopleIndexRef.value.init === 'function') {
|
||||
nextTick(() => {
|
||||
try {
|
||||
PreExamPeopleIndexRef.value.init();
|
||||
} catch (error: any) {
|
||||
message.error('初始化预登记人员弹窗失败:' + (error.message || '未知错误'));
|
||||
}
|
||||
});
|
||||
}
|
||||
// 否则等待 watch 监听器处理
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
@@ -42,13 +42,29 @@
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb15">
|
||||
<el-button
|
||||
v-if="hasAuth('recruit_recruitstudentplangroup_add')"
|
||||
v-if="hasAuth('recruit_recruitstudentschool_add')"
|
||||
type="primary"
|
||||
icon="FolderAdd"
|
||||
@click="addOrUpdateHandle"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
v-auth="'recruit_studentschool_import'"
|
||||
type="primary"
|
||||
plain
|
||||
icon="UploadFilled"
|
||||
@click="handleImportDialog"
|
||||
>导入信息
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasAuth('recruit_schoolhistory_view')"
|
||||
type="plain"
|
||||
icon="View"
|
||||
@click="handleShowHistory"
|
||||
>
|
||||
变更历史
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
@@ -109,6 +125,11 @@
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<table-form ref="addOrUpdateRef" @refreshDataList="getDataList" />
|
||||
<major-group-by-dept-form v-if="majorGroupByDeptVisible" ref="majorGroupByDeptRef" />
|
||||
|
||||
<school-history ref="SchoolHistoryRef"></school-history>
|
||||
|
||||
<import-recruit-info ref="ImportRecruitInfoRef" @refreshDataList="getDataList"></import-recruit-info>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -124,11 +145,16 @@ import { getDeptList } from '/@/api/basic/basicclass'
|
||||
|
||||
const TableForm = defineAsyncComponent(() => import('./detaiform.vue'))
|
||||
const MajorGroupByDeptForm = defineAsyncComponent(() => import('/@/views/recruit/recruitplanmajor/majorGroupByDept.vue'))
|
||||
const ImportRecruitInfo = defineAsyncComponent(() => import('/@/views/recruit/common/import-recruit-info.vue'));
|
||||
const SchoolHistory = defineAsyncComponent(() => import('/@/views/recruit/recruitstudentschool/school-history.vue'))
|
||||
|
||||
const { hasAuth } = useAuth()
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
const ImportRecruitInfoRef=ref<any>();
|
||||
|
||||
const SchoolHistoryRef=ref()
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const searchFormRef = ref()
|
||||
@@ -236,6 +262,14 @@ const resetQuery = () => {
|
||||
getDataList()
|
||||
}
|
||||
|
||||
const handleShowHistory=()=>{
|
||||
SchoolHistoryRef.value?.init()
|
||||
}
|
||||
|
||||
const handleImportDialog = () => {
|
||||
ImportRecruitInfoRef.value?.init("R10004");
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
63
src/views/recruit/recruitstudentschool/school-history.vue
Normal file
63
src/views/recruit/recruitstudentschool/school-history.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" width="80%" title="学校变更历史">
|
||||
<el-table ref="tableRef"
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
stripe
|
||||
row-key="id"
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle">
|
||||
<el-table-column label="学校代码" prop="schoolCode"></el-table-column>
|
||||
<el-table-column label="旧名称" prop="oldName"></el-table-column>
|
||||
<el-table-column label="新名称" prop="newName"></el-table-column>
|
||||
<el-table-column label="变动时间" prop="createTime"></el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-bind="state.pagination"
|
||||
@current-change="currentChangeHandle"
|
||||
@size-change="sizeChangeHandle"
|
||||
/>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useTable,BasicTableProps} from "/@/hooks/table";
|
||||
import {fetchList} from "/@/api/recruit/recruitSchoolHistory";
|
||||
|
||||
// 表格状态
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {},
|
||||
createdIsNeed: false,
|
||||
pageList: async (params: any) => {
|
||||
const response = await fetchList(params)
|
||||
return {
|
||||
data: {
|
||||
records: response.data.records,
|
||||
total: response.data.total
|
||||
}
|
||||
}
|
||||
},
|
||||
createdIsNeed: false
|
||||
})
|
||||
const visible = ref(false)
|
||||
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
|
||||
|
||||
|
||||
const init=()=>{
|
||||
visible.value = true
|
||||
getDataList()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="mod-config">
|
||||
<basic-container>
|
||||
<div >
|
||||
<el-form :inline="true" :model="dataForm" @keyup.enter="handleFilter" ref="searchFormRef">
|
||||
<el-form-item label="招生计划" prop="groupId">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划" size="small">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划" >
|
||||
<el-option
|
||||
v-for="item in planList"
|
||||
:key="item.id"
|
||||
@@ -14,10 +13,10 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button icon="Search" type="primary" size="small"
|
||||
<el-button icon="Search" type="primary"
|
||||
@click="handleFilter">查询
|
||||
</el-button>
|
||||
<el-button icon="Delete" type="default" plain size="small"
|
||||
<el-button icon="Delete" type="default" plain
|
||||
@click="resetForm">清空
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -27,27 +26,24 @@
|
||||
<el-button icon="Download" type="warning" size="small" @click="dataExportHandle">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="avue-crud">
|
||||
<el-table :data="dataList" border stripe v-loading="dataListLoading"
|
||||
:summary-method="getSummaries" show-summary
|
||||
:summary-method="getSummaries" show-summary height="700"
|
||||
>
|
||||
<el-table-column align="center" header-align="center" prop="provinceName" label="省市" />
|
||||
<el-table-column align="center" header-align="center" prop="peopleNum" label="人数" />
|
||||
<el-table-column align="center" header-align="center" prop="peopleRate" label="占比" />
|
||||
</el-table>
|
||||
|
||||
<chart ref="typeEchartBarRef" style="width:100%;margin-top:80px" :options="chartOption" theme="macarons"></chart>
|
||||
<!-- <chart ref="typeEchartBarRef" style="width:100%;margin-top:80px" :options="chartOption" theme="macarons"></chart>-->
|
||||
|
||||
</div>
|
||||
</basic-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { getAreaStatic } from "@/api/recruit/recruitstudentsignup"
|
||||
import { getList } from "@/api/recruit/recruitstudentplangroup"
|
||||
import { getAreaStatic } from '/@/api/recruit/recruitstudentsignup'
|
||||
import { getList } from '/@/api/recruit/recruitstudentplangroup'
|
||||
|
||||
// 响应式数据
|
||||
const dataForm = reactive({
|
||||
@@ -65,11 +61,13 @@ const typeEchartBarRef = ref()
|
||||
// 初始化
|
||||
const init = () => {
|
||||
getList().then((data: any) => {
|
||||
planList.value = data.data
|
||||
planList.value = Array.isArray(data?.data) ? data.data : []
|
||||
if (planList.value.length > 0) {
|
||||
dataForm.groupId = planList.value[0].id
|
||||
}
|
||||
getDataList()
|
||||
}).catch(() => {
|
||||
planList.value = []
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,8 +77,26 @@ const getDataList = () => {
|
||||
dataForm.degreeOfEducation = '1'
|
||||
dataListLoading.value = true
|
||||
getAreaStatic(dataForm).then((response: any) => {
|
||||
dataList.value = response.data
|
||||
chartOption.value = response.data.option
|
||||
const res = response?.data
|
||||
// 兼容:接口可能返回 { data: [], option: {} } 或直接返回数组
|
||||
dataList.value = Array.isArray(res) ? res : (res?.data || res?.records || res?.list || [])
|
||||
const rawOption = Array.isArray(res) ? null : (res?.option ?? null)
|
||||
// 确保 chart 的 option 合法,series[].data 必须为数组,避免 .includes 报错
|
||||
if (rawOption && typeof rawOption === 'object') {
|
||||
const option = { ...rawOption }
|
||||
if (Array.isArray(option.series)) {
|
||||
option.series = option.series.map((s: any) => ({
|
||||
...s,
|
||||
data: Array.isArray(s?.data) ? s.data : []
|
||||
}))
|
||||
}
|
||||
if (option.data !== undefined && !Array.isArray(option.data)) {
|
||||
option.data = []
|
||||
}
|
||||
chartOption.value = option
|
||||
} else {
|
||||
chartOption.value = {}
|
||||
}
|
||||
dataListLoading.value = false
|
||||
}).catch(() => {
|
||||
dataListLoading.value = false
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="mod-config">
|
||||
<basic-container>
|
||||
<div>
|
||||
<el-form :inline="true" :model="dataForm" @keyup.enter="handleFilter" ref="searchFormRef">
|
||||
<el-form-item label="招生计划" prop="groupId">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划" size="small">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划" >
|
||||
<el-option
|
||||
v-for="item in planList"
|
||||
:key="item.id"
|
||||
@@ -14,30 +13,26 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button icon="Search" type="primary" size="small"
|
||||
<el-button icon="Search" type="primary"
|
||||
@click="handleFilter">查询
|
||||
</el-button>
|
||||
<el-button icon="Delete" type="default" plain size="small"
|
||||
<el-button icon="Delete" type="default" plain
|
||||
@click="resetForm">清空
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-button icon="Download" type="warning" size="small" @click="dataExportHandle">导出</el-button>
|
||||
<el-button icon="Download" type="warning" @click="dataExportHandle">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="avue-crud">
|
||||
<el-table :data="dataList" border stripe v-loading="dataListLoading"
|
||||
:summary-method="getSummaries" show-summary
|
||||
>
|
||||
<el-table :data="dataList" border stripe v-loading="dataListLoading" height="700"
|
||||
:summary-method="getSummaries" show-summary>
|
||||
<el-table-column align="center" header-align="center" prop="deptName" label="部门" />
|
||||
<el-table-column align="center" header-align="center" prop="allNum" label="合计" />
|
||||
<el-table-column align="center" header-align="center" prop="schoolNum" label="学校推荐" />
|
||||
<el-table-column align="center" header-align="center" prop="contantNum" label="联系人" />
|
||||
</el-table>
|
||||
</div>
|
||||
</basic-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="mod-config">
|
||||
<basic-container>
|
||||
<el-form :inline="true" :model="dataForm" @keyup.enter="handleFilter" ref="searchFormRef">
|
||||
<el-form-item label="招生计划" prop="groupId">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划" size="small">
|
||||
<el-select v-model="dataForm.groupId" filterable placeholder="请选择招生计划">
|
||||
<el-option
|
||||
v-for="item in planList"
|
||||
:key="item.id"
|
||||
@@ -14,17 +13,17 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button icon="Search" type="primary" size="small"
|
||||
<el-button icon="Search" type="primary"
|
||||
@click="handleFilter">查询
|
||||
</el-button>
|
||||
<el-button icon="Delete" type="default" plain size="small"
|
||||
<el-button icon="Delete" type="default" plain
|
||||
@click="resetForm">清空
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-button icon="Download" type="warning" size="small" @click="dataExportHandle">导出</el-button>
|
||||
<el-button icon="Download" type="warning" @click="dataExportHandle">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="avue-crud">
|
||||
@@ -40,7 +39,6 @@
|
||||
<el-table-column align="center" header-align="center" prop="allNum" label="高中+技职校" />
|
||||
</el-table>
|
||||
</div>
|
||||
</basic-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -671,8 +671,9 @@
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit('0')" v-if="hasAuth('recruit_recruitstudentsignup_add') && canSubmit&&!dataForm.id">保存并送审</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit('0')" v-if="hasAuth('recruit_recruitstudentsignup_edit') && canSubmit&&dataForm.id">保存</el-button>
|
||||
<el-button type="success" icon="CircleCheck" @click="dataFormSubmit('20')" v-if="hasAuth('signup_info_exam') && canSubmit&&dataForm.id">确认录取</el-button>
|
||||
<el-button type="danger" icon="CircleClose" @click="dataFormSubmit('-20')" v-if="hasAuth('signup_info_exam') && canSubmit&&dataForm.id">驳回录取</el-button>
|
||||
<el-button type="success" icon="CircleCheck" @click="dataFormSubmit('20',false)" v-if="hasAuth('signup_info_exam') && canSubmit&&dataForm.id">确认录取</el-button>
|
||||
<el-button type="warning" icon="CircleCheck" @click="dataFormSubmit('20',true)" v-if="hasAuth('signup_pass_force') && canSubmit&&dataForm.id">强制录取</el-button>
|
||||
<el-button type="danger" icon="CircleClose" @click="dataFormSubmit('-20',false)" v-if="hasAuth('signup_info_exam') && canSubmit&&dataForm.id">驳回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1493,7 +1494,7 @@ const updateTuitionByMajorAndEducation = () => {
|
||||
}
|
||||
|
||||
// 表单提交
|
||||
const dataFormSubmit = (state: string) => {
|
||||
const dataFormSubmit = (state: string,force:any) => {
|
||||
dataForm.auditStatus = state
|
||||
let submitTitle = "确认通过该学生的报名申请么?"
|
||||
// 新增模式
|
||||
@@ -1545,6 +1546,7 @@ const dataFormSubmit = (state: string) => {
|
||||
canSubmit.value = false
|
||||
if (dataForm.id) {
|
||||
// 编辑模式
|
||||
dataForm.force=force
|
||||
putObj(dataForm).then(() => {
|
||||
message.success('操作成功')
|
||||
visible.value = false
|
||||
|
||||
@@ -289,6 +289,15 @@
|
||||
@click="handleImportDialog"
|
||||
>导入中招平台数据
|
||||
</el-button>
|
||||
<el-button
|
||||
v-auth="'recruit_sign_sync'"
|
||||
type="warning"
|
||||
plain
|
||||
icon="Refresh"
|
||||
:loading="exportLoading"
|
||||
@click="handleSyncData"
|
||||
>一键同步省人社
|
||||
</el-button>
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="hasAuth('zipExport')"-->
|
||||
<!-- type="warning"-->
|
||||
@@ -1158,6 +1167,16 @@ const handleImportDialog = () => {
|
||||
ImportRecruitInfoRef.value?.init("R10003");
|
||||
};
|
||||
|
||||
const exportLoading=ref(false);
|
||||
const handleSyncData=()=>{
|
||||
exportLoading.value=true;
|
||||
|
||||
setTimeout(() => {
|
||||
exportLoading.value=false;
|
||||
message.success('同步成功');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<el-table-column prop="minScore" header-align="center" align="center" label="最低分" />
|
||||
<el-table-column prop="avgScore" header-align="center" align="center" label="平均分" />
|
||||
<el-table-column prop="majorPeopleNum" header-align="center" align="center" label="专业人数" />
|
||||
<el-table-column prop="avgScoreDB" header-align="center" align="center" label="均分对比" />
|
||||
<!-- <el-table-column prop="avgScoreDB" header-align="center" align="center" label="均分对比" />-->
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,12 +76,13 @@ import { useDict } from '/@/hooks/dict'
|
||||
import { juniorlneStatic } from '/@/api/recruit/recruitstudentsignup'
|
||||
import { getList } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
|
||||
import {getDictsByTypes} from "/@/api/admin/dict";
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
|
||||
// 字典
|
||||
const { getTypeValue } = useDict()
|
||||
// const { useDict } = useDict()
|
||||
|
||||
// 引用
|
||||
const searchFormRef = ref()
|
||||
@@ -104,19 +105,24 @@ const queryForm = reactive({
|
||||
// 使用 table hook 获取样式
|
||||
const { tableStyle, downBlobFile } = useTable()
|
||||
|
||||
const queryDictData=()=>{
|
||||
getDictsByTypes(['basic_major_years']).then((res:any)=>{
|
||||
majorYears.value = res.data.basic_major_years || []
|
||||
})
|
||||
}
|
||||
// 初始化
|
||||
const init = async () => {
|
||||
try {
|
||||
const [deptResponse, majorYearsRes, planData] = await Promise.all([
|
||||
queryDictData()
|
||||
|
||||
const [deptResponse, planData] = await Promise.all([
|
||||
getDeptListByLevelTwo(),
|
||||
getTypeValue('basic_major_years'),
|
||||
getList()
|
||||
])
|
||||
|
||||
|
||||
deptCodes.value = deptResponse.data || []
|
||||
majorYears.value = majorYearsRes.data || []
|
||||
planList.value = planData.data || []
|
||||
|
||||
|
||||
if (planList.value.length > 0) {
|
||||
queryForm.groupId = planList.value[0].id
|
||||
getDataList()
|
||||
|
||||
@@ -102,7 +102,8 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit" v-if="canSubmit">确认修改</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit(false)" v-if="canSubmit">确认修改</el-button>
|
||||
<el-button type="warning" @click="dataFormSubmit(true)" v-if="canSubmit" v-auth="'recruit_signup_change_force'">强制修改</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -272,12 +273,13 @@ const changeCM = (id: string) => {
|
||||
|
||||
|
||||
// 表单提交
|
||||
const dataFormSubmit = async () => {
|
||||
const dataFormSubmit = async (force:any) => {
|
||||
const titleText = "确认调整录取专业么?"
|
||||
if (dataForm.confirmedMajor == dataForm.newConfirmedMajor) {
|
||||
message.error('新专业不能和原专业相同')
|
||||
return
|
||||
}
|
||||
dataForm.force=force
|
||||
try {
|
||||
await messageBox.confirm(titleText)
|
||||
dataFormRef.value?.validate((valid: boolean) => {
|
||||
|
||||
@@ -183,9 +183,10 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit('1')" v-if="hasAuth('recruit_recruitstudentsignup_edit') && canSubmit">保存</el-button>
|
||||
<el-button type="success" icon="CircleCheck" @click="dataFormSubmit('2')" v-if="hasAuth('signup_material_exam') && canSubmit">通过</el-button>
|
||||
<el-button type="danger" icon="CircleClose" @click="dataFormSubmit('3')" v-if="hasAuth('signup_material_exam') && canSubmit">驳回</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmit('1',false)" v-if="hasAuth('recruit_recruitstudentsignup_edit') && canSubmit">保存</el-button>
|
||||
<el-button type="success" icon="CircleCheck" @click="dataFormSubmit('2',false)" v-if="hasAuth('signup_material_exam') && canSubmit">通过</el-button>
|
||||
<el-button type="success" icon="CircleCheck" @click="dataFormSubmit('2',true)" v-if="hasAuth('signup_material_pass_force') && canSubmit">强制通过</el-button>
|
||||
<el-button type="danger" icon="CircleClose" @click="dataFormSubmit('3',false)" v-if="hasAuth('signup_material_exam') && canSubmit">驳回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -412,13 +413,14 @@ const initData = () => {
|
||||
}
|
||||
|
||||
// 表单提交
|
||||
const dataFormSubmit = (submitType: string) => {
|
||||
const dataFormSubmit = (submitType: string,force:any) => {
|
||||
if ((dataForm.zlshRemark == '' || !dataForm.zlshRemark) && submitType == '3') {
|
||||
message.error('请填写驳回理由')
|
||||
return
|
||||
}
|
||||
dataForm.zlsh = submitType
|
||||
canSubmit.value = false
|
||||
dataForm.force=force
|
||||
materialExam(dataForm).then(() => {
|
||||
message.success('操作成功')
|
||||
visible.value = false
|
||||
|
||||
@@ -201,7 +201,8 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancelPlace">取消</el-button>
|
||||
<el-button type="primary" @click="update">保存</el-button>
|
||||
<el-button type="primary" @click="update(false)">保存</el-button>
|
||||
<el-button type="warning" @click="update(true)" v-auth="'recruit_signup_change_force'">强制保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -273,7 +274,8 @@ const exarmForm = reactive({
|
||||
isMajorChange: '',
|
||||
examRemark: '',
|
||||
groupId: '',
|
||||
remarks: ''
|
||||
remarks: '',
|
||||
force:false
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
@@ -340,11 +342,11 @@ const cancelPlace = () => {
|
||||
}
|
||||
|
||||
// 保存审核
|
||||
const update = async () => {
|
||||
const update = async (force:any) => {
|
||||
try {
|
||||
const valid = await exarmFormRef.value?.validate().catch(() => {})
|
||||
if (!valid) return
|
||||
|
||||
exarmForm.force=force
|
||||
await putObj(exarmForm)
|
||||
message.success('审核成功')
|
||||
majorChangeVisible.value = false
|
||||
|
||||
Reference in New Issue
Block a user