<template> <div class="block"> <div class="flex justify-between items-center mb-5"> <search v-model="params.customsPassName" @change="getList"></search> <div class="filter"> <div class="select"> <el-select v-model="params.isEnable" placeholder="启用状态" size="large" clearable> <el-option v-for="item in enables" :key="item.id" :label="item.name" :value="item.id" /> </el-select> <img src="@/assets/images/7.png" alt="" class="icon" /> </div> <el-popconfirm :title="delTitle" @confirm.stop="delAll"> <template #reference> <div class="add-btn mr-2"> <el-icon :size="24" color="#fff"> <Delete /> </el-icon> 删除关卡 </div> </template> </el-popconfirm> <div class="add-btn" @click="toAdd"> <img src="@/assets/images/plus.png" alt="" class="icon" /> 新增关卡 </div> </div> </div> <div class="h-[calc(100vh-270px)] overflow-auto" id="tableWrap"> <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> <el-table-column label="移动" width="100"> <template #default="{ row, $index }"> <el-popover placement="right" trigger="hover"> <template #reference> <el-icon class="rotate-90 cursor-pointer" :size="16" color="#877c7c"> <MoreFilled /> </el-icon> </template> <div class="flex items-center mb-2"> <el-input class="w-[80px]" placeholder="请输入" v-model.number="row.serial"></el-input> <el-icon class="ml-2 cursor-pointer" :size="16" color="#877c7c" @click.stop="submitSerial(row, $index, row.serial)"> <Check /> </el-icon> </div> <p class="my-2 cursor-pointer" @click="submitSerial(row, $index, 1)">置顶</p> <p class="cursor-pointer" @click="submitSerial(row, $index, list.length)">置底</p> </el-popover> </template> </el-table-column> <el-table-column type="selection" width="55" /> <el-table-column label="序号" width="80" align="center"> <template #default="{ row, $index }"> {{ $index + 1 }} </template> </el-table-column> <el-table-column prop="customsPassName" label="关卡名称"> <template #default="{ row }"> <div class="flex items-center"> <el-input v-if="row.editing" class="w-[250px]" placeholder="请输入关卡名称" v-model="row.customsPassName"></el-input> <span v-else>{{ row.customsPassName }}</span> <el-icon class="mx-2 cursor-pointer" :size="16" color="#877c7c" @click="edit(row)"> <Check v-if="row.editing" /> <Edit v-else /> </el-icon> <el-icon v-if="row.editing" class="cursor-pointer" :size="16" color="#877c7c" @click="cancel(row)"> <Close /> </el-icon> </div> </template> </el-table-column> <el-table-column prop="creator" label="创建人"></el-table-column> <el-table-column prop="createTime" label="创建时间" sortable="custom"></el-table-column> <el-table-column label="启用关卡" width="140" align="center"> <template #default="{ row }"> <el-switch v-if="row.checkpointId" v-model="row.isEnable" :active-value="1" :inactive-value="0" /> </template> </el-table-column> <el-table-column label="操作" width="140"> <template #default="{ row }"> <el-popconfirm v-if="row.checkpointId" :title="delTitle" @confirm.stop="handleDelete([row.checkpointId])"> <template #reference> <el-button type="text" size="small">删除</el-button> </template> </el-popconfirm> </template> </el-table-column> </el-table> </div> <div class="filter flex justify-end mt-3"> <div class="add-btn" @click="save" v-loading="saveLoading"> 保存 </div> </div> </div> </template> <script setup lang="ts"> import { computed, onMounted, ref, reactive, watch, nextTick } from 'vue'; import { ElMessage } from 'element-plus'; import { Delete, Edit, Check, MoreFilled, Close } from '@element-plus/icons-vue'; import { listPass, savePass, updatePass } from '@/api/config'; import Search from '@/components/Search.vue'; import { useRouter, useRoute } from 'vue-router'; import Cookies from 'js-cookie'; const router = useRouter(); const route = useRoute(); const projectId = +Cookies.get('sand-projectId'); const levelId = +Cookies.get('sand-level'); const height = window.innerHeight - 270; const delTitle: string = '删除关卡后,这个关卡的数据将被删除,确定删除吗?'; const params = reactive({ platformId: 3, customsPassName: '', isEnable: '', }); const enables = ref<Array<any>>([ { id: 0, name: '禁用', }, { id: 1, name: '启用', }, ]); const list = ref<Array<any>>([]); const loading = ref<boolean>(false); const saveLoading = ref<boolean>(false); const multipleSelection = ref<Record<string, any>[]>([]); // 列表 const getList = async () => { loading.value = true; try { const { data } = await listPass(params); data.forEach((e, i) => { e.serial = ''; }); list.value = data; } finally { loading.value = false; } }; onMounted(() => { getList(); }); watch([params, () => route.query], getList); // 保存 const save = async () => { if (saveLoading.value) return false; saveLoading.value = true; // 编辑 const param = list.value .filter((e) => e.checkpointId) .map((e, i) => { e.serialNumber = i + 1; return { checkpointId: e.checkpointId, customsPassName: e.customsPassName, isEnable: e.isEnable, serialNumber: e.serialNumber, }; }); await updatePass(param); // 新增 const addList = list.value.filter((e) => !e.checkpointId); await savePass(addList); getList(); ElMessage.success('保存成功!'); saveLoading.value = false; }; // 输入序号排序 const submitSerial = (row: Record<string, any>, oldIndex: number, newIndex: number) => { if (newIndex) { const temp = list.value.splice(oldIndex, 1); row.serialNumber = newIndex; list.value.splice(newIndex - 1, 0, temp[0]); } }; // 多选 const handleSelectionChange = (val: Record<string, any>[]) => { multipleSelection.value = val; }; // 新增 const toAdd = () => { list.value.push({ customsPassName: '', editing: true, }); nextTick(() => { document.querySelector('#tableWrap').scrollTo({ top: document.querySelector('#tableWrap')?.scrollHeight + 200, behavior: 'smooth', }); }); }; // 编辑 const edit = async (row: Record<string, any>) => { if (!row.editing) { row.oldName = row.customsPassName; } row.editing = !row.editing; }; // 取消 const cancel = async (row: Record<string, any>) => { row.customsPassName = row.oldName; row.editing = !row.editing; }; // 删除 const handleDelete = async (id: number[]) => { const param = id.map((e) => { return { checkpointId: e, isDel: 1, }; }); await updatePass(param); getList(); ElMessage.success('删除成功!'); }; // 批量删除 const delAll = async () => { handleDelete(multipleSelection.value.map((e) => e.checkpointId)); }; </script>