From 280ef5100bece9b40ac51736aef037704a52a4ca Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期四, 30 七月 2026 14:58:52 +0800
Subject: [PATCH] update
---
frontend/src/views/GuideUserDetailView.vue | 99 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 90 insertions(+), 9 deletions(-)
diff --git a/frontend/src/views/GuideUserDetailView.vue b/frontend/src/views/GuideUserDetailView.vue
index 9bbaf87..c6e6d53 100644
--- a/frontend/src/views/GuideUserDetailView.vue
+++ b/frontend/src/views/GuideUserDetailView.vue
@@ -3,13 +3,25 @@
import { useRoute, useRouter } from 'vue-router'
import { ArrowLeft, Check, Plus, Upload } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
-import { getGuideUserDetail, updateGuideUserDetail, updateGuideWhitelist } from '@/api/users'
+import {
+ addGuideScenicConfig,
+ deleteGuideScenicConfig,
+ getGuideUserDetail,
+ updateGuideUserDetail,
+ updateGuideWhitelist,
+} from '@/api/users'
+import { getScenicSpots } from '@/api/scenicSpots'
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const saving = ref(false)
const user = ref(null)
+const scenicOptions = ref([])
+const scenicPopoverVisible = ref(false)
+const selectedScenicSpotId = ref(null)
+const scenicSaving = ref(false)
+const deletingScenicConfigId = ref(null)
const documentImages = computed(() => [
{ key: 'idCardFrontUrl', label: '身份证(正)*' },
@@ -21,6 +33,10 @@
const formatDateTime = (value) => value ? value.replace('T', ' ').slice(0, 19) : '-'
const displayValue = (value) => value === null || value === undefined || value === '' ? '-' : value
const guideStatusLabel = (status) => ({ 0: '禁用', 1: '启用', 2: '待审核', 3: '已注销' }[status] || '未知')
+const availableScenicOptions = computed(() => {
+ const configuredNames = new Set((user.value?.scenicConfigs || []).map((item) => item.scenicName))
+ return scenicOptions.value.filter((item) => !configuredNames.has(item.scenicName))
+})
const loadDetail = async () => {
loading.value = true
@@ -31,16 +47,55 @@
}
}
+const loadScenicOptions = async () => {
+ const result = await getScenicSpots({ page: 1, size: 100, status: 1 })
+ scenicOptions.value = result.records || []
+}
+
const updateWhitelist = async (enabled) => {
await updateGuideWhitelist(user.value.id, enabled)
ElMessage.success(enabled ? '已加入自动禁用白名单' : '已移出自动禁用白名单')
}
-const addScenic = async () => {
+const openScenicSelector = () => {
+ selectedScenicSpotId.value = null
+ if (!availableScenicOptions.value.length) {
+ ElMessage.info('暂无可添加的启用景区')
+ return
+ }
+ scenicPopoverVisible.value = true
+}
+
+const saveSelectedScenic = async (scenicSpotId) => {
+ if (!scenicSpotId || scenicSaving.value) return
+ scenicSaving.value = true
try {
- const { value: scenicName } = await ElMessageBox.prompt('请输入景区名称', '添加景区配置', { inputValidator: (value) => !!value?.trim() || '景区名称不能为空' })
- const { value: cityName } = await ElMessageBox.prompt('请输入城市名称', '添加景区配置')
- user.value.scenicConfigs.push({ scenicName: scenicName.trim(), cityName: cityName?.trim() || '' })
+ user.value.scenicConfigs = await addGuideScenicConfig(user.value.id, scenicSpotId)
+ scenicPopoverVisible.value = false
+ selectedScenicSpotId.value = null
+ ElMessage.success('景区配置已保存')
+ } catch (error) {
+ selectedScenicSpotId.value = null
+ throw error
+ } finally {
+ scenicSaving.value = false
+ }
+}
+
+const removeScenic = async (config) => {
+ try {
+ await ElMessageBox.confirm(`确认删除“${config.scenicName}”配置吗?`, '删除景区配置', {
+ type: 'warning',
+ confirmButtonText: '删除',
+ cancelButtonText: '取消',
+ })
+ deletingScenicConfigId.value = config.id
+ try {
+ user.value.scenicConfigs = await deleteGuideScenicConfig(user.value.id, config.id)
+ ElMessage.success('景区配置已删除')
+ } finally {
+ deletingScenicConfigId.value = null
+ }
} catch (error) {
if (error !== 'cancel' && error !== 'close') throw error
}
@@ -64,7 +119,6 @@
qualificationCertificateUrl: user.value.qualificationCertificateUrl,
teamId: user.value.teamId,
wechatOpenId: user.value.wechatOpenId,
- scenicConfigs: user.value.scenicConfigs,
})
ElMessage.success('导游详情保存成功')
} finally {
@@ -82,7 +136,7 @@
query: { guideId: user.value.id, guideName: user.value.realName },
})
-onMounted(loadDetail)
+onMounted(() => Promise.all([loadDetail(), loadScenicOptions()]))
</script>
<template>
@@ -158,11 +212,37 @@
<el-table-column prop="scenicName" label="景区名称" align="center" />
<el-table-column prop="cityName" label="城市" align="center" />
<el-table-column label="操作" align="center">
- <template #default="{ $index }"><el-button link type="danger" @click="user.scenicConfigs.splice($index, 1)">删除</el-button></template>
+ <template #default="{ row }">
+ <el-button
+ link
+ type="danger"
+ :loading="deletingScenicConfigId === row.id"
+ @click="removeScenic(row)"
+ >删除</el-button>
+ </template>
</el-table-column>
<template #empty><span class="empty-text">暂无景区配置</span></template>
</el-table>
- <el-button class="add-scenic" type="primary" :icon="Plus" @click="addScenic">添加</el-button>
+ <el-popover v-model:visible="scenicPopoverVisible" placement="bottom-end" :width="320" trigger="manual">
+ <el-select
+ v-model="selectedScenicSpotId"
+ class="scenic-selector"
+ filterable
+ placeholder="请选择景区,选择后自动保存"
+ :loading="scenicSaving"
+ @change="saveSelectedScenic"
+ >
+ <el-option
+ v-for="item in availableScenicOptions"
+ :key="item.id"
+ :label="`${item.scenicName}(${item.cityName || '未配置城市'})`"
+ :value="item.id"
+ />
+ </el-select>
+ <template #reference>
+ <el-button class="add-scenic" type="primary" :icon="Plus" @click="openScenicSelector">添加</el-button>
+ </template>
+ </el-popover>
</div>
<div class="whitelist-row">
@@ -216,6 +296,7 @@
.scenic-table { margin-left: 86px; }
.empty-text { color: #9aa5b1; }
.add-scenic { display: block; margin: 12px 0 0 auto; }
+.scenic-selector { width: 100%; }
.whitelist-row { display: flex; align-items: center; gap: 18px; margin-top: 22px; }
.collection-section { min-height: 150px; }
.section-heading { display: flex; align-items: baseline; gap: 24px; }
--
Gitblit v1.7.1