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