2025-07-31 17:00:32 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="regulation-proposal">
|
|
|
|
|
<a-card title="制度提案管理" :bordered="false">
|
|
|
|
|
<template #extra>
|
|
|
|
|
<a-button type="primary" @click="handleAdd">
|
|
|
|
|
<template #icon>
|
|
|
|
|
<GiSvgIcon name="plus" />
|
|
|
|
|
</template>
|
|
|
|
|
新增制度提案
|
|
|
|
|
</a-button>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- 搜索区域 -->
|
|
|
|
|
<div class="search-container">
|
|
|
|
|
<a-form layout="inline" :model="searchForm" class="search-form">
|
|
|
|
|
<a-form-item label="提案标题">
|
|
|
|
|
<a-input
|
|
|
|
|
v-model="searchForm.title"
|
|
|
|
|
placeholder="请输入提案标题"
|
|
|
|
|
allow-clear
|
|
|
|
|
style="width: 200px"
|
|
|
|
|
/>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item label="提案人">
|
|
|
|
|
<a-input
|
2025-08-01 17:22:47 +08:00
|
|
|
|
v-model="searchForm.proposer"
|
2025-07-31 17:00:32 +08:00
|
|
|
|
placeholder="请输入提案人"
|
|
|
|
|
allow-clear
|
|
|
|
|
style="width: 150px"
|
|
|
|
|
/>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item label="状态">
|
|
|
|
|
<a-select
|
|
|
|
|
v-model="searchForm.status"
|
|
|
|
|
placeholder="请选择状态"
|
|
|
|
|
allow-clear
|
|
|
|
|
style="width: 150px"
|
|
|
|
|
>
|
|
|
|
|
<a-option value="">全部</a-option>
|
|
|
|
|
<a-option value="DRAFT">草稿</a-option>
|
2025-08-01 15:37:53 +08:00
|
|
|
|
<a-option value="PUBLISHED">已公告</a-option>
|
2025-07-31 17:00:32 +08:00
|
|
|
|
</a-select>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item>
|
|
|
|
|
<a-space>
|
|
|
|
|
<a-button type="primary" @click="search">
|
|
|
|
|
<template #icon><icon-search /></template>
|
|
|
|
|
搜索
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button @click="reset">
|
|
|
|
|
<template #icon><icon-refresh /></template>
|
|
|
|
|
重置
|
|
|
|
|
</a-button>
|
|
|
|
|
</a-space>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a-table
|
|
|
|
|
:columns="columns"
|
|
|
|
|
:data="tableData"
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:pagination="pagination"
|
|
|
|
|
@page-change="handlePageChange"
|
|
|
|
|
@page-size-change="handlePageSizeChange"
|
|
|
|
|
>
|
|
|
|
|
<template #toolbar-left>
|
|
|
|
|
<span class="search-result-info">
|
|
|
|
|
共找到 <strong>{{ pagination.total }}</strong> 条记录
|
|
|
|
|
</span>
|
|
|
|
|
</template>
|
|
|
|
|
<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.DRAFT"
|
|
|
|
|
type="text"
|
|
|
|
|
size="small"
|
|
|
|
|
@click="handleEdit(record)"
|
|
|
|
|
>
|
|
|
|
|
编辑
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button
|
|
|
|
|
v-if="record.status === RegulationStatus.DRAFT"
|
|
|
|
|
type="primary"
|
|
|
|
|
size="small"
|
|
|
|
|
@click="handleConfirm(record)"
|
|
|
|
|
>
|
|
|
|
|
确认公示
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button
|
|
|
|
|
v-if="record.status !== RegulationStatus.DRAFT"
|
|
|
|
|
type="text"
|
|
|
|
|
size="small"
|
|
|
|
|
disabled
|
|
|
|
|
>
|
|
|
|
|
已公示
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-popconfirm
|
|
|
|
|
v-if="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="900px"
|
|
|
|
|
@ok="handleSubmit"
|
|
|
|
|
@cancel="handleCancel"
|
|
|
|
|
class="proposal-form-modal"
|
|
|
|
|
>
|
|
|
|
|
<a-form
|
|
|
|
|
ref="formRef"
|
|
|
|
|
:model="formData"
|
|
|
|
|
:rules="rules"
|
|
|
|
|
layout="vertical"
|
|
|
|
|
class="proposal-form"
|
|
|
|
|
>
|
|
|
|
|
<a-row :gutter="24">
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-form-item label="提案标题" field="title" class="form-item">
|
|
|
|
|
<a-input
|
|
|
|
|
v-model="formData.title"
|
|
|
|
|
placeholder="请输入提案标题"
|
|
|
|
|
class="form-input"
|
|
|
|
|
allow-clear
|
|
|
|
|
/>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-col>
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-form-item label="提案类型" field="regulationType" class="form-item">
|
|
|
|
|
<a-select
|
|
|
|
|
v-model="formData.regulationType"
|
|
|
|
|
placeholder="请选择提案类型"
|
|
|
|
|
class="form-select"
|
|
|
|
|
allow-clear
|
|
|
|
|
>
|
|
|
|
|
<a-option
|
|
|
|
|
v-for="type in regulationTypes"
|
|
|
|
|
:key="type.typeId"
|
|
|
|
|
:value="type.typeName"
|
|
|
|
|
:disabled="type.isEnabled === '0'"
|
|
|
|
|
>
|
|
|
|
|
{{ type.typeName }}
|
|
|
|
|
</a-option>
|
|
|
|
|
</a-select>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-col>
|
|
|
|
|
</a-row>
|
|
|
|
|
|
|
|
|
|
<a-row :gutter="24">
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-form-item label="适用范围" field="scope" class="form-item">
|
|
|
|
|
<a-input
|
|
|
|
|
v-model="formData.scope"
|
|
|
|
|
placeholder="请输入适用范围"
|
|
|
|
|
class="form-input"
|
|
|
|
|
allow-clear
|
|
|
|
|
/>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-col>
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-form-item label="制度级别" field="level" class="form-item">
|
|
|
|
|
<a-select
|
|
|
|
|
v-model="formData.level"
|
|
|
|
|
placeholder="请选择制度级别"
|
|
|
|
|
class="form-select"
|
|
|
|
|
allow-clear
|
|
|
|
|
>
|
|
|
|
|
<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" class="form-item">
|
|
|
|
|
<a-textarea
|
|
|
|
|
v-model="formData.content"
|
|
|
|
|
placeholder="请详细描述提案的具体内容,包括制度的目的、适用范围、具体规定等"
|
|
|
|
|
:rows="8"
|
|
|
|
|
class="form-textarea"
|
|
|
|
|
allow-clear
|
|
|
|
|
/>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item label="备注" field="remark" class="form-item">
|
|
|
|
|
<a-textarea
|
|
|
|
|
v-model="formData.remark"
|
|
|
|
|
placeholder="请输入其他补充说明(可选)"
|
|
|
|
|
:rows="3"
|
|
|
|
|
class="form-textarea"
|
|
|
|
|
allow-clear
|
|
|
|
|
/>
|
|
|
|
|
</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.createByName }}</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.DRAFT && currentProposal.createByName === currentUser"
|
|
|
|
|
type="primary"
|
|
|
|
|
@click="handleConfirm(currentProposal)"
|
|
|
|
|
>
|
|
|
|
|
确认公示
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button @click="detailModalVisible = false">
|
|
|
|
|
关闭
|
|
|
|
|
</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</a-modal>
|
|
|
|
|
|
|
|
|
|
<!-- 确认公示弹窗 -->
|
|
|
|
|
<a-modal
|
|
|
|
|
v-model:visible="confirmModalVisible"
|
|
|
|
|
title="确认公示提案"
|
|
|
|
|
width="600px"
|
|
|
|
|
@ok="submitConfirm"
|
|
|
|
|
@cancel="confirmModalVisible = false"
|
|
|
|
|
>
|
|
|
|
|
<div class="confirm-content">
|
|
|
|
|
<div class="confirm-header">
|
|
|
|
|
<GiSvgIcon name="exclamation-circle" style="color: #faad14; font-size: 24px; margin-right: 8px;" />
|
|
|
|
|
<span style="font-weight: 500; font-size: 16px;">公示确认</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="confirm-body">
|
|
|
|
|
<p>您即将公示提案《<strong>{{ currentProposal?.title }}</strong>》</p>
|
|
|
|
|
<p>公示后:</p>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>该提案将进入制度公示页面</li>
|
|
|
|
|
<li>其他用户可以在制度公示页面查看此提案</li>
|
|
|
|
|
<li>提案将进入正式的公示流程</li>
|
|
|
|
|
<li>您将无法再编辑此提案</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="confirm-footer">
|
|
|
|
|
<a-checkbox v-model="agreeDisplay">
|
|
|
|
|
我已仔细阅读并确认公示此提案
|
|
|
|
|
</a-checkbox>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</a-modal>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
|
|
|
import { Message } from '@arco-design/web-vue'
|
|
|
|
|
import { IconSearch, IconRefresh } from '@arco-design/web-vue/es/icon'
|
|
|
|
|
import { useRegulationStore } from '@/stores/modules/regulation'
|
|
|
|
|
import { regulationApi } from '@/apis/regulation'
|
|
|
|
|
import {
|
|
|
|
|
RegulationStatus,
|
|
|
|
|
RegulationLevel,
|
|
|
|
|
type Regulation,
|
2025-08-01 17:22:47 +08:00
|
|
|
|
type RegulationType,
|
|
|
|
|
type RegulationProposalSearchRequest
|
2025-07-31 17:00:32 +08:00
|
|
|
|
} from '@/apis/regulation/type'
|
|
|
|
|
|
|
|
|
|
defineOptions({ name: 'RegulationProposal' })
|
|
|
|
|
|
|
|
|
|
// 表格列定义
|
|
|
|
|
const columns = [
|
|
|
|
|
{ title: '提案标题', dataIndex: 'title', key: 'title', width: 220 },
|
|
|
|
|
{ title: '提案人', dataIndex: 'createByName', key: 'createByName', width: 130 },
|
|
|
|
|
{ title: '提案类型', dataIndex: 'regulationType', key: 'regulationType', width: 130 },
|
|
|
|
|
{ title: '状态', dataIndex: 'status', key: 'status', slotName: 'status', width: 110 },
|
|
|
|
|
{ title: '级别', dataIndex: 'level', key: 'level', slotName: 'level', width: 90 },
|
|
|
|
|
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 200 },
|
|
|
|
|
{ title: '操作', key: 'operations', slotName: 'operations', width: 320 }
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// 搜索表单
|
|
|
|
|
const searchForm = reactive({
|
|
|
|
|
title: '',
|
2025-08-01 17:22:47 +08:00
|
|
|
|
proposer: '',
|
2025-07-31 17:00:32 +08:00
|
|
|
|
status: ''
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 表格数据
|
|
|
|
|
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 confirmModalVisible = ref(false)
|
|
|
|
|
const agreeDisplay = ref(false)
|
|
|
|
|
|
|
|
|
|
// 当前用户
|
|
|
|
|
const currentUser = ref('管理者') // 从用户认证系统获取当前用户ID
|
|
|
|
|
|
|
|
|
|
// 制度管理store
|
|
|
|
|
const regulationStore = useRegulationStore()
|
|
|
|
|
|
|
|
|
|
// 制度类型列表
|
|
|
|
|
const regulationTypes = ref<RegulationType[]>([])
|
|
|
|
|
|
|
|
|
|
// 表单验证规则
|
|
|
|
|
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]: '已否决',
|
2025-08-01 15:37:53 +08:00
|
|
|
|
[RegulationStatus.PUBLISHED]: '已公告',
|
|
|
|
|
[RegulationStatus.APPROVED]: '已公示',
|
2025-07-31 17:00:32 +08:00
|
|
|
|
[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 getRegulationTypes = async () => {
|
|
|
|
|
try {
|
2025-08-04 22:15:48 +08:00
|
|
|
|
const response = await regulationApi.searchRegulationTypes()
|
2025-07-31 17:00:32 +08:00
|
|
|
|
if (response.status === 200) {
|
|
|
|
|
regulationTypes.value = response.data.records || response.data
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取制度类型列表失败:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-01 17:22:47 +08:00
|
|
|
|
// 获取表格数据 - 使用后端搜索接口
|
2025-07-31 17:00:32 +08:00
|
|
|
|
const getTableData = async () => {
|
|
|
|
|
loading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const response = await regulationApi.getRegulationList({
|
|
|
|
|
page: pagination.current,
|
|
|
|
|
size: pagination.pageSize,
|
|
|
|
|
title: searchForm.title || undefined,
|
2025-08-01 17:22:47 +08:00
|
|
|
|
proposer: searchForm.proposer || undefined,
|
2025-07-31 17:00:32 +08:00
|
|
|
|
status: searchForm.status || undefined
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (response.status === 200) {
|
|
|
|
|
tableData.value = response.data.records
|
|
|
|
|
pagination.total = response.data.total
|
|
|
|
|
pagination.current = response.data.current
|
|
|
|
|
} else {
|
2025-08-01 17:22:47 +08:00
|
|
|
|
Message.error('搜索失败')
|
2025-07-31 17:00:32 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2025-08-01 17:22:47 +08:00
|
|
|
|
console.error('搜索制度提案失败:', error)
|
|
|
|
|
Message.error('搜索失败')
|
2025-07-31 17:00:32 +08:00
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 搜索
|
|
|
|
|
const search = () => {
|
|
|
|
|
pagination.current = 1
|
|
|
|
|
getTableData()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重置
|
|
|
|
|
const reset = () => {
|
|
|
|
|
Object.assign(searchForm, {
|
|
|
|
|
title: '',
|
2025-08-01 17:22:47 +08:00
|
|
|
|
proposer: '',
|
2025-07-31 17:00:32 +08:00
|
|
|
|
status: ''
|
|
|
|
|
})
|
|
|
|
|
pagination.current = 1
|
|
|
|
|
getTableData()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 新增
|
|
|
|
|
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 handleConfirm = (record: Regulation) => {
|
|
|
|
|
currentProposal.value = record
|
|
|
|
|
confirmModalVisible.value = true
|
|
|
|
|
agreeDisplay.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除
|
|
|
|
|
const handleDelete = async (record: Regulation) => {
|
|
|
|
|
try {
|
|
|
|
|
await regulationApi.deleteProposal(record.regulationId)
|
|
|
|
|
Message.success('删除成功')
|
|
|
|
|
getTableData()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('删除失败:', error)
|
|
|
|
|
Message.error('删除失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提交确认公示
|
|
|
|
|
const submitConfirm = async () => {
|
|
|
|
|
if (!agreeDisplay.value) {
|
|
|
|
|
Message.warning('请先确认公示此提案')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (currentProposal.value) {
|
|
|
|
|
console.log('准备公示提案:', currentProposal.value.regulationId)
|
|
|
|
|
// 使用公示制度API
|
|
|
|
|
const response = await regulationApi.publishRegulation(currentProposal.value.regulationId)
|
|
|
|
|
console.log('公示响应:', response)
|
|
|
|
|
|
|
|
|
|
Message.success('提案公示成功,已进入公示流程')
|
|
|
|
|
confirmModalVisible.value = false
|
|
|
|
|
getTableData() // 刷新列表
|
|
|
|
|
|
|
|
|
|
// 如果是从详情弹窗发起的确认,也关闭详情弹窗
|
|
|
|
|
if (detailModalVisible.value) {
|
|
|
|
|
detailModalVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('公示失败:', error)
|
|
|
|
|
console.error('错误详情:', error.response || 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 {
|
|
|
|
|
// 新增
|
|
|
|
|
const createData = {
|
|
|
|
|
title: formData.title,
|
|
|
|
|
regulationType: formData.regulationType,
|
|
|
|
|
content: formData.content,
|
|
|
|
|
scope: formData.scope,
|
|
|
|
|
level: formData.level,
|
|
|
|
|
remark: formData.remark,
|
|
|
|
|
createByName: currentUser.value
|
|
|
|
|
}
|
|
|
|
|
console.log('新增提案数据:', createData)
|
|
|
|
|
const response = await regulationApi.createProposal(createData)
|
|
|
|
|
console.log('新增提案响应:', response)
|
|
|
|
|
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()
|
|
|
|
|
getRegulationTypes()
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.regulation-proposal {
|
|
|
|
|
.arco-card {
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-container {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
background: var(--color-bg-2);
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
|
|
.search-form {
|
|
|
|
|
.arco-form-item {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
margin-right: 16px;
|
|
|
|
|
|
|
|
|
|
.arco-form-item-label {
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: var(--color-text-1);
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-input,
|
|
|
|
|
.arco-select {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-btn {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-result-info {
|
|
|
|
|
color: var(--color-text-2);
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
|
|
strong {
|
|
|
|
|
color: var(--color-text-1);
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提案表单美化样式
|
|
|
|
|
.proposal-form-modal {
|
|
|
|
|
.arco-modal-body {
|
|
|
|
|
padding: 24px 32px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-modal-header {
|
|
|
|
|
padding: 20px 32px 16px;
|
|
|
|
|
border-bottom: 1px solid var(--color-border);
|
|
|
|
|
|
|
|
|
|
.arco-modal-title {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: var(--color-text-1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-modal-footer {
|
|
|
|
|
padding: 16px 32px 24px;
|
|
|
|
|
border-top: 1px solid var(--color-border);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.proposal-form {
|
|
|
|
|
.form-item {
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
|
|
|
|
.arco-form-item-label {
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: var(--color-text-1);
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
|
|
&::before {
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-form-item-error {
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-input,
|
|
|
|
|
.form-select {
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
border: 1px solid var(--color-border);
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
border-color: var(--color-primary-light-3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:focus,
|
|
|
|
|
&.arco-input-focus,
|
|
|
|
|
&.arco-select-focus {
|
|
|
|
|
border-color: var(--color-primary);
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-input-inner {
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-textarea {
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
border: 1px solid var(--color-border);
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
border-color: var(--color-primary-light-3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:focus,
|
|
|
|
|
&.arco-textarea-focus {
|
|
|
|
|
border-color: var(--color-primary);
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-textarea-inner {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 选择框样式优化
|
|
|
|
|
.arco-select {
|
|
|
|
|
.arco-select-view {
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.arco-select-arrow {
|
|
|
|
|
color: var(--color-text-3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 占位符样式
|
|
|
|
|
.arco-input-inner::placeholder,
|
|
|
|
|
.arco-textarea-inner::placeholder {
|
|
|
|
|
color: var(--color-text-3);
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 清空按钮样式
|
|
|
|
|
.arco-input-clear-btn,
|
|
|
|
|
.arco-textarea-clear-btn {
|
|
|
|
|
color: var(--color-text-3);
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
color: var(--color-text-2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.confirm-content {
|
|
|
|
|
.confirm-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
padding-bottom: 12px;
|
|
|
|
|
border-bottom: 1px solid var(--color-border);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.confirm-body {
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
color: var(--color-text-1);
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul {
|
|
|
|
|
margin: 12px 0;
|
|
|
|
|
padding-left: 20px;
|
|
|
|
|
|
|
|
|
|
li {
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
color: var(--color-text-2);
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.confirm-footer {
|
|
|
|
|
padding-top: 16px;
|
|
|
|
|
border-top: 1px solid var(--color-border);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|