|
|
<template> <!-- 筛选与搜索区域 --> <el-card class="card1" style="margin-bottom: 1vh;"> <div class="condition"> <div class="condition-item"> <el-text size="large">搜索:</el-text> <el-input v-model="searchForm.chineseSimplified" style="width: 12vw" placeholder="请输入原文内容" clearable /> </div> <!-- 移除语言状态筛选 --> <div class="btn"> <el-button type="primary" @click="search">搜索</el-button> <el-button type="success" @click="reset">重置</el-button> </div> </div> </el-card>
<el-card class="card2"> <!-- 功能按钮区域 --> <div class="add-item"> <el-button type="success" @click="handleAdd">添加</el-button> <el-button class="add-item-export" @click="handleBatchImport">批量导入</el-button> </div>
<div> <el-table :data="tableData" style="width: 82vw;height:72vh;" :row-style="{ height: '50px' }"> <el-table-column type="index" label="序号" width="80px" fixed="left"> <template #default="scope"> <span>{{ scope.$index + 1 + (pagination.pageNum - 1) * pagination.pageSize }}</span> </template> </el-table-column>
<el-table-column prop="chineseSimplified" label="原文(中文)" width="180px"> <template #default="scope"> <el-tooltip :content="scope.row.chineseSimplified" placement="top" v-if="scope.row.chineseSimplified && scope.row.chineseSimplified.length > 20"> <span>{{ truncateText(scope.row.chineseSimplified) }}</span> </el-tooltip> <span v-else>{{ scope.row.chineseSimplified }}</span> </template> </el-table-column>
<el-table-column prop="english" label="英文" width="200px" header-align="center"> <template #default="scope"> <div style="display: flex; align-items: center; justify-content: space-between;"> <div style="flex: 1;"> <el-tooltip :content="scope.row.english" placement="top" v-if="scope.row.english && scope.row.english.length > 15"> <span>{{ truncateText(scope.row.english) }}</span> </el-tooltip> <span v-else>{{ scope.row.english }}</span> </div> <el-tag :type="scope.row.english ? 'success' : 'info'" size="small" style="margin-left: 8px;"> {{ scope.row.english ? '已翻译' : '未翻译' }} </el-tag> </div> </template> </el-table-column>
<el-table-column prop="thai" label="泰语" width="200px" header-align="center"> <template #default="scope"> <div style="display: flex; align-items: center; justify-content: space-between;"> <div style="flex: 1;"> <el-tooltip :content="scope.row.thai" placement="top" v-if="scope.row.thai && scope.row.thai.length > 15"> <span>{{ truncateText(scope.row.thai) }}</span> </el-tooltip> <span v-else>{{ scope.row.thai }}</span> </div> <el-tag :type="scope.row.thai ? 'success' : 'info'" size="small" style="margin-left: 8px;"> {{ scope.row.thai ? '已翻译' : '未翻译' }} </el-tag> </div> </template> </el-table-column>
<el-table-column prop="chineseTraditional" label="繁体中文" width="180px" header-align="center"> <template #default="scope"> <div style="display: flex; align-items: center; justify-content: space-between;"> <div style="flex: 1;"> <el-tooltip :content="scope.row.chineseTraditional" placement="top" v-if="scope.row.chineseTraditional && scope.row.chineseTraditional.length > 15"> <span>{{ truncateText(scope.row.chineseTraditional) }}</span> </el-tooltip> <span v-else>{{ scope.row.chineseTraditional }}</span> </div> <el-tag :type="scope.row.chineseTraditional ? 'success' : 'info'" size="small" style="margin-left: 8px;"> {{ scope.row.chineseTraditional ? '已翻译' : '未翻译' }} </el-tag> </div> </template> </el-table-column>
<el-table-column prop="malay" label="马来语" width="200px" header-align="center"> <template #default="scope"> <div style="display: flex; align-items: center; justify-content: space-between;"> <div style="flex: 1;"> <el-tooltip :content="scope.row.malay" placement="top" v-if="scope.row.malay && scope.row.malay.length > 15"> <span>{{ truncateText(scope.row.malay) }}</span> </el-tooltip> <span v-else>{{ scope.row.malay }}</span> </div> <el-tag :type="scope.row.malay ? 'success' : 'info'" size="small" style="margin-left: 8px;"> {{ scope.row.malay ? '已翻译' : '未翻译' }} </el-tag> </div> </template> </el-table-column>
<el-table-column prop="vietnamese" label="越南语" width="200px" header-align="center"> <template #default="scope"> <div style="display: flex; align-items: center; justify-content: space-between;"> <div style="flex: 1;"> <el-tooltip :content="scope.row.vietnamese" placement="top" v-if="scope.row.vietnamese && scope.row.vietnamese.length > 15"> <span>{{ truncateText(scope.row.vietnamese) }}</span> </el-tooltip> <span v-else>{{ scope.row.vietnamese }}</span> </div> <el-tag :type="scope.row.vietnamese ? 'success' : 'info'" size="small" style="margin-left: 8px;"> {{ scope.row.vietnamese ? '已翻译' : '未翻译' }} </el-tag> </div> </template> </el-table-column>
<!-- 移除状态列 --> <el-table-column prop="configTime" label="配置时间" width="180px" header-align="center"> <template #default="scope"> {{ moment(scope.row.configTime).format('YYYY-MM-DD HH:mm:ss') }} </template> </el-table-column>
<el-table-column prop="operation" label="操作" width="155px" fixed="right" header-align="center"> <template #default="scope"> <div style="display:flex; justify-content:center; "> <el-button type="primary" text @click="handleEdit(scope.row)">编辑</el-button> <el-button type="danger" text @click="handleDelete(scope.row)">删除</el-button> </div> </template> </el-table-column> </el-table> </div>
<!-- 分页组件 --> <div style="margin-top: 10px;display: flex;"> <el-pagination background v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" style="margin-top: 1vh;" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> </el-card>
<!-- 确认删除对话框 --> <ConfirmDialog v-model="showDeleteDialog" message="删除该翻译记录!" @confirm="handleDeleteConfirm" @cancel="handleDeleteCancel" @close="handleDeleteClose" />
<!-- 编辑对话框 --> <el-dialog v-model="showEditDialog" :title="editForm.id ? '编辑翻译' : '新增翻译'" width="30vw" draggable> <el-form :model="editForm" label-width="120px"> <el-form-item label="原文(中文):"> <el-input v-model="editForm.chineseSimplified" placeholder="请输入原文内容" show-word-limit /> </el-form-item>
<el-form-item label="英文:"> <el-input v-model="editForm.english" placeholder="请输入英文翻译" show-word-limit /> </el-form-item>
<el-form-item label="泰语:"> <el-input v-model="editForm.thai" placeholder="请输入泰语翻译" show-word-limit /> </el-form-item>
<el-form-item label="繁体中文:"> <el-input v-model="editForm.chineseTraditional" placeholder="请输入繁体中文翻译" show-word-limit /> </el-form-item>
<el-form-item label="马来语:"> <el-input v-model="editForm.malay" placeholder="请输入马来语翻译" show-word-limit /> </el-form-item>
<el-form-item label="越南语:"> <el-input v-model="editForm.vietnamese" placeholder="请输入越南语翻译" show-word-limit /> </el-form-item>
</el-form>
<template #footer> <el-button @click="showEditDialog = false">取消</el-button> <el-button type="primary" @click="handleSave">保存</el-button> </template> </el-dialog>
<!-- 批量导入对话框 --> <el-dialog v-model="showImportDialog" title="批量导入" width="40vw" draggable> <div style="margin-bottom: 20px;"> <el-text>下载导入模板:</el-text> <el-button type="text" @click="downloadTemplate">中文/英文/泰语/繁体中文/马来语/越南语模板</el-button> </div>
<el-upload class="upload-demo" drag action="#" :auto-upload="false" :on-change="handleFileChange" :show-file-list="false"> <el-icon class="el-icon--upload"><upload-filled /></el-icon> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> </el-upload>
<template #footer> <el-button @click="showImportDialog = false">取消</el-button> <el-button type="primary" @click="handleImport">导入</el-button> </template> </el-dialog></template>
<script setup>import { ElMessage, ElMessageBox } from 'element-plus';import { onMounted, ref, computed } from 'vue'import API from "@/util/http.js"import moment from 'moment'import { UploadFilled } from '@element-plus/icons-vue'import ConfirmDialog from '@/components/dialogs/ConfirmDialog.vue'// 引入AdminStore
import { useAdminStore } from '@/store/index.js';import { storeToRefs } from "pinia";const adminStore = useAdminStore();const { adminData } = storeToRefs(adminStore);
// 响应式数据
const tableData = ref([])const pagination = ref({ pageNum: 1, pageSize: 20, total: 0})
const searchForm = ref({ chineseSimplified: '', // 移除languageStatus字段
})
const showEditDialog = ref(false)const showImportDialog = ref(false)const showDeleteDialog = ref(false)const currentDeleteRow = ref(null) // 当前要删除的行数据
const editForm = ref({ id: '', chineseSimplified: '', english: '', thai: '', chineseTraditional: '', malay: '', vietnamese: '', // modules: [],
configTime: new Date()})
// 移除计算属性 - 不再需要统一的状态计算
// const translationStatus = computed(() => {
// return (row) => {
// const hasTranslation = row.english || row.thai || row.chineseTraditional || row.malay || row.vietnamese
// return hasTranslation ? 'translated' : 'untranslated'
// }
// })
// 方法定义
const truncateText = (text) => { if (!text) return '' return text.length > 20 ? text.substring(0, 20) + '...' : text}
// 移除getStatusType方法,因为现在每个语言列单独判断状态
// const getStatusType = (status) => {
// return status === 'translated' ? 'success' : 'info'
// }
// 搜索功能
const search = async () => { await getTranslationList()}
// 重置功能
const reset = () => { searchForm.value = { chineseSimplified: '', // 移除languageStatus
} getTranslationList()}
// 获取翻译列表
const getTranslationList = async () => { try { const params = { pageNum: pagination.value.pageNum, pageSize: pagination.value.pageSize, ...searchForm.value }
// 这里调用实际的API接口
const res = await API({ url: '/language/getTranslation', data: params })
if (res.code === 200) { // 不再需要设置统一的状态字段
tableData.value = res.data.list pagination.value.total = res.data.total } } catch (error) { console.error('获取翻译列表失败:', error) ElMessage.error('获取数据失败') }}
// 编辑翻译
const handleEdit = (row) => { editForm.value = { ...row } showEditDialog.value = true}
// 新增翻译
const handleAdd = () => { editForm.value = { id: '', chineseSimplified: '', english: '', thai: '', chineseTraditional: '', malay: '', vietnamese: '', // modules: [],
configTime: new Date() } showEditDialog.value = true}
const getMenuTree = async function () { // 获取菜单树
try { const result = await request({ url: '/menu/tree', data: { id: adminData.value.roleId,
} }) if (result.code === 200) { adminStore.setMenuTree(result.data)
}
return result.data // 直接返回接口响应数据
} catch (error) { console.error('菜单数据请求失败:', error) // return { code: 500, msg: '获取菜单失败' }
ElMessage.error('网络异常') adminStore.clearState() }}
// 保存翻译
const handleSave = async () => { // 原文必填校验
if (!editForm.value.chineseSimplified || editForm.value.chineseSimplified.trim() === '') { ElMessage.error('原文为必填项') return }
// 纯文本校验
const fields = ['english', 'thai', 'chineseTraditional', 'malay', 'vietnamese'] for (const field of fields) { if (editForm.value[field] && /<[^>]*>/.test(editForm.value[field])) { ElMessage.error('译文仅支持纯文本,不支持HTML标签') return } }
try { const url = editForm.value.id ? '/language/updateTranslation' : '/language/addTranslation' const res = await API({ url: url, data: editForm.value })
if (res.code === 200) { ElMessage.success(editForm.value.id ? '编辑成功' : '添加成功') showEditDialog.value = false getTranslationList() } else if (res.code === 0) { // 处理后端返回的错误信息
ElMessage.error(res.msg || '操作失败') } else { // 处理其他错误码
ElMessage.error(res.msg || '操作失败') } } catch (error) { console.error('保存失败:', error) ElMessage.error('保存失败') } // 点击保存后,刷新菜单树
await getMenuTree()}
// 删除翻译 - 打开确认对话框
const handleDelete = (row) => { currentDeleteRow.value = row showDeleteDialog.value = true}
// 确认删除
const handleDeleteConfirm = async () => { try { const res = await API({ url: '/language/deleteTranslation', data: { id: currentDeleteRow.value.id } })
if (res.code === 200) { ElMessage.success('删除成功') getTranslationList() } } catch (error) { console.error('删除失败:', error) ElMessage.error('删除失败') } finally { showDeleteDialog.value = false currentDeleteRow.value = null } // 点击删除后,刷新菜单树
await getMenuTree()}
// 取消删除
const handleDeleteCancel = () => { showDeleteDialog.value = false currentDeleteRow.value = null}
// 关闭删除对话框
const handleDeleteClose = () => { showDeleteDialog.value = false currentDeleteRow.value = null}
// 批量导入
const handleBatchImport = () => { showImportDialog.value = true}
// 下载模板
const downloadTemplate = () => { // 这里实现下载模板的逻辑
ElMessage.info('模板下载功能待实现')}
// 文件变化处理
const handleFileChange = (file) => { // 这里处理文件上传逻辑
console.log('文件变化:', file)}
// 导入处理
const handleImport = () => { // 这里实现导入逻辑
ElMessage.info('导入功能待实现')}
// 分页处理
const handleSizeChange = (val) => { pagination.value.pageSize = val pagination.value.pageNum = 1 getTranslationList()}
const handleCurrentChange = (val) => { pagination.value.pageNum = val getTranslationList()}
// 生命周期
onMounted(() => { getTranslationList()})</script>
<style scoped lang="scss">// 搜索卡片样式 - 与活动管理一致
.card1 { background: #F3FAFE;}
// 数据表格卡片样式 - 与活动管理一致
.card2 { background: #E7F4FD;}
// 表头背景等 - 与活动管理一致
:deep(.el-table__header-wrapper),:deep(.el-table__body-wrapper),:deep(.el-table__cell),/* 表格 */:deep(.el-table__body td) { background-color: #F3FAFE !important;}
/* 表头 */:deep(.el-table__header th) { background-color: #F3FAFE !important;}
/* 鼠标悬停 */:deep(.el-table__row:hover > .el-table__cell) { background-color: #E5EBFE !important;}
.condition { display: flex; align-items: center; flex-wrap: wrap; gap: 16px;}
.condition-item { display: flex; align-items: center; min-width: 180px;}
.btn { display: flex; align-items: center; gap: 4px;
}
.add-item { display: flex; align-items: center; gap: 4px; margin-bottom: 1vh;
.add-item-export { background-color: #5870FF; color: white; }}
// 标签样式
.el-tag { border: none;}
// 上传组件样式
.upload-demo { width: 100%;}
:deep(.el-upload-dragger) { width: 100%; height: 180px;}</style>
|