Compare commits
merge into: huangqizhen:master
huangqizhen:0919test
huangqizhen:dev
huangqizhen:huangqizheng/feature-20250702164103-登录页面退出登录
huangqizhen:lihui/feature-20250623144029-金币前端lihui
huangqizhen:lihui/feature-20250711103624-金币二期
huangqizhen:lihui/feature-20250728114233-金币前端三期
huangqizhen:lihui/feature-20250815155204-金币优化
huangqizhen:lihui/feature-20250915101448-现金管理
huangqizhen:lihui/feature-20250915101448-紧急
huangqizhen:lihui/feature-20251104165712-现金二期
huangqizhen:lihuilin/feature-20250815155204-金币优化
huangqizhen:lihuilin/feature-20250913114949-现金
huangqizhen:lihuilin/feature-20250923114949-现金
huangqizhen:lihuilin/feature-20251104102812-现金二期
huangqizhen:master
huangqizhen:milestone-20250623-金币前端
huangqizhen:milestone-20250711-金币前端二期
huangqizhen:milestone-20250728-金币前端三期
huangqizhen:milestone-20250815-金币优化
huangqizhen:milestone-20250913-现金管理
huangqizhen:milestone-20250917-重构工作台
huangqizhen:milestone-20251104-现金二期
huangqizhen:milestone-20251125-多语言
huangqizhen:youhua/chongzhi
huangqizhen:zhangrenyuan/feature-20250623164058-金币前端
huangqizhen:zhangrenyuan/feature-20250714163943-金币前端二期
huangqizhen:zhangrenyuan/feature-20250728113353-金币前端三期
huangqizhen:zhangrenyuan/feature-20250817091555-金币优化
huangqizhen:zhangrenyuan/feature-20250917134308-现金管理
huangqizhen:zhangrenyuan/feature-20251104133449-现金管理二期
huangqizhen:zhangrenyuan/feature-20251125114759-多语言
huangqizhen:zhangyong/feature-20250716164232-金币前端
huangqizhen:zhangyong/feature-20250815160302-金币优化
huangqizhen:zhangyong/milestone-20250913-现金管理
huangqizhen:zhangyong/milestone-20250913-现金管理二期
pull from: huangqizhen:milestone-20251125-多语言
huangqizhen:0919test
huangqizhen:dev
huangqizhen:huangqizheng/feature-20250702164103-登录页面退出登录
huangqizhen:lihui/feature-20250623144029-金币前端lihui
huangqizhen:lihui/feature-20250711103624-金币二期
huangqizhen:lihui/feature-20250728114233-金币前端三期
huangqizhen:lihui/feature-20250815155204-金币优化
huangqizhen:lihui/feature-20250915101448-现金管理
huangqizhen:lihui/feature-20250915101448-紧急
huangqizhen:lihui/feature-20251104165712-现金二期
huangqizhen:lihuilin/feature-20250815155204-金币优化
huangqizhen:lihuilin/feature-20250913114949-现金
huangqizhen:lihuilin/feature-20250923114949-现金
huangqizhen:lihuilin/feature-20251104102812-现金二期
huangqizhen:master
huangqizhen:milestone-20250623-金币前端
huangqizhen:milestone-20250711-金币前端二期
huangqizhen:milestone-20250728-金币前端三期
huangqizhen:milestone-20250815-金币优化
huangqizhen:milestone-20250913-现金管理
huangqizhen:milestone-20250917-重构工作台
huangqizhen:milestone-20251104-现金二期
huangqizhen:milestone-20251125-多语言
huangqizhen:youhua/chongzhi
huangqizhen:zhangrenyuan/feature-20250623164058-金币前端
huangqizhen:zhangrenyuan/feature-20250714163943-金币前端二期
huangqizhen:zhangrenyuan/feature-20250728113353-金币前端三期
huangqizhen:zhangrenyuan/feature-20250817091555-金币优化
huangqizhen:zhangrenyuan/feature-20250917134308-现金管理
huangqizhen:zhangrenyuan/feature-20251104133449-现金管理二期
huangqizhen:zhangrenyuan/feature-20251125114759-多语言
huangqizhen:zhangyong/feature-20250716164232-金币前端
huangqizhen:zhangyong/feature-20250815160302-金币优化
huangqizhen:zhangyong/milestone-20250913-现金管理
huangqizhen:zhangyong/milestone-20250913-现金管理二期
14 Commits
master
...
milestone-
32 changed files with 2162 additions and 748 deletions
-
82package-lock.json
-
1package.json
-
29src/App.vue
-
12src/assets/SvgIcons/mutiple-language.svg
-
3src/components/dialogs/ConfirmDialog.vue
-
138src/components/dialogs/LanguageSwitch.vue
-
28src/components/locales/index.js
-
104src/components/locales/lang/en.js
-
34src/components/locales/lang/th.js
-
388src/components/locales/lang/zh-CN.js
-
16src/main.ts
-
7src/router/index.js
-
14src/util/request.js
-
4src/utils/menuTreePermission.js
-
107src/utils/menuUtils.js
-
2src/views/activityManage/activity.vue
-
121src/views/audit/bean/beanAudit.vue
-
5src/views/audit/gold/audit.vue
-
164src/views/audit/gold/rechargeAudit.vue
-
193src/views/audit/gold/refundAudit.vue
-
167src/views/consume/gold/addCoinConsume.vue
-
5src/views/consume/gold/coinConsume.vue
-
127src/views/consume/gold/coinConsumeDetail.vue
-
40src/views/home.vue
-
535src/views/language/languageTranslate.vue
-
2src/views/login.vue
-
197src/views/recharge/gold/addCoinRecharge.vue
-
7src/views/recharge/gold/coinRecharge.vue
-
121src/views/recharge/gold/coinRechargeDetail.vue
-
138src/views/refund/gold/addCoinRefund.vue
-
5src/views/refund/gold/coinRefund.vue
-
114src/views/refund/gold/coinRefundDetail.vue
@ -1,9 +1,26 @@ |
|||||
<script setup> |
|
||||
</script> |
|
||||
|
|
||||
<template> |
<template> |
||||
<router-view></router-view> |
|
||||
|
<el-config-provider :locale="elLocale"> |
||||
|
<router-view /> |
||||
|
</el-config-provider> |
||||
</template> |
</template> |
||||
|
|
||||
<style scoped> |
|
||||
</style> |
|
||||
|
<script setup> |
||||
|
import { computed } from 'vue' |
||||
|
import { useI18n } from 'vue-i18n' |
||||
|
// 引入 Element Plus 的语言包 |
||||
|
import zhCnLocale from 'element-plus/dist/locale/zh-cn.mjs' |
||||
|
import enLocale from 'element-plus/dist/locale/en.mjs' |
||||
|
import thLocale from 'element-plus/dist/locale/th.mjs' |
||||
|
|
||||
|
const { locale } = useI18n() |
||||
|
|
||||
|
// 计算属性:根据当前 i18n 的语言,返回对应的 Element Plus 语言包 |
||||
|
const elLocale = computed(() => { |
||||
|
switch (locale.value) { |
||||
|
case 'zh-CN': return zhCnLocale |
||||
|
case 'en': return enLocale |
||||
|
case 'th': return thLocale |
||||
|
default: return zhCnLocale |
||||
|
} |
||||
|
}) |
||||
|
</script> |
||||
@ -0,0 +1,12 @@ |
|||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31 31" class="design-iconfont"> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0085 0.38608C11.9389 0.0559933 15.4797 -0.285745 20.5862 0.38608C25.6927 1.0579 28.9411 3.89977 30.0237 7.3258C31.1063 10.7518 31.0277 17.4517 30.6289 20.8033C30.3013 24.8149 27.9662 29.5636 22.3821 30.3908C16.7979 31.2181 9.93529 30.9975 7.18245 30.0172C4.42961 29.0369 0.783904 26.9498 0.307218 21.1038C-0.169468 15.2577 -0.484463 7.41159 2.49025 4.23018C4.55287 1.77953 8.07806 0.716166 10.0085 0.38608Z" fill="#C0F2FF"/> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.61719 23.264V7.64694C3.61719 6.23685 4.76029 5.09375 6.17038 5.09375H10.9232C12.4762 5.09375 14.0013 5.49747 15.3494 6.26363L15.5321 6.37035C16.6369 5.54169 17.9808 5.09375 19.3619 5.09375H24.8938C26.3039 5.09375 27.447 6.23685 27.447 7.64694V23.264C27.447 24.6741 26.3039 25.8172 24.8938 25.8172H19.3619C18.0383 25.8172 16.749 26.2285 15.6714 26.9922L15.5321 27.0938C14.1399 26.2584 12.5468 25.8172 10.9232 25.8172H6.17038C4.76029 25.8172 3.61719 24.6741 3.61719 23.264Z" fill="url(#zc4k4a1w8__paint0_linear_1264_34725)"/> |
||||
|
<path d="M21.7535 8.27734H9.12647C8.28947 8.27734 7.60547 8.96134 7.60547 9.79834V19.0593C7.60547 19.8963 8.28947 20.5803 9.12647 20.5803H13.0685L15.0305 22.5423C15.1475 22.6593 15.2915 22.7133 15.4445 22.7133C15.5975 22.7133 15.7415 22.6593 15.8585 22.5423L17.8205 20.5803H21.7625C22.5995 20.5803 23.2835 19.8963 23.2835 19.0593V9.79834C23.2745 8.96134 22.5995 8.27734 21.7535 8.27734ZM22.1045 19.0593C22.1045 19.2483 21.9515 19.4103 21.7535 19.4103H17.6945C17.5145 19.3743 17.3165 19.4283 17.1725 19.5723L15.4445 21.3003L13.7165 19.5723C13.5725 19.4283 13.3745 19.3743 13.1945 19.4103H9.12647C8.93747 19.4103 8.77547 19.2573 8.77547 19.0593V9.79834C8.77547 9.60934 8.92847 9.44734 9.12647 9.44734H21.7535C21.9515 9.44734 22.1045 9.60034 22.1045 9.79834V19.0593Z" fill="#fff"/> |
||||
|
<path d="M10.8119 10.9941C10.5149 10.9941 10.2719 11.2281 10.2539 11.5251V17.1051C10.2539 17.4111 10.5059 17.6631 10.8119 17.6631C11.1179 17.6631 11.3699 17.4111 11.3699 17.1051V11.5251C11.3519 11.2281 11.1089 10.9941 10.8119 10.9941ZM15.5009 13.1001C15.3389 12.9741 15.1319 12.8841 14.8979 12.8391C14.6639 12.7851 14.3939 12.7671 14.0969 12.7671C13.8449 12.7671 13.6199 12.7941 13.4309 12.8391C13.2419 12.8841 13.0709 12.9471 12.9269 13.0191C12.7829 13.0911 12.6569 13.1811 12.5579 13.2711C12.4769 13.3521 12.4049 13.4421 12.3509 13.5231C12.2699 13.6221 12.2159 13.7481 12.2159 13.8831C12.2159 14.1891 12.4679 14.4411 12.7739 14.4411C13.0439 14.4411 13.2689 14.2521 13.3229 14.0001L13.3319 13.9911C13.3769 13.9461 13.4309 13.9011 13.4939 13.8651C13.5659 13.8291 13.6469 13.7931 13.7369 13.7751C13.8359 13.7481 13.9439 13.7391 14.0789 13.7391C14.2139 13.7391 14.3399 13.7481 14.4479 13.7751C14.5469 13.7931 14.6279 13.8291 14.6909 13.8741C14.7539 13.9191 14.7989 13.9731 14.8349 14.0451C14.8709 14.1171 14.8889 14.2251 14.8889 14.3421V14.4231L14.0339 14.5041C13.7819 14.5311 13.5479 14.5671 13.3409 14.6301C13.1249 14.6931 12.9269 14.7741 12.7649 14.8911C12.6029 15.0081 12.4679 15.1701 12.3779 15.3591C12.2879 15.5481 12.2339 15.7821 12.2339 16.0521C12.2339 16.2591 12.2699 16.4481 12.3329 16.6281C12.3959 16.7991 12.4949 16.9611 12.6209 17.0871C12.7469 17.2131 12.8999 17.3211 13.0799 17.3841C13.2599 17.4561 13.4669 17.4921 13.7009 17.4921C13.9799 17.4921 14.2409 17.4291 14.4839 17.3121C14.6369 17.2311 14.7899 17.1411 14.9339 17.0331V17.2041C14.9339 17.5011 15.1769 17.7441 15.4739 17.7441C15.7709 17.7441 16.0139 17.5011 16.0139 17.2041V14.3601C16.0139 14.0631 15.9689 13.8111 15.8879 13.6041C15.7979 13.3971 15.6719 13.2261 15.5009 13.1001ZM14.8889 16.0431C14.8169 16.0971 14.7449 16.1601 14.6729 16.2051C14.5829 16.2681 14.4929 16.3221 14.4119 16.3671C14.3219 16.4121 14.2409 16.4481 14.1599 16.4751C14.0789 16.5021 14.0069 16.5111 13.9349 16.5111C13.7459 16.5111 13.6109 16.4751 13.5119 16.4031C13.4219 16.3401 13.3859 16.2051 13.3859 16.0251C13.3859 15.9171 13.4039 15.8181 13.4489 15.7461C13.4939 15.6741 13.5479 15.6111 13.6289 15.5571C13.7189 15.5031 13.8269 15.4581 13.9529 15.4311C14.0879 15.3951 14.2499 15.3771 14.4299 15.3591L14.8979 15.3141V16.0431H14.8889ZM20.4959 13.2081C20.3879 13.0641 20.2439 12.9471 20.0639 12.8751C19.8929 12.8031 19.6769 12.7671 19.4249 12.7671C19.2809 12.7671 19.1369 12.7851 18.9929 12.8301C18.8489 12.8751 18.7139 12.9291 18.5789 12.9921C18.4439 13.0641 18.3269 13.1451 18.2009 13.2351L18.0929 13.3161V13.2171V13.2981C18.0929 12.9921 17.8409 12.7491 17.5349 12.7491C17.2289 12.7491 16.9769 12.9921 16.9769 13.2981V13.2171V17.1951C16.9769 17.5011 17.2289 17.7531 17.5349 17.7531C17.8409 17.7531 18.0929 17.5011 18.0929 17.1951V14.3871C18.1739 14.3151 18.2549 14.2521 18.3449 14.1801C18.4439 14.1081 18.5429 14.0361 18.6419 13.9821C18.7409 13.9281 18.8309 13.8831 18.9299 13.8471C19.0199 13.8201 19.1009 13.8021 19.1729 13.8021C19.2899 13.8021 19.3799 13.8201 19.4429 13.8471C19.4969 13.8741 19.5419 13.9191 19.5779 13.9911C19.6139 14.0721 19.6409 14.1711 19.6499 14.3061C19.6589 14.4501 19.6679 14.6211 19.6679 14.8281V17.1951C19.6679 17.5011 19.9199 17.7531 20.2259 17.7531C20.5319 17.7531 20.7839 17.5011 20.7839 17.1951V14.4141C20.7839 14.1621 20.7659 13.9371 20.7209 13.7391C20.6849 13.5321 20.6039 13.3521 20.4959 13.2081Z" fill="#fff"/> |
||||
|
<defs> |
||||
|
<linearGradient id="zc4k4a1w8__paint0_linear_1264_34725" x1="39.3619" y1="16.0938" x2="19.665" y2="-7.37491" gradientUnits="userSpaceOnUse"> |
||||
|
<stop stop-color="#2FB7FC"/> |
||||
|
<stop offset="1" stop-color="#82DEFF"/> |
||||
|
</linearGradient> |
||||
|
</defs> |
||||
|
</svg> |
||||
@ -0,0 +1,138 @@ |
|||||
|
<template> |
||||
|
<el-dialog |
||||
|
v-model="dialogVisible" |
||||
|
title="语言切换" |
||||
|
width="300px" |
||||
|
:close-on-click-modal="false" |
||||
|
append-to-body |
||||
|
class="lang-switch-dialog" |
||||
|
> |
||||
|
<el-form label-width="80px"> |
||||
|
<el-form-item label="切换语言"> |
||||
|
<el-select |
||||
|
v-model="tempLang" |
||||
|
placeholder="请选择语言" |
||||
|
style="width: 100%" |
||||
|
> |
||||
|
<el-option |
||||
|
v-for="item in langOptions" |
||||
|
:key="item.value" |
||||
|
:label="item.label" |
||||
|
:value="item.value" |
||||
|
/> |
||||
|
</el-select> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
|
<template #footer> |
||||
|
<div class="dialog-footer"> |
||||
|
<el-button @click="dialogVisible = false">取 消</el-button> |
||||
|
<el-button type="primary" @click="handleConfirm">确 定</el-button> |
||||
|
</div> |
||||
|
</template> |
||||
|
</el-dialog> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import {computed, ref} from 'vue' |
||||
|
import {useI18n} from 'vue-i18n' |
||||
|
// === 显式引入所有用到的 Element Plus 组件 === |
||||
|
import {ElButton, ElDialog, ElForm, ElFormItem, ElMessage, ElOption, ElSelect} from 'element-plus' |
||||
|
import request from "@/util/http.js"; |
||||
|
import {useAdminStore} from '@/store/index.js'; |
||||
|
import {storeToRefs} from "pinia"; |
||||
|
|
||||
|
const {locale} = useI18n() |
||||
|
|
||||
|
// 控制弹窗显示 |
||||
|
const dialogVisible = ref(false) |
||||
|
|
||||
|
// 真正的当前语言 |
||||
|
const currentLang = computed(() => locale.value) |
||||
|
|
||||
|
// 临时选择的语言 |
||||
|
const tempLang = ref('') |
||||
|
|
||||
|
// 语言选项 |
||||
|
const langOptions = [ |
||||
|
{label: '中文(简体)', value: 'zh-CN'}, |
||||
|
{label: '中文(繁體)', value: 'zh-TW'}, |
||||
|
{label: '英语', value: 'en'}, |
||||
|
{label: 'ภาษาไทย', value: 'th'}, |
||||
|
{label: 'Tiếng Việt', value: 'vi'} |
||||
|
] |
||||
|
|
||||
|
// 获取语言显示名称 |
||||
|
const getLangLabel = (langCode) => { |
||||
|
const find = langOptions.find(item => item.value === langCode) |
||||
|
return find ? find.label : langCode |
||||
|
} |
||||
|
|
||||
|
// 打开弹窗 |
||||
|
const open = () => { |
||||
|
tempLang.value = currentLang.value |
||||
|
dialogVisible.value = true |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// 确认修改 |
||||
|
const handleConfirm = async () => { |
||||
|
locale.value = tempLang.value |
||||
|
localStorage.setItem('lang', tempLang.value) |
||||
|
|
||||
|
await getMenuTree() |
||||
|
|
||||
|
ElMessage.success(`语言已切换为:${getLangLabel(tempLang.value)}`) |
||||
|
dialogVisible.value = false |
||||
|
// 触发页面刷新以重新加载数据 |
||||
|
setTimeout(() => { |
||||
|
window.location.reload() |
||||
|
}, 500) |
||||
|
} |
||||
|
|
||||
|
defineExpose({ |
||||
|
open |
||||
|
}) |
||||
|
|
||||
|
const adminStore = useAdminStore(); |
||||
|
const {adminData} = storeToRefs(adminStore); |
||||
|
// 切换多语言 菜单改变 |
||||
|
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() |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
<style scoped> |
||||
|
.dialog-footer { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
gap: 20px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* :deep(.el-dialog__body) { |
||||
|
height: 220px !important; |
||||
|
overflow-y: auto !important; |
||||
|
} */ |
||||
|
</style> |
||||
@ -0,0 +1,28 @@ |
|||||
|
import { createI18n } from 'vue-i18n' |
||||
|
|
||||
|
// 引入你的本地语言包
|
||||
|
import zhCN from './lang/zh-CN' |
||||
|
import en from './lang/en' |
||||
|
import th from './lang/th' // 泰文
|
||||
|
|
||||
|
// 组合语言包
|
||||
|
const messages = { |
||||
|
'zh-CN': zhCN, |
||||
|
'en': en, |
||||
|
'th': th |
||||
|
} |
||||
|
|
||||
|
// 获取浏览器默认语言或缓存语言
|
||||
|
const getLocale = () => { |
||||
|
// 优先读取缓存,没有则读取浏览器语言,默认 zh-CN
|
||||
|
return localStorage.getItem('lang') || 'zh-CN' |
||||
|
} |
||||
|
|
||||
|
const i18n = createI18n({ |
||||
|
legacy: false, // Vue 3 组合式 API 必须设置为 false
|
||||
|
globalInjection: true, // 全局注入 $t 函数
|
||||
|
locale: getLocale(), // 初始化语言
|
||||
|
messages // 语言包数据
|
||||
|
}) |
||||
|
|
||||
|
export default i18n |
||||
@ -0,0 +1,104 @@ |
|||||
|
export default { |
||||
|
// Common Group
|
||||
|
common: { |
||||
|
// Filters
|
||||
|
jwcode: 'jwcode', |
||||
|
jwcodePlaceholder: 'Please enter jwcode', |
||||
|
activityName: 'Activity Name', |
||||
|
activityNamePlaceholder: 'Please enter activity name', |
||||
|
goodsName: 'Goods Name', |
||||
|
goodsNamePlaceholder: 'Please enter goods name', |
||||
|
payModel: 'Payment Method', |
||||
|
payModelPlaceholder: 'Please select payment method', |
||||
|
refundType: 'Refund Type', |
||||
|
refundTypePlaceholder: 'Please select refund type', |
||||
|
market: 'Market', |
||||
|
marketPlaceholder: 'Please select market', |
||||
|
submitTime: 'Submit Time', |
||||
|
auditTime: 'Audit Time', |
||||
|
startTime: 'Start Time', |
||||
|
to: 'To', |
||||
|
endTime: 'End Time', |
||||
|
|
||||
|
// Button Group
|
||||
|
search: 'Search', |
||||
|
reset: 'Reset', |
||||
|
edit: 'Edit', |
||||
|
pass: 'Pass', |
||||
|
reject: 'Reject', |
||||
|
cancel: 'Cancel', |
||||
|
confirm: 'Confirm', |
||||
|
|
||||
|
// Currency Types
|
||||
|
SGD: 'SGD', |
||||
|
goldCoin: '', // Gold Coin label intentionally empty
|
||||
|
// 对话框标题
|
||||
|
will: 'Will', |
||||
|
}, |
||||
|
|
||||
|
// Audit Group
|
||||
|
audit: { |
||||
|
// Audit Common
|
||||
|
refundTypeOptions: { |
||||
|
'商品退款': 'Product Refund', |
||||
|
'金币退款': 'Gold Refund', |
||||
|
}, |
||||
|
waitAudit: 'Pending Audit', |
||||
|
passed: 'Approved', |
||||
|
rejected: 'Rejected', |
||||
|
permanentGold: 'Permanent', |
||||
|
freeGold: 'Free', |
||||
|
taskGold: 'Task', |
||||
|
|
||||
|
// Audit Common - List Fields
|
||||
|
id: 'ID', |
||||
|
name: 'Name', |
||||
|
jwcode: 'JW Code', |
||||
|
market: 'Market', |
||||
|
activityName: 'Activity Name', |
||||
|
currencyName: 'Currency Name', |
||||
|
rechargeAmount: 'Recharge Amount', |
||||
|
note: 'Note', |
||||
|
payModel: 'Payment Method', |
||||
|
paymentVoucher: 'Payment Voucher', |
||||
|
submitter: 'Submitter', |
||||
|
auditor: 'Auditor', |
||||
|
rejectReason: 'Reject Reason', |
||||
|
rejectReasonPlaceholder: 'Please enter reject reason', |
||||
|
paymentTime: 'Payment Time', |
||||
|
submitTime: 'Submit Time', |
||||
|
auditTime: 'Audit Time', |
||||
|
operation: 'Operation', |
||||
|
|
||||
|
// Supplement Fields for Refund Audit
|
||||
|
orderCode: 'Order Number', |
||||
|
refundType: 'Refund Type', |
||||
|
refundModel: 'Refund Method', |
||||
|
allRefund: 'Full Refund', |
||||
|
partialRefund: 'Partial Refund', |
||||
|
refundGoods: 'Refund Goods', |
||||
|
|
||||
|
// Gold Recharge Audit ------------------------
|
||||
|
rechargeAudit: 'Recharge Audit', |
||||
|
rechargeSGD: 'Recharge SGD', |
||||
|
totalGold: 'Total Gold', |
||||
|
// 添加支付方式翻译
|
||||
|
payMethods: { |
||||
|
bankTransfer: 'Bank Transfer', |
||||
|
cash: 'Cash', |
||||
|
check: 'Check', |
||||
|
card: 'Card Payment', |
||||
|
grabpay: 'Grabpay', |
||||
|
nets: 'Nets', |
||||
|
paypal: 'PayPal', |
||||
|
stripe: 'Stripe - Link Payment', |
||||
|
ipay88: 'Ipay88 - Link Payment', |
||||
|
paymentAsia: 'PaymentAsia - Link Payment', |
||||
|
other: 'Other' |
||||
|
}, |
||||
|
|
||||
|
// Gold Refund Audit --------------------------
|
||||
|
refundAudit: 'Refund Audit', |
||||
|
refundTotalGold: 'Total Refund', |
||||
|
}, |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
export default { |
||||
|
common: { |
||||
|
jwcode: 'jwcode', |
||||
|
jwcodePlaceholder: 'กรุณาใส่ jwcode', |
||||
|
activityName: 'ชื่อกิจกรรม', |
||||
|
activityNamePlaceholder: 'กรุณาใส่ชื่อกิจกรรม', |
||||
|
goodsName: 'ชื่อสินค้า', |
||||
|
goodsNamePlaceholder: 'กรุณาใส่ชื่อสินค้า', |
||||
|
refundType: 'ประเภทการคืนเงิน', |
||||
|
refundTypePlaceholder: 'กรุณาเลือกประเภทการคืนเงิน', |
||||
|
payModel: 'วิธีการชำระเงิน', |
||||
|
payModelPlaceholder: 'กรุณาเลือกวิธีการชำระเงิน', |
||||
|
market: 'ตลาด', |
||||
|
marketPlaceholder: 'กรุณาเลือกตลาด', |
||||
|
submitTime: 'เวลาส่ง', |
||||
|
auditTime: 'เวลาตรวจสอบ', |
||||
|
startTime: 'เวลาเริ่มต้น', |
||||
|
to: 'ถึง', |
||||
|
endTime: 'เวลาสิ้นสุด', |
||||
|
search: 'ค้นหา', |
||||
|
reset: 'รีเซ็ต', |
||||
|
}, |
||||
|
audit: { |
||||
|
rechargeAudit: 'การตรวจสอบการเติมเงิน', |
||||
|
refundAudit: 'การตรวจสอบการคืนเงิน', |
||||
|
refundTypeOptions: { |
||||
|
'商品退款': 'คืนเงินสินค้า', |
||||
|
'金币退款': 'คืนเงินทอง', |
||||
|
}, |
||||
|
waitAudit: 'รอตรวจสอบ', |
||||
|
passed: 'อนุมัติ', |
||||
|
rejected: 'ปฏิเสธ', |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,388 @@ |
|||||
|
import { UploadFilled } from "@element-plus/icons-vue"; |
||||
|
|
||||
|
export default { |
||||
|
// 通用组 (筛选,按钮,币种计量)
|
||||
|
common: { |
||||
|
// 筛选
|
||||
|
jwcode: '精网号', |
||||
|
jwcodePlaceholder: '请输入精网号', |
||||
|
activityName: '活动名称', |
||||
|
activityNamePlaceholder: '请输入活动名称', |
||||
|
goodsName: '商品名称', |
||||
|
goodsNamePlaceholder: '请输入商品名称', |
||||
|
payModel: '支付方式', |
||||
|
payModelPlaceholder: '请选择支付方式', |
||||
|
refundType: '退款类型', |
||||
|
refundTypePlaceholder: '请选择退款类型', |
||||
|
market: '所属地区', |
||||
|
marketPlaceholder: '请选择所属地区', |
||||
|
consumePlatform: '消耗平台', |
||||
|
consumePlatformPlaceholder: '请选择消耗平台', |
||||
|
rechargePlatform: '充值平台', |
||||
|
rechargePlatformPlaceholder: '请选择充值平台', |
||||
|
consumeTime: '消耗时间', |
||||
|
rechargeTime: '充值时间', |
||||
|
refundTime: '退款时间', |
||||
|
submitTime: '提交时间', |
||||
|
auditTime: '审核时间', |
||||
|
startTime: '起始时间', |
||||
|
to: '至', |
||||
|
endTime: '结束时间', |
||||
|
// 按钮组
|
||||
|
search: '查询', |
||||
|
exportExcel: '导出Excel', |
||||
|
viewExportList: '查看导出列表', |
||||
|
reset: '重置', |
||||
|
edit: '编辑', |
||||
|
pass: '通过', |
||||
|
reject: '驳回', |
||||
|
cancel: '取消', |
||||
|
confirm: '确认', |
||||
|
submit: '提交', |
||||
|
confrimRecharge: '确认充值', |
||||
|
// 按钮组-日期
|
||||
|
today: '今', |
||||
|
yesterday: '昨', |
||||
|
last7Days: '近7天', |
||||
|
// 币种计量单位类型
|
||||
|
rechargeSGD: '充值新币', |
||||
|
consumeSGD: '消耗新币', |
||||
|
refundGoldCoin: '退款金币总数', |
||||
|
totalGoldCoin: '总金币数', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
SGD: '新币', |
||||
|
goldCoin: '金币', |
||||
|
条: '条', |
||||
|
个: '个', |
||||
|
goldBean: '金豆', |
||||
|
// 对话框标题
|
||||
|
will: '将要', |
||||
|
}, |
||||
|
// 提示信息组
|
||||
|
elmessage: { |
||||
|
// 通用
|
||||
|
addSuccess: '添加成功', |
||||
|
searchSuccess: '查询成功', |
||||
|
requestFailed: '请求失败', |
||||
|
jwcodeError: '精网号错误', |
||||
|
addFailedUnknown: '添加失败,未知错误', |
||||
|
addFailed: '添加失败,请检查网络连接或联系管理员', |
||||
|
queryFailed: '查询失败,请检查网络连接或精网号是否正确', |
||||
|
refundTypeError: '退款类型数据格式错误,请联系管理员', |
||||
|
confirmRefund: '确认退款?', |
||||
|
// 校验精网号,充值等输入
|
||||
|
checkInputContent: '请检查输入内容', |
||||
|
permanentAndFreeNoZero: '永久金币和免费金币不能同时为0', |
||||
|
checkRate: '请选择币种名称', |
||||
|
checkMoney: '请输入充值金额', |
||||
|
checkJwcode: '请输入精网号', |
||||
|
checkGoodsName: '请选择商品', |
||||
|
checkUserInfo: '请先查询用户信息', |
||||
|
checkActivity: '请输入活动名称', |
||||
|
checkPermanentGold: '请输入永久金币数', |
||||
|
checkFreeGold: '请输入免费金币数', |
||||
|
checkTaskGold: '请输入任务金币数', |
||||
|
checkNumber: '请输入有效的数字', |
||||
|
checkPayModel: '请选择付款方式', |
||||
|
checkPayTime: '请选择交款时间', |
||||
|
checkQueryParams: '请检查查询参数', |
||||
|
checkRefundType: '请选择退款类型', |
||||
|
checkRefundGoods: '请选择退款商品', |
||||
|
checkOrderNo: '请输入订单号', |
||||
|
// 校验提示(error)
|
||||
|
noEmptyJwcode: '精网号不能为空', |
||||
|
noEmptySumGold: '消耗金币总数不能为空', |
||||
|
noUser: '用户不存在', |
||||
|
noOrder: '未查询到相关订单', |
||||
|
noTotalGoldZero: '总金币数不能为0', |
||||
|
noNegativeNumber: '不能输入负数', |
||||
|
limitDigitJwcode: '精网号只能包含数字', |
||||
|
limitNoSpecialChar: '不能包含特殊符号或负数', |
||||
|
limitNegativeNumber: '消耗金币总数不能为负数', |
||||
|
limitExceeded: '消耗金币总数超过可用金币总和', |
||||
|
limitSix: '整数位数不能超过6位', |
||||
|
limitTwoDecimal: '小数位数不能超过两位', |
||||
|
limitZero: '输入金额不能小于0', |
||||
|
limitPositiveNumber: '请输入大于0的正数(可包含最多两位小数)', |
||||
|
limitJwcodeNine: '精网号必须为数字且不超过九位', |
||||
|
limitBalance: '所填金额大于该类金币余额', |
||||
|
// 图片上传
|
||||
|
onlyUploadJPGPNG: '只能上传 JPG/PNG 图片!', |
||||
|
limitImageSize: '图片大小不能超过 1MB!', |
||||
|
uploadSuccess: '上传成功', |
||||
|
UploadFailed: '上传失败', |
||||
|
// 审核
|
||||
|
noPermission: '暂无权限', |
||||
|
checkJwcodeFormat: '请检查精网号格式', |
||||
|
rejectReasonPlaceholder: '请输入驳回理由', |
||||
|
rejectSuccess: '驳回成功', |
||||
|
rejectFailed: '驳回失败', |
||||
|
operationFailed: '操作失败', |
||||
|
approveSuccess: '审核通过成功', |
||||
|
approveFailed: '审核通过失败', |
||||
|
activityFormatError: '活动数据格式错误,请联系管理员', |
||||
|
rechargeFormatError: '充值方式格式错误,请联系管理员', |
||||
|
getRechargeError: '获取充值方式失败,请稍后重试', |
||||
|
// 导出相关
|
||||
|
exportSuccess: '导出成功', |
||||
|
exportFailed: '导出失败,请稍后重试', |
||||
|
getExportListError: '获取导出列表失败,请稍后重试', |
||||
|
exportingInProgress: '文件还在导出中,请稍后再试', |
||||
|
// 导出状态标签
|
||||
|
pendingExecution: '待执行', |
||||
|
executing: '执行中', |
||||
|
executed: '执行完成', |
||||
|
errorExecution: '执行出错', |
||||
|
unknownStatus: '未知状态', |
||||
|
}, |
||||
|
|
||||
|
// 通用列表字段组
|
||||
|
common_list: { |
||||
|
id: '序号', |
||||
|
name: '姓名', |
||||
|
jwcode: '精网号', |
||||
|
market: '所属地区', |
||||
|
orderNo: '订单号', |
||||
|
goodsName: '商品名称', |
||||
|
refundType: '退款类型', |
||||
|
refundModel: '退款方式', |
||||
|
refundModelAll: '全部退款', |
||||
|
refundModelPart: '部分退款', |
||||
|
refundGoldCoin: '退款金币总数', |
||||
|
activity: '活动名称', |
||||
|
rateName: '货币名称', |
||||
|
rechargeAmount: '充值金额', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
rechargePlatform: '充值平台', |
||||
|
consumePlatform: '消耗平台', |
||||
|
consumeTotalGold: '消耗金币总数', |
||||
|
payModel: '支付方式', |
||||
|
remark: '备注', |
||||
|
orderStatus: '订单状态', |
||||
|
submitter: '提交人', |
||||
|
rechargeTime: '充值时间', |
||||
|
consumeTime: '消耗时间', |
||||
|
refundTime: '退款时间', |
||||
|
}, |
||||
|
// 通用导出字段组
|
||||
|
common_export: { |
||||
|
exportList: '导出列表', |
||||
|
fileName: '文件名称', |
||||
|
status: '状态', |
||||
|
createTime: '创建时间', |
||||
|
operation: '操作', |
||||
|
download: '下载', |
||||
|
close: '关闭', |
||||
|
}, |
||||
|
|
||||
|
// 新增表单字段组
|
||||
|
common_add: { |
||||
|
jwcode: '精网号', |
||||
|
activity: '活动名称', |
||||
|
activityPlaceholder: '请输入活动名称', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
rechargeAmount: '充值金额', |
||||
|
currencyName: '货币名称', |
||||
|
goodsName: '商品名称', |
||||
|
goodsNamePlaceholder: '请选择商品', |
||||
|
payModel: '收款方式', |
||||
|
refundType: '退款类型', |
||||
|
refundTypePlaceholder: '请选择退款类型', |
||||
|
orderNo: '订单号', |
||||
|
orderNoPlaceholder: '请选择订单号', |
||||
|
refundModel: '退款方式', |
||||
|
refundModelAll: '全部退款', |
||||
|
refundModelPart: '部分退款', |
||||
|
refundGoldCoin: '退款金币总数', |
||||
|
payModelPlaceholder: '请选择收款方式', |
||||
|
consumeTotalGold: '消耗金币总数', |
||||
|
totalGold: '金币总数', |
||||
|
paymentTime: '交款时间', |
||||
|
paymentVoucher: '交款凭证', |
||||
|
paymentVoucherPlaceholder: '仅支持.jpg .png格式,文件≤1MB', |
||||
|
remark: '备注', |
||||
|
// 确认表单
|
||||
|
operationConfirm: '操作确认', |
||||
|
userInfo: '用户信息', |
||||
|
prompt: '重复充值风险提示', |
||||
|
similarRechargeRecords: '检测到该用户近期有相似充值记录', |
||||
|
rechargePermanentGold: '充值永久金币', |
||||
|
buy: '购买', |
||||
|
operator: '操作人', |
||||
|
continueOperation: '是否继续操作', |
||||
|
}, |
||||
|
// 新增表单客户信息字段组
|
||||
|
common_add_user: { |
||||
|
customerInfo: '客户信息', |
||||
|
name: '姓名', |
||||
|
currentGoldCoinTotal: '当前金币总数', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
jwcode: '精网号', |
||||
|
consumptionTimes: '消费次数', |
||||
|
onlyStatisticsDataAfter20250101: '仅统计2025-01-01后的数据', |
||||
|
store: '所属门店', |
||||
|
}, |
||||
|
|
||||
|
// 审核组
|
||||
|
audit: { // 按照项目文件名分配
|
||||
|
// 审核通用 ----------------------------------------------------------
|
||||
|
refundTypeOptions: { |
||||
|
'商品退款': '商品退款', |
||||
|
'金币退款': '金币退款', |
||||
|
}, |
||||
|
waitAudit: '待审核', |
||||
|
passed: '已通过', |
||||
|
rejected: '已驳回', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
// 审核通用-充值审核列表字段
|
||||
|
id: '序号', |
||||
|
name: '姓名', |
||||
|
jwcode: '精网号', |
||||
|
market: '所属地区', |
||||
|
activityName: '活动名称', |
||||
|
currencyName: '货币名称', |
||||
|
rechargeAmount: '充值金额', |
||||
|
note: '备注', |
||||
|
payModel: '支付方式', |
||||
|
paymentVoucher: '支付凭证', |
||||
|
submitter: '提交人', |
||||
|
auditor: '审核人', |
||||
|
rejectReason: '驳回理由', |
||||
|
rejectReasonPlaceholder: '请输入驳回理由', |
||||
|
paymentTime: '交款时间', |
||||
|
submitTime: '提交时间', |
||||
|
auditTime: '审核时间', |
||||
|
operation: '操作', |
||||
|
// 审核通用-充值审核列表字段-补充退款审核列表字段
|
||||
|
orderCode: '订单号', |
||||
|
refundType: '退款类型', |
||||
|
refundModel: '退款方式', |
||||
|
allRefund: '全部退款', |
||||
|
partialRefund: '部分退款', |
||||
|
refundGoods: '退款商品', |
||||
|
// 审核通用-金豆审核列表字段补充
|
||||
|
permanentBean: '付费金豆', |
||||
|
freeBean: '免费金豆', |
||||
|
// 金币充值审核 --------------------------------
|
||||
|
rechargeAudit: '充值审核', |
||||
|
rechargeSGD: '充值新币', |
||||
|
totalGold: '总金币数', |
||||
|
// 添加支付方式
|
||||
|
payMethods: { |
||||
|
bankTransfer: '银行转账', |
||||
|
cash: '现金', |
||||
|
check: '支票', |
||||
|
card: '刷卡', |
||||
|
grabpay: 'Grabpay', |
||||
|
nets: 'Nets', |
||||
|
paypal: 'PayPal', |
||||
|
stripe: 'Stripe-链接收款', |
||||
|
ipay88: 'Ipay88-链接收款', |
||||
|
paymentAsia: 'PaymentAsia-链接收款', |
||||
|
other: '其他' |
||||
|
}, |
||||
|
// 金币退款审核 --------------------------------
|
||||
|
refundAudit: '退款审核', |
||||
|
refundTotalGold: '退款总金币数', |
||||
|
// 金豆审核 ------------------------------------
|
||||
|
totalNum: '总条数', |
||||
|
totalBean: '总金豆数', |
||||
|
permanentBean: '付费金豆', |
||||
|
freeBean: '免费金豆', |
||||
|
// 对话框的标题
|
||||
|
rejectRecord: '驳回该记录!', |
||||
|
passRecord: '通过该记录!', |
||||
|
}, |
||||
|
|
||||
|
// 充值组
|
||||
|
recharge: { |
||||
|
// 金币充值明细 ---------------------------------
|
||||
|
coinRechargeDetail: '金币充值明细', |
||||
|
// 订单状态
|
||||
|
normal: '正常', |
||||
|
refunded: '已退款', |
||||
|
unknown: '未知状态', |
||||
|
// 金币新增充值 ---------------------------------
|
||||
|
addCoinRecharge: '新增充值', |
||||
|
// 支付方式
|
||||
|
// 添加支付方式
|
||||
|
payMethods: { |
||||
|
bankTransfer: '银行转账', |
||||
|
cash: '现金', |
||||
|
check: '支票', |
||||
|
card: '刷卡', |
||||
|
grabpay: 'Grabpay', |
||||
|
nets: 'Nets', |
||||
|
paypal: 'PayPal', |
||||
|
stripe: 'Stripe-链接收款', |
||||
|
ipay88: 'Ipay88-链接收款', |
||||
|
paymentAsia: 'PaymentAsia-链接收款', |
||||
|
other: '其他' |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
// 消耗组
|
||||
|
consume: { |
||||
|
// 金币消耗明细 ---------------------------------
|
||||
|
coinConsumeDetail: '金币消耗明细', |
||||
|
// 订单状态
|
||||
|
normal: '正常', |
||||
|
refunded: '已退款', |
||||
|
unknown: '未知状态', |
||||
|
// 消费平台选项
|
||||
|
consumePlatforms: { |
||||
|
goldSystem: '金币系统', |
||||
|
HomilyChart: 'HomilyChart', |
||||
|
HomilyLink: 'HomilyLink', |
||||
|
ERP: 'ERP', |
||||
|
other: '其他', |
||||
|
initGold: '初始化金币', |
||||
|
}, |
||||
|
// 新增消耗
|
||||
|
addCoinConsume: '新增消耗', |
||||
|
}, |
||||
|
|
||||
|
//退款组
|
||||
|
refund: { |
||||
|
// 金币退款明细 ---------------------------------
|
||||
|
coinRefundDetail: '金币退款明细', |
||||
|
// 订单状态
|
||||
|
normal: '正常', |
||||
|
refunded: '已退款', |
||||
|
unknown: '未知状态', |
||||
|
// 退款方式选项
|
||||
|
refundMethods: { |
||||
|
allRefund: '全部退款', |
||||
|
partialRefund: '部分退款', |
||||
|
}, |
||||
|
// 新增退款
|
||||
|
refundTypeOptions: { |
||||
|
'商品退款': '商品退款', |
||||
|
'金币退款': '金币退款', |
||||
|
}, |
||||
|
addCoinRefund: '新增退款', |
||||
|
// 新增退款的用户表单
|
||||
|
id: '序号', |
||||
|
type: '类型', |
||||
|
recharge: '充值', |
||||
|
consume: '消费', |
||||
|
productName: '商品名称', |
||||
|
orderCode: '订单号', |
||||
|
permanentGold: '永久金币', |
||||
|
freeGold: '免费金币', |
||||
|
taskGold: '任务金币', |
||||
|
isRefund: '允许退款', |
||||
|
no: '否', |
||||
|
yes: '是', |
||||
|
}, |
||||
|
} |
||||
@ -0,0 +1,535 @@ |
|||||
|
<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:70vh;" :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="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.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="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.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="150px" 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="150px" 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="150px" 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: 20px;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' |
||||
|
|
||||
|
// 响应式数据 |
||||
|
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 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('保存失败') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 删除翻译 - 打开确认对话框 |
||||
|
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 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 取消删除 |
||||
|
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> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue