|
|
@@ -87,6 +87,42 @@
|
|
|
<span v-else class="muted">—</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="工作人员"
|
|
|
+ min-width="160"
|
|
|
+ align="left"
|
|
|
+ header-align="center"
|
|
|
+ class-name="hospital-info-col"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <template v-if="row.staffNames && row.staffNames.length">
|
|
|
+ <div v-for="(name, idx) in row.staffNames" :key="idx" class="hospital-cell-line">
|
|
|
+ {{ name }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <span v-else class="muted">—</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="负责人"
|
|
|
+ min-width="140"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <template v-if="row.leaderNames && row.leaderNames.length">
|
|
|
+ <el-tag
|
|
|
+ v-for="(name, idx) in row.leaderNames"
|
|
|
+ :key="idx"
|
|
|
+ type="success"
|
|
|
+ size="small"
|
|
|
+ style="margin: 2px"
|
|
|
+ >{{ name }}</el-tag
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <el-tag v-else type="info" size="small">未设置</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column
|
|
|
prop="remark"
|
|
|
label="备注"
|
|
|
@@ -110,16 +146,19 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
label="操作"
|
|
|
- min-width="160"
|
|
|
+ min-width="300"
|
|
|
fixed="right"
|
|
|
align="center"
|
|
|
header-align="center"
|
|
|
>
|
|
|
<template #default="{ row }">
|
|
|
- <div style="display: flex; justify-content: center; gap: 8px">
|
|
|
+ <div style="display: flex; justify-content: center; gap: 8px; flex-wrap: wrap">
|
|
|
<el-button class="btn-op-item primary" @click="openHospitalDialog(row)">
|
|
|
地区医院配置
|
|
|
</el-button>
|
|
|
+ <el-button class="btn-op-item primary" @click="openStaffDialog(row)">
|
|
|
+ 地区人员配置
|
|
|
+ </el-button>
|
|
|
<el-dropdown trigger="hover" @command="(cmd: string) => handleDropdownCommand(cmd, row)">
|
|
|
<el-button class="btn-op-item">
|
|
|
<el-icon><More /></el-icon>
|
|
|
@@ -360,6 +399,187 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
+ <el-dialog
|
|
|
+ v-model="staffDialogVisible"
|
|
|
+ :title="staffDialogTitle"
|
|
|
+ width="860px"
|
|
|
+ class="dialog-form-layout"
|
|
|
+ align-center
|
|
|
+ append-to-body
|
|
|
+ modal-class="protocol-dialog-mask"
|
|
|
+ destroy-on-close
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @closed="onStaffDialogClosed"
|
|
|
+ >
|
|
|
+ <div class="hospital-dialog-head">
|
|
|
+ <span class="muted">当前地区:{{ currentRegionName }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="list-toolbar hospital-toolbar">
|
|
|
+ <div class="list-toolbar-row">
|
|
|
+ <div class="list-toolbar-selected">
|
|
|
+ 已选 <span class="sel-num">{{ staffSelected.length }}</span> 项
|
|
|
+ </div>
|
|
|
+ <el-button class="btn-main" type="primary" @click="handleAddStaff">
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ 添加人员
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ class="btn-ghost"
|
|
|
+ type="danger"
|
|
|
+ :disabled="staffSelected.length === 0"
|
|
|
+ @click="handleBatchDeleteStaff"
|
|
|
+ >
|
|
|
+ <el-icon><Delete /></el-icon>
|
|
|
+ 批量移除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="list-body list-wrap hospital-table-wrap">
|
|
|
+ <el-table
|
|
|
+ class="list-table"
|
|
|
+ :data="staffTable"
|
|
|
+ v-loading="staffLoading"
|
|
|
+ stripe
|
|
|
+ row-key="id"
|
|
|
+ max-height="360"
|
|
|
+ @selection-change="onStaffSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
|
|
+ <el-table-column
|
|
|
+ type="index"
|
|
|
+ label="序号"
|
|
|
+ min-width="68"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ prop="userName"
|
|
|
+ label="姓名"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ prop="userNo"
|
|
|
+ label="工号"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ prop="deptName"
|
|
|
+ label="部门"
|
|
|
+ min-width="140"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span v-if="row.deptName">{{ row.deptName }}</span>
|
|
|
+ <span v-else class="muted">—</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="是否负责人"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag v-if="row.isLeader" type="success" size="small">负责人</el-tag>
|
|
|
+ <el-tag v-else type="info" size="small">否</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="操作"
|
|
|
+ min-width="260"
|
|
|
+ fixed="right"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button class="btn-op-item primary" @click="toggleStaffLeader(row)">
|
|
|
+ {{ row.isLeader ? '取消负责人' : '设为负责人' }}
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-op-item" @click="handleDeleteStaff(row)">移除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div class="pagination list-pager-bar">
|
|
|
+ <el-pagination
|
|
|
+ :current-page="staffPagination.page"
|
|
|
+ :page-size="staffPagination.pageSize"
|
|
|
+ :total="staffPagination.total"
|
|
|
+ :page-sizes="[10, 20, 50]"
|
|
|
+ layout="total, sizes, prev, pager, next"
|
|
|
+ @size-change="
|
|
|
+ (val) => (
|
|
|
+ (staffPagination.page = 1), (staffPagination.pageSize = val), loadStaff()
|
|
|
+ )
|
|
|
+ "
|
|
|
+ @current-change="(val) => ((staffPagination.page = val), loadStaff())"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="staffAddVisible"
|
|
|
+ title="添加人员"
|
|
|
+ width="520px"
|
|
|
+ class="dialog-form-layout"
|
|
|
+ align-center
|
|
|
+ append-to-body
|
|
|
+ modal-class="protocol-dialog-mask"
|
|
|
+ destroy-on-close
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <el-form label-position="top">
|
|
|
+ <el-form-item label="系统人员" required>
|
|
|
+ <el-select
|
|
|
+ v-model="staffAddForm.userId"
|
|
|
+ filterable
|
|
|
+ remote
|
|
|
+ clearable
|
|
|
+ :remote-method="remoteSearchUsers"
|
|
|
+ :loading="staffUserLoading"
|
|
|
+ placeholder="搜索姓名/账号"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="u in staffUserOptions"
|
|
|
+ :key="u.id"
|
|
|
+ :label="`${u.nickName}(${u.userNo})`"
|
|
|
+ :value="u.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设为负责人">
|
|
|
+ <el-switch v-model="staffAddForm.isLeader" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button class="btn-ghost" @click="staffAddVisible = false">
|
|
|
+ <el-icon><Close /></el-icon>
|
|
|
+ 取消
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ class="btn-main"
|
|
|
+ type="primary"
|
|
|
+ :loading="staffAddLoading"
|
|
|
+ @click="submitAddStaff"
|
|
|
+ >
|
|
|
+ <el-icon><Check /></el-icon>
|
|
|
+ 确定
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ <template #footer>
|
|
|
+ <el-button class="btn-ghost" @click="staffDialogVisible = false">
|
|
|
+ <el-icon><Close /></el-icon>
|
|
|
+ 关闭
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
<SystemViewDialog
|
|
|
v-model:visible="viewVisible"
|
|
|
:title="viewRow?.regionName || '地区详情'"
|
|
|
@@ -388,7 +608,12 @@
|
|
|
fetchHospitalList,
|
|
|
fetchCreateHospital,
|
|
|
fetchUpdateHospital,
|
|
|
- fetchDeleteHospital
|
|
|
+ fetchDeleteHospital,
|
|
|
+ fetchRegionStaffList,
|
|
|
+ fetchCreateRegionStaff,
|
|
|
+ fetchUpdateRegionStaff,
|
|
|
+ fetchDeleteRegionStaff,
|
|
|
+ fetchUserList
|
|
|
} from '@/api/admin'
|
|
|
defineOptions({ name: 'BizCollectionRegion' })
|
|
|
|
|
|
@@ -434,6 +659,10 @@
|
|
|
if (!row) return []
|
|
|
const hospitals =
|
|
|
row.hospitalNames && row.hospitalNames.length > 0 ? row.hospitalNames.join('、') : '无'
|
|
|
+ const staffs =
|
|
|
+ row.staffNames && row.staffNames.length > 0 ? row.staffNames.join('、') : '无'
|
|
|
+ const leaders =
|
|
|
+ row.leaderNames && row.leaderNames.length > 0 ? row.leaderNames.join('、') : '未设置'
|
|
|
return [
|
|
|
{
|
|
|
title: '基本信息',
|
|
|
@@ -441,6 +670,13 @@
|
|
|
{ label: '地区名称', value: row.regionName },
|
|
|
{ label: '创建时间', value: row.createTime },
|
|
|
{ label: '关联医院', value: hospitals, span: true },
|
|
|
+ { label: '工作人员', value: staffs, span: true },
|
|
|
+ {
|
|
|
+ label: '负责人',
|
|
|
+ value: row.leaderNames?.length ? leaders : '未设置',
|
|
|
+ tagType: row.leaderNames?.length ? 'success' : 'info',
|
|
|
+ span: true
|
|
|
+ },
|
|
|
{ label: '备注', value: row.remark, span: true }
|
|
|
]
|
|
|
}
|
|
|
@@ -674,6 +910,156 @@
|
|
|
await loadHospitals()
|
|
|
}, fullscreenLoadingText.batchDelete)
|
|
|
}
|
|
|
+
|
|
|
+ const staffDialogVisible = ref(false)
|
|
|
+ const staffDialogTitle = ref('地区人员配置')
|
|
|
+ const staffTable = ref<Api.BizCollectionRegionStaff.StaffItem[]>([])
|
|
|
+ const staffSelected = ref<Api.BizCollectionRegionStaff.StaffItem[]>([])
|
|
|
+ const staffLoading = ref(false)
|
|
|
+ const staffPagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
|
|
+ const staffAddVisible = ref(false)
|
|
|
+ const staffAddLoading = ref(false)
|
|
|
+ const staffAddForm = reactive<{ userId: string; isLeader: boolean }>({
|
|
|
+ userId: '',
|
|
|
+ isLeader: false
|
|
|
+ })
|
|
|
+ const staffUserOptions = ref<Api.User.UserItem[]>([])
|
|
|
+ const staffUserLoading = ref(false)
|
|
|
+ const boundStaffUserIds = ref<Set<string>>(new Set())
|
|
|
+
|
|
|
+ function onStaffSelectionChange(rows: Api.BizCollectionRegionStaff.StaffItem[]) {
|
|
|
+ staffSelected.value = rows
|
|
|
+ }
|
|
|
+
|
|
|
+ function openStaffDialog(row: Api.BizCollectionRegion.RegionItem) {
|
|
|
+ currentRegionId.value = row.id
|
|
|
+ currentRegionName.value = row.regionName || ''
|
|
|
+ staffDialogTitle.value = '地区人员配置'
|
|
|
+ staffPagination.page = 1
|
|
|
+ staffSelected.value = []
|
|
|
+ staffDialogVisible.value = true
|
|
|
+ loadStaff()
|
|
|
+ }
|
|
|
+
|
|
|
+ async function refreshBoundStaffUserIds() {
|
|
|
+ if (!currentRegionId.value) {
|
|
|
+ boundStaffUserIds.value = new Set()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const res = await fetchRegionStaffList(currentRegionId.value, {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 500
|
|
|
+ })
|
|
|
+ boundStaffUserIds.value = new Set((res.list || []).map((s) => s.userId))
|
|
|
+ } catch {
|
|
|
+ boundStaffUserIds.value = new Set(staffTable.value.map((s) => s.userId))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function loadStaff() {
|
|
|
+ if (!currentRegionId.value) return
|
|
|
+ staffLoading.value = true
|
|
|
+ try {
|
|
|
+ const res = await fetchRegionStaffList(currentRegionId.value, {
|
|
|
+ page: staffPagination.page,
|
|
|
+ pageSize: staffPagination.pageSize
|
|
|
+ })
|
|
|
+ staffTable.value = res.list || []
|
|
|
+ staffPagination.total = res.total ?? 0
|
|
|
+ await refreshBoundStaffUserIds()
|
|
|
+ } finally {
|
|
|
+ staffLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function onStaffDialogClosed() {
|
|
|
+ staffTable.value = []
|
|
|
+ staffSelected.value = []
|
|
|
+ boundStaffUserIds.value = new Set()
|
|
|
+ loadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleAddStaff() {
|
|
|
+ staffAddForm.userId = ''
|
|
|
+ staffAddForm.isLeader = false
|
|
|
+ staffUserOptions.value = []
|
|
|
+ staffAddVisible.value = true
|
|
|
+ remoteSearchUsers('')
|
|
|
+ }
|
|
|
+
|
|
|
+ async function remoteSearchUsers(query: string) {
|
|
|
+ staffUserLoading.value = true
|
|
|
+ try {
|
|
|
+ const res = await fetchUserList({
|
|
|
+ page: 1,
|
|
|
+ pageSize: 20,
|
|
|
+ keyword: query || undefined,
|
|
|
+ status: '1'
|
|
|
+ })
|
|
|
+ const bound = boundStaffUserIds.value
|
|
|
+ staffUserOptions.value = (res.list || []).filter((u) => !bound.has(u.id))
|
|
|
+ } finally {
|
|
|
+ staffUserLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function submitAddStaff() {
|
|
|
+ if (!staffAddForm.userId) {
|
|
|
+ ElMessage.warning('请选择系统人员')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ staffAddLoading.value = true
|
|
|
+ try {
|
|
|
+ await fetchCreateRegionStaff(currentRegionId.value, {
|
|
|
+ userId: staffAddForm.userId,
|
|
|
+ isLeader: staffAddForm.isLeader
|
|
|
+ })
|
|
|
+ ElMessage.success('添加成功')
|
|
|
+ staffAddVisible.value = false
|
|
|
+ staffAddForm.userId = ''
|
|
|
+ staffAddForm.isLeader = false
|
|
|
+ await loadStaff()
|
|
|
+ await loadData()
|
|
|
+ } catch {
|
|
|
+ /* */
|
|
|
+ } finally {
|
|
|
+ staffAddLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function toggleStaffLeader(row: Api.BizCollectionRegionStaff.StaffItem) {
|
|
|
+ await fetchUpdateRegionStaff(currentRegionId.value, row.id, { isLeader: !row.isLeader })
|
|
|
+ ElMessage.success('已更新')
|
|
|
+ await loadStaff()
|
|
|
+ await loadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ async function handleDeleteStaff(row: Api.BizCollectionRegionStaff.StaffItem) {
|
|
|
+ await ElMessageBox.confirm(`确定移除「${row.userName}」吗?`, '提示', { type: 'warning' })
|
|
|
+ await fetchDeleteRegionStaff(currentRegionId.value, row.id)
|
|
|
+ ElMessage.success('已移除')
|
|
|
+ await loadStaff()
|
|
|
+ await loadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ async function handleBatchDeleteStaff() {
|
|
|
+ if (!staffSelected.value.length) return
|
|
|
+ await ElMessageBox.confirm(`确定移除选中的 ${staffSelected.value.length} 人吗?`, '提示', {
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ const rid = currentRegionId.value
|
|
|
+ await withFullscreenLoading(async () => {
|
|
|
+ for (const row of staffSelected.value) {
|
|
|
+ await fetchDeleteRegionStaff(rid, row.id)
|
|
|
+ }
|
|
|
+ ElMessage.success('已移除')
|
|
|
+ staffSelected.value = []
|
|
|
+ await loadStaff()
|
|
|
+ await loadData()
|
|
|
+ }, fullscreenLoadingText.batchDelete)
|
|
|
+ }
|
|
|
+
|
|
|
// 输入检索条件时自动搜索(防抖 300ms)
|
|
|
watchDebounced(
|
|
|
searchForm,
|