509 lines
14 KiB
Vue
509 lines
14 KiB
Vue
<template>
|
|
<div class="process-management">
|
|
<a-card title="制度提案管理" :bordered="false">
|
|
<template #extra>
|
|
<a-button type="primary" @click="handleAdd">
|
|
<template #icon>
|
|
<GiSvgIcon name="plus" />
|
|
</template>
|
|
提交制度提案
|
|
</a-button>
|
|
</template>
|
|
|
|
<a-table
|
|
:columns="columns"
|
|
:data="tableData"
|
|
:loading="loading"
|
|
:pagination="pagination"
|
|
@page-change="handlePageChange"
|
|
@page-size-change="handlePageSizeChange"
|
|
>
|
|
<template #status="{ record }">
|
|
<a-tag :color="getStatusColor(record.status)">
|
|
{{ getStatusText(record.status) }}
|
|
</a-tag>
|
|
</template>
|
|
|
|
<template #level="{ record }">
|
|
<a-tag :color="getLevelColor(record.level)">
|
|
{{ getLevelText(record.level) }}
|
|
</a-tag>
|
|
</template>
|
|
|
|
<template #operations="{ record }">
|
|
<a-space>
|
|
<a-button type="text" size="small" @click="handleView(record)">
|
|
查看详情
|
|
</a-button>
|
|
<a-button
|
|
v-if="record.status === RegulationStatus.PUBLISHED"
|
|
type="text"
|
|
size="small"
|
|
disabled
|
|
>
|
|
已发布
|
|
</a-button>
|
|
<a-button
|
|
v-if="record.publisherId === currentUser && record.status === RegulationStatus.DRAFT"
|
|
type="text"
|
|
size="small"
|
|
@click="handleEdit(record)"
|
|
>
|
|
编辑
|
|
</a-button>
|
|
<a-popconfirm
|
|
v-if="record.publisherId === currentUser && record.status === RegulationStatus.DRAFT"
|
|
content="确定要删除这个提案吗?"
|
|
@ok="handleDelete(record)"
|
|
>
|
|
<a-button type="text" size="small" status="danger">
|
|
删除
|
|
</a-button>
|
|
</a-popconfirm>
|
|
</a-space>
|
|
</template>
|
|
</a-table>
|
|
</a-card>
|
|
|
|
<!-- 提案表单弹窗 -->
|
|
<a-modal
|
|
v-model:visible="modalVisible"
|
|
:title="modalTitle"
|
|
width="800px"
|
|
@ok="handleSubmit"
|
|
@cancel="handleCancel"
|
|
>
|
|
<a-form
|
|
ref="formRef"
|
|
:model="formData"
|
|
:rules="rules"
|
|
layout="vertical"
|
|
>
|
|
<a-row :gutter="16">
|
|
<a-col :span="12">
|
|
<a-form-item label="提案标题" field="title">
|
|
<a-input v-model="formData.title" placeholder="请输入提案标题" />
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-form-item label="提案类型" field="regulationType">
|
|
<a-select v-model="formData.regulationType" placeholder="请选择提案类型">
|
|
<a-option value="人事制度">人事制度</a-option>
|
|
<a-option value="财务制度">财务制度</a-option>
|
|
<a-option value="安全制度">安全制度</a-option>
|
|
<a-option value="设备制度">设备制度</a-option>
|
|
<a-option value="工作流程">工作流程</a-option>
|
|
<a-option value="其他制度">其他制度</a-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
|
|
<a-row :gutter="16">
|
|
<a-col :span="12">
|
|
<a-form-item label="适用范围" field="scope">
|
|
<a-input v-model="formData.scope" placeholder="请输入适用范围" />
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-form-item label="制度级别" field="level">
|
|
<a-select v-model="formData.level" placeholder="请选择制度级别">
|
|
<a-option :value="RegulationLevel.LOW">低</a-option>
|
|
<a-option :value="RegulationLevel.MEDIUM">中</a-option>
|
|
<a-option :value="RegulationLevel.HIGH">高</a-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
|
|
<a-form-item label="提案内容" field="content">
|
|
<a-textarea
|
|
v-model="formData.content"
|
|
placeholder="请详细描述提案的具体内容"
|
|
:rows="6"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="备注" field="remark">
|
|
<a-textarea
|
|
v-model="formData.remark"
|
|
placeholder="请输入其他补充说明"
|
|
:rows="2"
|
|
/>
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-modal>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 提案详情弹窗 -->
|
|
<a-modal
|
|
v-model:visible="detailModalVisible"
|
|
title="提案详情"
|
|
width="800px"
|
|
:footer="false"
|
|
>
|
|
<div class="proposal-detail" v-if="currentProposal">
|
|
<div class="detail-header">
|
|
<h3>{{ currentProposal.title }}</h3>
|
|
<div class="detail-meta">
|
|
<span>提案人: {{ currentProposal.publisherName }}</span>
|
|
<span>提案类型: {{ currentProposal.regulationType }}</span>
|
|
<span>适用范围: {{ currentProposal.scope }}</span>
|
|
<span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span>
|
|
<span>创建时间: {{ formatDate(currentProposal.createTime) }}</span>
|
|
<span>状态: <a-tag :color="getStatusColor(currentProposal.status)">{{ getStatusText(currentProposal.status) }}</a-tag></span>
|
|
</div>
|
|
</div>
|
|
|
|
<a-divider />
|
|
|
|
<div class="detail-content">
|
|
<h4>提案内容</h4>
|
|
<div class="content-text">{{ currentProposal.content }}</div>
|
|
|
|
<h4>备注</h4>
|
|
<div class="content-text">{{ currentProposal.remark || '暂无备注' }}</div>
|
|
</div>
|
|
|
|
<a-divider />
|
|
|
|
<div class="detail-footer">
|
|
<a-button
|
|
v-if="currentProposal.status === RegulationStatus.PUBLISHED"
|
|
disabled
|
|
>
|
|
已自动发布
|
|
</a-button>
|
|
</div>
|
|
</div>
|
|
</a-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import { Message } from '@arco-design/web-vue'
|
|
import { useRegulationStore } from '@/stores/modules/regulation'
|
|
import { regulationApi } from '@/apis/regulation'
|
|
import {
|
|
RegulationStatus,
|
|
RegulationLevel,
|
|
type Regulation
|
|
} from '@/apis/regulation/type'
|
|
|
|
defineOptions({ name: 'ProcessManagement' })
|
|
|
|
// 表格列定义
|
|
const columns = [
|
|
{ title: '提案标题', dataIndex: 'title', key: 'title' },
|
|
{ title: '提案人', dataIndex: 'publisherName', key: 'publisherName' },
|
|
{ title: '提案类型', dataIndex: 'regulationType', key: 'regulationType' },
|
|
{ title: '状态', dataIndex: 'status', key: 'status', slotName: 'status' },
|
|
{ title: '级别', dataIndex: 'level', key: 'level', slotName: 'level' },
|
|
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime' },
|
|
{ title: '操作', key: 'operations', slotName: 'operations', width: 280 }
|
|
]
|
|
|
|
// 表格数据
|
|
const tableData = ref<Regulation[]>([])
|
|
const loading = ref(false)
|
|
const pagination = reactive({
|
|
current: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
showTotal: true,
|
|
showJumper: true,
|
|
showPageSize: true
|
|
})
|
|
|
|
// 弹窗相关
|
|
const modalVisible = ref(false)
|
|
const modalTitle = ref('提交制度提案')
|
|
const formRef = ref()
|
|
const formData = reactive({
|
|
regulationId: '',
|
|
title: '',
|
|
regulationType: '',
|
|
content: '',
|
|
scope: '',
|
|
level: RegulationLevel.MEDIUM,
|
|
remark: ''
|
|
})
|
|
|
|
const currentProposal = ref<Regulation | null>(null)
|
|
|
|
// 详情相关
|
|
const detailModalVisible = ref(false)
|
|
|
|
// 当前用户 - 应该从用户认证系统获取
|
|
const currentUser = ref('') // TODO: 从用户认证系统获取当前用户ID
|
|
|
|
// 制度管理store
|
|
const regulationStore = useRegulationStore()
|
|
|
|
// 表单验证规则
|
|
const rules = {
|
|
title: [{ required: true, message: '请输入提案标题' }],
|
|
regulationType: [{ required: true, message: '请选择提案类型' }],
|
|
content: [{ required: true, message: '请输入提案内容' }],
|
|
scope: [{ required: true, message: '请输入适用范围' }]
|
|
}
|
|
|
|
// 获取状态颜色
|
|
const getStatusColor = (status: RegulationStatus) => {
|
|
const colors = {
|
|
[RegulationStatus.DRAFT]: 'blue',
|
|
[RegulationStatus.VOTING]: 'orange',
|
|
[RegulationStatus.REJECTED]: 'red',
|
|
[RegulationStatus.PUBLISHED]: 'purple',
|
|
[RegulationStatus.APPROVED]: 'green',
|
|
[RegulationStatus.ARCHIVED]: 'gray'
|
|
}
|
|
return colors[status] || 'blue'
|
|
}
|
|
|
|
// 获取状态文本
|
|
const getStatusText = (status: RegulationStatus) => {
|
|
const texts = {
|
|
[RegulationStatus.DRAFT]: '草稿',
|
|
[RegulationStatus.VOTING]: '投票中',
|
|
[RegulationStatus.REJECTED]: '已否决',
|
|
[RegulationStatus.PUBLISHED]: '已发布',
|
|
[RegulationStatus.APPROVED]: '已通过',
|
|
[RegulationStatus.ARCHIVED]: '已归档'
|
|
}
|
|
return texts[status] || '草稿'
|
|
}
|
|
|
|
// 格式化日期
|
|
const formatDate = (dateString: string) => {
|
|
if (!dateString) return '-'
|
|
const date = new Date(dateString)
|
|
return date.toLocaleDateString('zh-CN', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
})
|
|
}
|
|
|
|
// 获取级别颜色
|
|
const getLevelColor = (level: RegulationLevel) => {
|
|
const colors = {
|
|
[RegulationLevel.LOW]: 'blue',
|
|
[RegulationLevel.MEDIUM]: 'orange',
|
|
[RegulationLevel.HIGH]: 'red'
|
|
}
|
|
return colors[level] || 'blue'
|
|
}
|
|
|
|
// 获取级别文本
|
|
const getLevelText = (level: RegulationLevel) => {
|
|
const texts = {
|
|
[RegulationLevel.LOW]: '低',
|
|
[RegulationLevel.MEDIUM]: '中',
|
|
[RegulationLevel.HIGH]: '高'
|
|
}
|
|
return texts[level] || '中'
|
|
}
|
|
|
|
// 获取表格数据
|
|
const getTableData = async () => {
|
|
loading.value = true
|
|
try {
|
|
const response = await regulationApi.getRegulationList({
|
|
page: pagination.current,
|
|
size: pagination.pageSize
|
|
})
|
|
|
|
if (response.status === 200) {
|
|
tableData.value = response.data.records
|
|
pagination.total = response.data.total
|
|
pagination.current = response.data.current
|
|
} else {
|
|
Message.error('获取数据失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('获取制度列表失败:', error)
|
|
Message.error('获取数据失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 新增
|
|
const handleAdd = () => {
|
|
modalTitle.value = '提交制度提案'
|
|
modalVisible.value = true
|
|
resetForm()
|
|
}
|
|
|
|
// 编辑
|
|
const handleEdit = (record: Regulation) => {
|
|
modalTitle.value = '编辑制度提案'
|
|
modalVisible.value = true
|
|
Object.assign(formData, {
|
|
regulationId: record.regulationId,
|
|
title: record.title,
|
|
regulationType: record.regulationType,
|
|
content: record.content,
|
|
scope: record.scope,
|
|
level: record.level,
|
|
remark: record.remark
|
|
})
|
|
}
|
|
|
|
// 查看
|
|
const handleView = (record: Regulation) => {
|
|
currentProposal.value = record
|
|
detailModalVisible.value = true
|
|
}
|
|
|
|
|
|
|
|
// 删除
|
|
const handleDelete = async (record: Regulation) => {
|
|
try {
|
|
await regulationApi.deleteProposal(record.regulationId)
|
|
Message.success('删除成功')
|
|
getTableData()
|
|
} catch (error) {
|
|
console.error('删除失败:', error)
|
|
Message.error('删除失败')
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 提交表单
|
|
const handleSubmit = async () => {
|
|
try {
|
|
await formRef.value.validate()
|
|
|
|
if (formData.regulationId) {
|
|
// 更新
|
|
await regulationApi.updateProposal(formData.regulationId, {
|
|
title: formData.title,
|
|
regulationType: formData.regulationType,
|
|
content: formData.content,
|
|
scope: formData.scope,
|
|
level: formData.level,
|
|
remark: formData.remark
|
|
})
|
|
Message.success('更新成功')
|
|
} else {
|
|
// 新增
|
|
await regulationApi.createProposal({
|
|
title: formData.title,
|
|
regulationType: formData.regulationType,
|
|
content: formData.content,
|
|
scope: formData.scope,
|
|
level: formData.level,
|
|
remark: formData.remark
|
|
})
|
|
Message.success('提案提交成功')
|
|
}
|
|
|
|
modalVisible.value = false
|
|
getTableData()
|
|
} catch (error) {
|
|
console.error('操作失败:', error)
|
|
Message.error('操作失败')
|
|
}
|
|
}
|
|
|
|
// 取消
|
|
const handleCancel = () => {
|
|
modalVisible.value = false
|
|
resetForm()
|
|
}
|
|
|
|
// 重置表单
|
|
const resetForm = () => {
|
|
Object.assign(formData, {
|
|
regulationId: '',
|
|
title: '',
|
|
regulationType: '',
|
|
content: '',
|
|
scope: '',
|
|
level: RegulationLevel.MEDIUM,
|
|
remark: ''
|
|
})
|
|
formRef.value?.resetFields()
|
|
}
|
|
|
|
// 分页事件
|
|
const handlePageChange = (page: number) => {
|
|
pagination.current = page
|
|
getTableData()
|
|
}
|
|
|
|
const handlePageSizeChange = (pageSize: number) => {
|
|
pagination.pageSize = pageSize
|
|
pagination.current = 1
|
|
getTableData()
|
|
}
|
|
|
|
onMounted(() => {
|
|
getTableData()
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.process-management {
|
|
.arco-card {
|
|
margin-bottom: 16px;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.proposal-detail {
|
|
.detail-header {
|
|
margin-bottom: 16px;
|
|
|
|
h3 {
|
|
margin-bottom: 12px;
|
|
color: var(--color-text-1);
|
|
}
|
|
|
|
.detail-meta {
|
|
display: flex;
|
|
gap: 16px;
|
|
color: var(--color-text-3);
|
|
font-size: 14px;
|
|
flex-wrap: wrap;
|
|
}
|
|
}
|
|
|
|
.detail-content {
|
|
h4 {
|
|
margin: 16px 0 8px 0;
|
|
color: var(--color-text-1);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.content-text {
|
|
color: var(--color-text-2);
|
|
line-height: 1.6;
|
|
margin-bottom: 16px;
|
|
padding: 12px;
|
|
background: var(--color-fill-1);
|
|
border-radius: 6px;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.detail-footer {
|
|
display: flex;
|
|
gap: 12px;
|
|
justify-content: center;
|
|
margin-top: 20px;
|
|
}
|
|
}
|
|
</style> |