大数据模型练习4

html 复制代码
<template>
  <el-dialog v-model="visible" title="模板管理" width="900px">
    <el-table :data="searchStore.templates" style="width: 100%" stripe>
      <el-table-column prop="id" label="编号" width="60" />

      <el-table-column label="模板类型" width="100">
        <template #default="scope">
          <el-tag :type="scope.row.type === 'public' ? 'warning' : 'info'">
            {{ scope.row.type === 'public' ? '公用' : '个人' }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column label="模板名称" min-width="150">
        <template #default="scope">
          <el-button link type="primary" @click="handleApply(scope.row)">
            {{ scope.row.name }}
          </el-button>
        </template>
      </el-table-column>

      <el-table-column prop="creator" label="创建人" width="120" />
      <el-table-column prop="createTime" label="创建时间" width="180" />

      <el-table-column label="设为默认" width="100" align="center">
        <template #default="scope">
          <el-switch
            :model-value="scope.row.isDefault"
            :loading="switchLoadingMap[scope.row.id]"
            :disabled="scope.row.isDefault"
            @change="() => handleSetDefault(scope.row)"
          />
        </template>
      </el-table-column>

      <el-table-column label="操作" width="120" fixed="right">
        <template #default="scope">
          <div class="action-buttons">
            <el-tooltip content="分享模板" placement="top" v-if="scope.row.permission?.canShare">
              <el-button link type="primary" :icon="Share" @click="handleShareOpen(scope.row)" />
            </el-tooltip>

            <el-tooltip content="删除模板" placement="top" v-if="scope.row.permission?.canDelete">
              <el-button link type="danger" :icon="Delete" @click="handleDelete(scope.row)" />
            </el-tooltip>
          </div>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>

  <el-dialog v-model="shareVisible" title="共享模板" width="450px" append-to-body>
    <el-form label-position="top">
      <el-form-item label="模板名称">
        <el-input v-model="currentShareRow.name" disabled />
      </el-form-item>
      <el-form-item label="共享给 (个人/群组)">
        <el-input v-model="shareTarget" placeholder="请输入工号或群组名" />
      </el-form-item>
      <el-form-item label="描述">
        <el-input type="textarea" placeholder="请输入描述信息" />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="shareVisible = false" :disabled="shareSubmitting">取消</el-button>
      <el-button type="primary" @click="handleShareSubmit" :loading="shareSubmitting">
        确定分享
      </el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { computed, ref, reactive } from 'vue'
import { useSearchStore } from '../../stores/searchStore'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Share, Delete } from '@element-plus/icons-vue'

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const searchStore = useSearchStore()

const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val),
})

// === 1. 设为默认的相关逻辑 ===
const switchLoadingMap = reactive({}) // 存储每一行的 loading 状态 { id: boolean }

// 定义超时时长 (毫秒)
const API_TIMEOUT = 3000

const handleSetDefault = async (row) => {
  // 如果已经是默认的,不做操作(UI上其实已经disable了)
  if (row.isDefault) return

  // 1. 开启 Loading
  switchLoadingMap[row.id] = true

  try {
    // 2. 构造超时 Promise
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error('请求超时,请稍后重试'))
      }, API_TIMEOUT)
    })

    // 3. Race: 真实请求 vs 超时
    await Promise.race([
      searchStore.apiSetDefault(row.id), // 调用 Store 的异步 Action
      timeoutPromise,
    ])

    // 成功后,Loading 会在 finally 移除,State 由 Store 更新
    ElMessage.success('设置默认模板成功')
  } catch (error) {
    // 4. 失败或超时处理
    console.error(error)
    ElMessage.error(error.message || '设置失败')

    // 注意:因为我们绑定的是 model-value 而不是 v-model,
    // 且数据更新依赖 store,所以失败时只要不改 store,Switch 就会自动保持原样。
  } finally {
    // 5. 关闭 Loading
    switchLoadingMap[row.id] = false
  }
}

// === 2. 删除相关逻辑 ===
const handleDelete = (row) => {
  ElMessageBox.confirm(`确定删除模板 "${row.name}" 吗?`, '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    beforeClose: async (action, instance, done) => {
      if (action === 'confirm') {
        instance.confirmButtonLoading = true // 让 MessageBox 的按钮转圈
        instance.confirmButtonText = '删除中...'

        try {
          await searchStore.apiDeleteTemplate(row.id)
          ElMessage.success('删除成功')
          done()
        } catch (e) {
          ElMessage.error('删除失败')
        } finally {
          instance.confirmButtonLoading = false
        }
      } else {
        done()
      }
    },
  })
    .then(() => {
      // confirm 回调
    })
    .catch(() => {
      // cancel 回调
    })
}

// === 3. 分享相关逻辑 ===
const shareVisible = ref(false)
const shareSubmitting = ref(false)
const currentShareRow = ref({})
const shareTarget = ref('')

const handleShareOpen = (row) => {
  currentShareRow.value = { ...row }
  shareTarget.value = '' // 重置输入
  shareVisible.value = true
}

const handleShareSubmit = async () => {
  if (!shareTarget.value) {
    ElMessage.warning('请输入分享对象')
    return
  }

  shareSubmitting.value = true
  try {
    await searchStore.apiShareTemplate(currentShareRow.value.id, shareTarget.value)
    ElMessage.success('分享成功')
    shareVisible.value = false
  } catch (error) {
    ElMessage.error('分享失败,请重试')
  } finally {
    shareSubmitting.value = false
  }
}

// 点击名称应用模板
const handleApply = (row) => {
  searchStore.applyTemplate(row)
  visible.value = false
}
</script>

<style scoped>
.action-buttons {
  display: flex;
  gap: 8px;
  justify-content: center;
}
</style>
相关推荐
苏州IT威翰德4 小时前
算力资产“续命”专家:苏州威翰德科技赋能NVIDIA高端AI芯片芯片级维修
大数据·人工智能
Miao121315 小时前
某海外住宿平台如何在大规模场景下实现指标一致性:Minerva 指标平台实践
大数据·数据库·人工智能
SeaTunnel5 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
爱自由的代码工6 小时前
游戏沉默用户怎么激活?一套可执行的步骤、指标与复盘方法
大数据·游戏·游戏发行·游戏运营·游戏分发
miaowu3577 小时前
AI智能体推动数字化转型:从流程自动化到决策辅助的完整路线图
大数据·人工智能·自动化
互联网江湖7 小时前
珞石机器人:向左科技股,向右零部件制造商?
大数据·人工智能
CRMEB系统商城7 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
Leo.yuan7 小时前
数据仓库建设怎么做?从源数据到分析报表全流程讲清
大数据·分布式·spark
pftn9 小时前
从0到1搭建具身智能数据飞轮:Ray + Kafka + LanceDB 全链路实战
大数据
Web3_Daisy10 小时前
什么是 Robinhood Chain?
大数据·人工智能·web3·区块链