|
|
@@ -0,0 +1,397 @@
|
|
|
+<template>
|
|
|
+ <div class="space-y-6">
|
|
|
+ <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
|
|
+ <div class="border-b border-gray-200 pb-4 mb-6">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <h2 class="text-xl font-semibold text-gray-800 flex items-center gap-2">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
|
+ </svg>
|
|
|
+ 落地页配置管理
|
|
|
+ </h2>
|
|
|
+ <el-button type="primary" @click="handleAdd">
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ 新增配置
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 数据统计 -->
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
|
|
+ <div class="bg-gradient-to-br from-blue-50 to-blue-100 rounded-lg p-4 border border-blue-200">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div>
|
|
|
+ <p class="text-sm text-blue-600 mb-1">配置总数</p>
|
|
|
+ <p class="text-2xl font-bold text-blue-700">{{ pagination.total }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="p-3 bg-blue-200 rounded-lg">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="bg-gradient-to-br from-green-50 to-green-100 rounded-lg p-4 border border-green-200">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div>
|
|
|
+ <p class="text-sm text-green-600 mb-1">当前页数量</p>
|
|
|
+ <p class="text-2xl font-bold text-green-700">{{ confList.length }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="p-3 bg-green-200 rounded-lg">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="bg-gradient-to-br from-purple-50 to-purple-100 rounded-lg p-4 border border-purple-200">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div>
|
|
|
+ <p class="text-sm text-purple-600 mb-1">总页数</p>
|
|
|
+ <p class="text-2xl font-bold text-purple-700">{{ totalPages }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="p-3 bg-purple-200 rounded-lg">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索筛选 -->
|
|
|
+ <div class="mb-6 p-4 bg-gray-50 rounded-lg">
|
|
|
+ <el-form :inline="true" :model="queryForm" class="flex flex-wrap gap-4">
|
|
|
+ <el-form-item label="页面名称">
|
|
|
+ <el-input v-model="queryForm.name" placeholder="请输入页面名称" clearable style="width: 200px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="落地页ID">
|
|
|
+ <el-input v-model="queryForm.pageId" placeholder="请输入落地页ID" clearable style="width: 200px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleQuery">查询</el-button>
|
|
|
+ <el-button @click="handleReset">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 数据表格 -->
|
|
|
+ <el-table
|
|
|
+ :data="confList"
|
|
|
+ style="width: 100%"
|
|
|
+ v-loading="loading"
|
|
|
+ stripe
|
|
|
+ >
|
|
|
+ <el-table-column prop="id" label="ID" width="80" />
|
|
|
+ <el-table-column prop="name" label="页面名称" width="200" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="pageId" label="落地页ID" width="150" />
|
|
|
+ <el-table-column prop="createUserName" label="创建人" width="120" />
|
|
|
+ <el-table-column label="创建时间" width="180">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatDate(row.createTime) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="更新时间" width="180">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatDate(row.updateTime) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="150" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" size="small" link @click="handleEdit(row)">编辑</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <!-- 分页 -->
|
|
|
+ <div class="mt-6 flex justify-end">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="pagination.page"
|
|
|
+ v-model:page-size="pagination.pageSize"
|
|
|
+ :page-sizes="[10, 20, 50, 100]"
|
|
|
+ :total="pagination.total"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增/编辑对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :title="isEdit ? '编辑配置' : '新增配置'"
|
|
|
+ width="500px"
|
|
|
+ @close="handleDialogClose"
|
|
|
+ >
|
|
|
+ <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
|
|
+ <el-form-item label="页面名称" prop="name">
|
|
|
+ <el-input v-model="form.name" placeholder="请输入页面名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="落地页ID" prop="pageId">
|
|
|
+ <el-input v-model.number="form.pageId" placeholder="请输入落地页ID" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit" :loading="submitting">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, reactive, computed, onMounted } from 'vue'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import { Plus } from '@element-plus/icons-vue'
|
|
|
+import {
|
|
|
+ getLoadPageConfList,
|
|
|
+ getLoadPageConfDetail,
|
|
|
+ addLoadPageConf,
|
|
|
+ updateLoadPageConf,
|
|
|
+ deleteLoadPageConf,
|
|
|
+ batchDeleteLoadPageConf
|
|
|
+} from '@/api/loadPageConf'
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const loading = ref(false)
|
|
|
+const submitting = ref(false)
|
|
|
+const confList = ref([])
|
|
|
+const selectedRows = ref([])
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const isEdit = ref(false)
|
|
|
+const formRef = ref(null)
|
|
|
+
|
|
|
+// 查询表单
|
|
|
+const queryForm = reactive({
|
|
|
+ name: '',
|
|
|
+ pageId: ''
|
|
|
+})
|
|
|
+
|
|
|
+// 分页数据
|
|
|
+const pagination = reactive({
|
|
|
+ page: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0
|
|
|
+})
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const form = reactive({
|
|
|
+ id: null,
|
|
|
+ name: '',
|
|
|
+ pageId: null
|
|
|
+})
|
|
|
+
|
|
|
+// 表单校验规则
|
|
|
+const rules = {
|
|
|
+ name: [
|
|
|
+ { required: true, message: '请输入页面名称', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ pageId: [
|
|
|
+ { required: true, message: '请输入落地页ID', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+}
|
|
|
+
|
|
|
+// 计算属性
|
|
|
+const totalPages = computed(() => {
|
|
|
+ return Math.ceil(pagination.total / pagination.pageSize)
|
|
|
+})
|
|
|
+
|
|
|
+// 格式化日期
|
|
|
+const formatDate = (dateStr) => {
|
|
|
+ if (!dateStr) return '-'
|
|
|
+ const date = new Date(dateStr)
|
|
|
+ return date.toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit',
|
|
|
+ second: '2-digit'
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 加载列表
|
|
|
+const loadList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ page: pagination.page,
|
|
|
+ size: pagination.pageSize
|
|
|
+ }
|
|
|
+ if (queryForm.name) {
|
|
|
+ params.name = queryForm.name
|
|
|
+ }
|
|
|
+ if (queryForm.pageId) {
|
|
|
+ params.pageId = queryForm.pageId
|
|
|
+ }
|
|
|
+ const response = await getLoadPageConfList(params)
|
|
|
+ if (response.success) {
|
|
|
+ confList.value = response.data.records || []
|
|
|
+ pagination.total = response.data.total || 0
|
|
|
+ } else {
|
|
|
+ ElMessage.error(response.message || '加载列表失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载列表失败:', error)
|
|
|
+ ElMessage.error('加载列表失败')
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 查询
|
|
|
+const handleQuery = () => {
|
|
|
+ pagination.page = 1
|
|
|
+ loadList()
|
|
|
+}
|
|
|
+
|
|
|
+// 重置
|
|
|
+const handleReset = () => {
|
|
|
+ queryForm.name = ''
|
|
|
+ queryForm.pageId = ''
|
|
|
+ handleQuery()
|
|
|
+}
|
|
|
+
|
|
|
+// 选择变化
|
|
|
+const handleSelectionChange = (selection) => {
|
|
|
+ selectedRows.value = selection
|
|
|
+}
|
|
|
+
|
|
|
+// 新增
|
|
|
+const handleAdd = () => {
|
|
|
+ isEdit.value = false
|
|
|
+ form.id = null
|
|
|
+ form.name = ''
|
|
|
+ form.pageId = null
|
|
|
+ dialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 编辑
|
|
|
+const handleEdit = async (row) => {
|
|
|
+ isEdit.value = true
|
|
|
+ try {
|
|
|
+ const response = await getLoadPageConfDetail(row.id)
|
|
|
+ if (response.success) {
|
|
|
+ form.id = response.data.id
|
|
|
+ form.name = response.data.name
|
|
|
+ form.pageId = response.data.pageId
|
|
|
+ dialogVisible.value = true
|
|
|
+ } else {
|
|
|
+ ElMessage.error(response.message || '获取详情失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取详情失败:', error)
|
|
|
+ ElMessage.error('获取详情失败')
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 删除
|
|
|
+const handleDelete = (row) => {
|
|
|
+ ElMessageBox.confirm('确定要删除该配置吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(async () => {
|
|
|
+ try {
|
|
|
+ const response = await deleteLoadPageConf(row.id)
|
|
|
+ if (response.success) {
|
|
|
+ ElMessage.success('删除成功')
|
|
|
+ loadList()
|
|
|
+ } else {
|
|
|
+ ElMessage.error(response.message || '删除失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('删除失败:', error)
|
|
|
+ ElMessage.error('删除失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+// 批量删除
|
|
|
+const handleBatchDelete = () => {
|
|
|
+ ElMessageBox.confirm(`确定要删除选中的 ${selectedRows.value.length} 个配置吗?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(async () => {
|
|
|
+ try {
|
|
|
+ const ids = selectedRows.value.map(item => item.id)
|
|
|
+ const response = await batchDeleteLoadPageConf(ids)
|
|
|
+ if (response.success) {
|
|
|
+ ElMessage.success('批量删除成功')
|
|
|
+ loadList()
|
|
|
+ } else {
|
|
|
+ ElMessage.error(response.message || '批量删除失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('批量删除失败:', error)
|
|
|
+ ElMessage.error('批量删除失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+// 对话框关闭
|
|
|
+const handleDialogClose = () => {
|
|
|
+ formRef.value?.resetFields()
|
|
|
+}
|
|
|
+
|
|
|
+// 提交表单
|
|
|
+const handleSubmit = async () => {
|
|
|
+ if (!formRef.value) return
|
|
|
+
|
|
|
+ await formRef.value.validate(async (valid) => {
|
|
|
+ if (!valid) return
|
|
|
+
|
|
|
+ submitting.value = true
|
|
|
+ try {
|
|
|
+ const data = {
|
|
|
+ name: form.name,
|
|
|
+ pageId: form.pageId
|
|
|
+ }
|
|
|
+
|
|
|
+ let response
|
|
|
+ if (isEdit.value) {
|
|
|
+ data.id = form.id
|
|
|
+ response = await updateLoadPageConf(data)
|
|
|
+ } else {
|
|
|
+ response = await addLoadPageConf(data)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.success) {
|
|
|
+ ElMessage.success(isEdit.value ? '更新成功' : '新增成功')
|
|
|
+ dialogVisible.value = false
|
|
|
+ loadList()
|
|
|
+ } else {
|
|
|
+ ElMessage.error(response.message || '操作失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('操作失败:', error)
|
|
|
+ ElMessage.error('操作失败')
|
|
|
+ } finally {
|
|
|
+ submitting.value = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 分页大小改变
|
|
|
+const handleSizeChange = (newSize) => {
|
|
|
+ pagination.pageSize = newSize
|
|
|
+ pagination.page = 1
|
|
|
+ loadList()
|
|
|
+}
|
|
|
+
|
|
|
+// 当前页改变
|
|
|
+const handleCurrentChange = (newPage) => {
|
|
|
+ pagination.page = newPage
|
|
|
+ loadList()
|
|
|
+}
|
|
|
+
|
|
|
+// 页面加载时获取列表
|
|
|
+onMounted(() => {
|
|
|
+ loadList()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+</style>
|