<template>
|
<basic-container>
|
<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
|
<el-form-item label="机构名称" prop="deptName">
|
<el-input
|
class="gd-input gray"
|
v-model="searchParams.deptName"
|
placeholder="请输入"
|
clearable
|
@clear="handleSearch"
|
/>
|
</el-form-item>
|
|
<el-form-item label="机构编码" prop="deptCode">
|
<el-input
|
class="gd-input gray"
|
v-model="searchParams.deptCode"
|
placeholder="请输入"
|
clearable
|
@clear="handleSearch"
|
/>
|
</el-form-item>
|
|
<el-form-item label="所属区划" prop="areaCode">
|
<RegionSelect
|
class="gd-select gray"
|
v-model="searchParams.areaCode"
|
placeholder="请选择"
|
clearable
|
filterable
|
@change="handleSearch"
|
/>
|
</el-form-item>
|
|
<el-form-item class="gd-search-actions">
|
<el-button :icon="RefreshRight" @click="resetForm"></el-button>
|
<el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button>
|
</el-form-item>
|
</el-form>
|
|
<div class="gd-table-toolbar">
|
<el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增机构</el-button>
|
<el-button :icon="Upload" @click="handleImport">机构导入</el-button>
|
<el-button :icon="Download" :loading="exportLoading" :disabled="exportLoading" @click="handleExport">机构导出</el-button>
|
</div>
|
|
<div class="gd-table-container" v-loading="loading">
|
<div class="gd-table-content gd-table-content-bg">
|
<el-table class="gd-table" :data="list" @selection-change="handleSelectionChange">
|
<el-table-column type="selection" width="46" />
|
<el-table-column label="序号" width="80">
|
<template v-slot="{ $index }">
|
{{ $index + 1 }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="deptCode" show-overflow-tooltip label="机构编码" />
|
<el-table-column prop="deptName" show-overflow-tooltip label="机构名称" />
|
<el-table-column prop="areaName" show-overflow-tooltip label="所属区划" />
|
<el-table-column prop="remark" show-overflow-tooltip label="机构描述" />
|
<el-table-column prop="status" show-overflow-tooltip label="机构状态">
|
<template v-slot="{ row }">
|
{{ getDictLabel(row.status, dictObj.institutionStatus) }}
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" class-name="operation-btns" width="200">
|
<template v-slot="{ row }">
|
<el-link type="primary" @click="openForm('view', row)">查看</el-link>
|
<el-link type="primary" @click="openForm('edit', row)">编辑</el-link>
|
<el-link type="primary" @click="handleDelete(row)">删除</el-link>
|
<el-link type="primary" @click="toggleStatus(row)">{{row.status === 1 ? '禁用' : '启用'}}</el-link>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
|
<div class="gd-pagination-parent">
|
<el-pagination
|
popper-class="gd-select-popper"
|
v-model:current-page="searchParams.current"
|
v-model:page-size="searchParams.size"
|
layout="total, prev, pager, next, sizes"
|
:total="total"
|
@change="getList"
|
/>
|
</div>
|
</div>
|
|
<FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" />
|
|
<!-- 导入机构弹框 -->
|
<el-dialog
|
class="gd-dialog"
|
append-to-body
|
v-model="isShowImportView"
|
title="机构导入"
|
:width="pxToRem(500)"
|
:close-on-click-modal="false"
|
:destroy-on-close="true"
|
@close="handleImportClose"
|
>
|
<el-form class="gd-dialog-form" ref="importFormRef" :model="importParams" :rules="importRules" label-width="140px">
|
<el-form-item label="导出模板">
|
<el-button
|
color="#F2F3F5"
|
type="primary"
|
@click="handleExportTemplate"
|
>
|
下载模板
|
</el-button>
|
</el-form-item>
|
<el-form-item label="上传文件" prop="file">
|
|
<el-upload class="avatar-uploader" action="" :show-file-list="false" :before-upload="onImportFileBefore">
|
<el-button type="primary">点击上传</el-button>
|
</el-upload>
|
<div class="upload-tip">
|
{{ importFileName }}
|
</div>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<el-button color="#F2F3F5" @click="isShowImportView = false">取消</el-button>
|
<el-button
|
|
color="#4C34FF"
|
:loading="importSubmitting"
|
:disabled="importSubmitting"
|
@click="submitImport(importFormRef)"
|
>
|
导入
|
</el-button>
|
</template>
|
</el-dialog>
|
</basic-container>
|
</template>
|
|
<script setup>
|
import { Search, RefreshRight, Plus, Delete, Upload, Download } from '@element-plus/icons-vue'
|
import { onMounted, ref, provide, nextTick } from 'vue'
|
import { ElMessage, ElMessageBox, ElUpload } from 'element-plus'
|
import FormDiaLog from './FormDiaLog.vue'
|
import RegionSelect from '@/components/RegionSelect/main.vue'
|
import {
|
agenciesPageApi,
|
agenciesRemoveApi,
|
agenciesImportApi,
|
agenciesExportApi,
|
agenciesExportTemplateApi,
|
agenciesSubmitApi
|
} from './agenciesApi'
|
import { getDictionaryByCode } from '@/api/system/dictbiz'
|
import { getDictLabel } from '@ztzf/utils'
|
import { pxToRem } from '@/utils/rem'
|
// 初始化查询参数
|
const initSearchParams = () => ({
|
deptName: '', // 机构名称
|
deptCode: '', // 机构编码
|
areaCode: '', // 所属区划
|
current: 1, // 当前页
|
size: 10, // 每页大小
|
})
|
const searchParams = ref(initSearchParams()) // 查询参数
|
const total = ref(0) // 总条数
|
const loading = ref(true) // 列表加载中
|
const list = ref([]) // 列表数据
|
const queryParamsRef = ref(null) // 查询表单实例
|
const dialogRef = ref(null) // 弹框实例
|
const dialogVisible = ref(false)
|
const regionOptions = ref([]) // 区域选项
|
const dictObj = ref({}) // 字典对象
|
const selectedFiles = ref([]) // 勾选的文件列表
|
// 导入机构相关
|
const isShowImportView = ref(false)
|
const importFileName = ref('')
|
const importParams = ref({
|
isCovered: '0',
|
file: '',
|
})
|
const importFormRef = ref()
|
const importSubmitting = ref(false)
|
const importRules = ref({
|
file: [{ required: true, message: '请上传文件', trigger: ['change'] }],
|
})
|
|
// 导出加载状态
|
const exportLoading = ref(false)
|
|
// 模板导出加载状态
|
const templateExportLoading = ref(false)
|
|
provide('regionOptions', regionOptions)
|
provide('dictObj', dictObj)
|
|
// 获取字典列表
|
function getDictList() {
|
getDictionaryByCode('institutionStatus').then(res => {
|
dictObj.value = res.data.data
|
})
|
}
|
// 获取列表
|
async function getList() {
|
loading.value = true
|
try {
|
const res = await agenciesPageApi(searchParams.value)
|
list.value = res?.data?.data?.records ?? []
|
total.value = res?.data?.data?.total ?? 0
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 查询
|
function handleSearch() {
|
searchParams.value.current = 1
|
getList()
|
}
|
|
// 重置查询
|
function resetForm() {
|
queryParamsRef.value?.resetFields()
|
searchParams.value.current = 1
|
getList()
|
}
|
|
// 新增/编辑/查看 弹框
|
function openForm(mode, row) {
|
dialogVisible.value = true
|
nextTick(() => {
|
dialogRef.value?.open({ mode, row })
|
})
|
}
|
|
// 删除
|
async function handleDelete(row) {
|
await ElMessageBox.confirm('确认删除该条记录吗?', '提示', {
|
type: 'warning',
|
customClass: 'gd-confirm-custom',
|
confirmButtonClass: 'gd-confirm-button',
|
cancelButtonClass: 'gd-confirm-cancel-button',
|
})
|
await agenciesRemoveApi({ ids: row.id })
|
ElMessage.success('删除成功')
|
getList()
|
}
|
|
// 切换机构状态
|
async function toggleStatus(row) {
|
// 计算目标状态:当前为1则切换为0,当前为0则切换为1
|
const targetStatus = row.status === 1 ? 0 : 1
|
const actionText = targetStatus === 0 ? '禁用' : '启用'
|
|
await ElMessageBox.confirm(`确认${actionText}该机构吗?`, '提示', {
|
type: 'warning',
|
customClass: 'gd-confirm-custom',
|
confirmButtonClass: 'gd-confirm-button',
|
cancelButtonClass: 'gd-confirm-cancel-button',
|
})
|
|
try {
|
await agenciesSubmitApi({ ...row, status: targetStatus })
|
ElMessage.success(`${actionText}成功`)
|
getList()
|
} catch (error) {
|
ElMessage.error(`${actionText}失败`)
|
}
|
}
|
|
// 导入机构
|
function handleImport() {
|
isShowImportView.value = true
|
}
|
|
// 导入机构弹框关闭
|
function handleImportClose() {
|
importFileName.value = ''
|
importParams.value = {
|
isCovered: '0',
|
file: '',
|
}
|
}
|
|
// 勾选值设置
|
function handleSelectionChange(rows) {
|
selectedFiles.value = rows
|
}
|
|
// 导出模板
|
async function handleExportTemplate() {
|
templateExportLoading.value = true
|
try {
|
const res = await agenciesExportTemplateApi()
|
const blob = new Blob([res.data])
|
const url = URL.createObjectURL(blob)
|
const a = document.createElement('a')
|
a.href = url
|
a.download = `机构导入模板.xlsx`
|
document.body.appendChild(a)
|
a.click()
|
document.body.removeChild(a)
|
URL.revokeObjectURL(url)
|
} catch (error) {
|
console.error('导出模板失败:', error)
|
} finally {
|
templateExportLoading.value = false
|
}
|
}
|
|
// 上传文件前处理
|
function onImportFileBefore(file) {
|
// 检查文件类型
|
const allowedTypes = ['.xlsx', '.xls']
|
const fileExtension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase()
|
if (!allowedTypes.includes(fileExtension)) {
|
ElMessage.error('请上传Excel文件(.xlsx 或 .xls)')
|
return false
|
}
|
|
// 保存文件名和文件对象
|
importFileName.value = file.name
|
importParams.value.file = file
|
ElMessage.success('上传成功')
|
|
return false // 阻止组件的默认上传行为
|
}
|
|
// 提交导入
|
async function submitImport(formValidate) {
|
if (!formValidate) return
|
await formValidate.validate(async (valid, fields) => {
|
if (valid) {
|
importSubmitting.value = true
|
try {
|
if (!importParams.value.file) {
|
ElMessage.error('请先上传文件')
|
return
|
}
|
|
// 构建表单数据并调用导入接口
|
let data = new FormData()
|
data.append('file', importParams.value.file)
|
|
const res = await agenciesImportApi(data, { isCovered: importParams.value.isCovered })
|
if (res.data.code === 200) {
|
ElMessage.success('导入成功')
|
isShowImportView.value = false
|
getList()
|
} else {
|
ElMessage.error(res.msg || '导入失败')
|
}
|
} finally {
|
importSubmitting.value = false
|
}
|
}
|
})
|
}
|
|
// 导出机构
|
async function handleExport() {
|
// 检查是否有选中的数据
|
if (selectedFiles.value.length === 0) {
|
ElMessage.warning('请选择要导出的机构')
|
return
|
}
|
|
exportLoading.value = true
|
try {
|
const params = {}
|
params.deptIds = selectedFiles.value.map(i => i.id)
|
// 调用导出API
|
const res = await agenciesExportApi(params)
|
const blob = new Blob([res.data])
|
const url = URL.createObjectURL(blob)
|
const a = document.createElement('a')
|
a.href = url
|
// `机构列表${new Date().getTime()}.xlsx`
|
const fileName = `机构列表.xlsx`
|
a.download = fileName
|
|
document.body.appendChild(a)
|
a.click()
|
document.body.removeChild(a)
|
URL.revokeObjectURL(url)
|
} catch (error) {
|
console.error('导出失败:', error)
|
} finally {
|
exportLoading.value = false
|
}
|
}
|
|
onMounted(() => {
|
getDictList()
|
getList()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.upload-tip {
|
margin-left: 5px;
|
}
|
</style>
|