| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- <template>
- <ContentWrap title="机构公章管理">
- <template #header>
- <div class="seal-header">
- <el-button :loading="loading" @click="handleRefresh">
- <Icon icon="ep:refresh" class="mr-5px" />刷新
- </el-button>
- </div>
- </template>
- <el-alert type="info" :closable="false" show-icon class="mb-20px">
- 当前机构:<strong>{{ tenantName || '—' }}</strong
- >,公章仅对本机构生效,每个类型只能上传一枚公章。
- </el-alert>
- <div v-loading="loading" class="seal-container">
- <el-empty
- v-if="!typeOptions.length"
- description="未获取到公章类型字典(common_seal),请先配置字典"
- />
- <div v-for="opt in typeOptions" :key="opt.value" class="seal-card">
- <div class="seal-card-title">{{ opt.label }}</div>
- <div class="seal-box">
- <UploadImg
- v-model="formMap[opt.value].url"
- v-model:fileName="formMap[opt.value].fileName"
- :width="'220px'"
- :height="'220px'"
- :show-delete="false"
- />
- </div>
- <div class="seal-tip">支持 jpg / png / gif,大小不超过 5MB。点击图片即可上传或替换。</div>
- <div class="seal-actions">
- <el-button
- type="primary"
- :loading="savingType === opt.value"
- @click="handleSave(opt.value)"
- >
- 保存
- </el-button>
- <el-button type="danger" plain :disabled="!formMap[opt.value].id" @click="handleDelete(opt.value)">
- 删除公章
- </el-button>
- </div>
- </div>
- </div>
- </ContentWrap>
- </template>
- <script setup lang="ts">
- import { ref, reactive, computed, onMounted } from 'vue'
- import { ElMessageBox } from 'element-plus'
- import { UploadImg } from '@/components/UploadFile'
- import { getTenantId } from '@/utils/auth'
- import { useUserStore } from '@/store/modules/user'
- import { useDictStore } from '@/store/modules/dict'
- import { useMessage } from '@/hooks/web/useMessage'
- import { getStrDictOptions, DICT_TYPE, type StringDictDataType } from '@/utils/dict'
- import {
- getCommonSealList,
- createCommonSeal,
- updateCommonSeal,
- deleteCommonSeal,
- type CommonSealVO
- } from '@/api/system/commonSeal'
- defineOptions({ name: 'OfficialSeal' })
- /** 单个类型公章的编辑态 */
- interface SealForm {
- id?: number
- url: string
- fileName: string
- }
- const message = useMessage()
- const userStore = useUserStore()
- const dictStore = useDictStore()
- const tenantId = getTenantId() as number
- const tenantName = computed(() => userStore.tenant?.name || '')
- const loading = ref(false)
- const savingType = ref('')
- /** 公章类型(字典 common_seal) */
- const typeOptions = ref<StringDictDataType[]>([])
- /** 各类型公章编辑数据,key 为字典值 */
- const formMap = reactive<Record<string, SealForm>>({})
- /** 按字典构建表单结构,保证模板中 formMap[type] 一定存在 */
- const buildForms = () => {
- typeOptions.value = getStrDictOptions(DICT_TYPE.COMMON_SEAL)
- typeOptions.value.forEach((opt) => {
- if (!formMap[opt.value]) {
- formMap[opt.value] = { id: undefined, url: '', fileName: '' }
- }
- })
- }
- /** 拉取当前机构公章列表,按类型回填 */
- const loadSealList = async () => {
- loading.value = true
- try {
- const list: CommonSealVO[] = (await getCommonSealList({ tenantId })) || []
- Object.keys(formMap).forEach((key) => {
- formMap[key].id = undefined
- formMap[key].url = ''
- formMap[key].fileName = ''
- })
- list.forEach((item) => {
- const key = item?.type || ''
- if (!key) return
- if (!formMap[key]) {
- formMap[key] = { id: undefined, url: '', fileName: '' }
- }
- formMap[key].id = item.id
- formMap[key].url = item.url || ''
- })
- } catch {
- message.error('公章列表加载失败,请稍后重试')
- } finally {
- loading.value = false
- }
- }
- /** 手动刷新:重新拉取列表,避免新增 / 更新后数据延迟 */
- const handleRefresh = async () => {
- await loadSealList()
- message.success('已刷新')
- }
- /** 保存:已存在则更新,否则创建 */
- const handleSave = async (type: string) => {
- const form = formMap[type]
- if (!form?.url) {
- message.error('请先上传公章图片')
- return
- }
- savingType.value = type
- try {
- if (form.id) {
- await updateCommonSeal({ id: form.id, type, url: form.url, tenantId })
- } else {
- await createCommonSeal({ type, url: form.url, tenantId })
- }
- message.success('公章已保存')
- await loadSealList()
- } catch {
- // 失败提示由请求拦截器统一处理
- } finally {
- savingType.value = ''
- }
- }
- /** 删除公章 */
- const handleDelete = async (type: string) => {
- const form = formMap[type]
- if (!form?.id) {
- message.warning('当前没有可删除的公章')
- return
- }
- try {
- await ElMessageBox.confirm('确认删除该类型公章?删除后需重新上传。', '提示', {
- type: 'warning'
- })
- } catch {
- return
- }
- try {
- await deleteCommonSeal(form.id)
- form.id = undefined
- form.url = ''
- form.fileName = ''
- message.success('公章已删除')
- } catch {
- // 失败提示由请求拦截器统一处理
- }
- }
- onMounted(async () => {
- // 字典可能尚未加载(或新增了 common_seal),兜底重新拉取一次
- if (!getStrDictOptions(DICT_TYPE.COMMON_SEAL).length) {
- await dictStore.resetDict()
- }
- buildForms()
- await loadSealList()
- })
- </script>
- <style scoped lang="scss">
- .seal-header {
- display: flex;
- justify-content: flex-end;
- flex: 1;
- }
- .seal-container {
- display: flex;
- flex-wrap: wrap;
- gap: 24px;
- padding: 10px 0;
- }
- .seal-card {
- width: 280px;
- padding: 16px;
- border: 1px solid var(--el-border-color-lighter);
- border-radius: 8px;
- }
- .seal-card-title {
- margin-bottom: 12px;
- font-size: 15px;
- font-weight: 600;
- text-align: center;
- }
- .seal-box {
- display: flex;
- justify-content: center;
- margin: 16px 0;
- }
- .seal-tip {
- text-align: center;
- font-size: 13px;
- color: var(--el-text-color-secondary);
- margin-bottom: 18px;
- }
- .seal-actions {
- display: flex;
- justify-content: center;
- gap: 12px;
- }
- </style>
|