5 Commits

  1. 18
      src/components/locales/lang/en.js
  2. 91
      src/components/locales/lang/zh-CN.js
  3. 3
      src/utils/menuTreePermission.js
  4. 24
      src/views/moneyManage/financialAccount/cashFlow.vue
  5. 286
      src/views/moneyManage/financialAccount/performanceAttribution.vue
  6. 2
      src/views/walletManage/components/WalletDetailTemplate.vue

18
src/components/locales/lang/en.js

@ -10,6 +10,7 @@ export default {
pleaseInputName: "Enter name", pleaseInputName: "Enter name",
customerName: "Customer", customerName: "Customer",
customerNamePlaceholder: "Enter customer name", customerNamePlaceholder: "Enter customer name",
customer: "Customer",
jwcode: "Homily ID", jwcode: "Homily ID",
jwcodePlaceholder: "Enter Homily ID", jwcodePlaceholder: "Enter Homily ID",
activityName: "Activity", activityName: "Activity",
@ -203,6 +204,7 @@ export default {
refreshFailed: 'Refresh failed: {msg}', refreshFailed: 'Refresh failed: {msg}',
unknownError: 'Unknown error', unknownError: 'Unknown error',
refreshError: 'Refresh error, try again', refreshError: 'Refresh error, try again',
refundagain:'Refund submitted. Please do not submit again',
logoutSuccess: 'Logged out', logoutSuccess: 'Logged out',
staffHidden: 'Staff data hidden', staffHidden: 'Staff data hidden',
staffShown: 'Staff data shown', staffShown: 'Staff data shown',
@ -1345,6 +1347,22 @@ export default {
invalidFormat:"Invalid amount format. Maximum 2 decimal places allowed.", invalidFormat:"Invalid amount format. Maximum 2 decimal places allowed.",
paymentMust:"Payment amount must be 0", paymentMust:"Payment amount must be 0",
remarksexceed:"Remarks cannot exceed 100 characters", remarksexceed:"Remarks cannot exceed 100 characters",
marketConsumption:"Market Consumption Gold Performance Adjustment",
time:"Select Time",
coefficient:"Coefficient Adjustment",
coefficientPlaceholder:"Please enter coefficient adjustment",
adjustment:"Transfer In",
adjustmentOut:"Transfer Out",
marketTeam:"Market Team",
total:"Total",
performanceAdjustment:"Performance Adjustment",
payTime:"Payment Time",
orderCode:"System Transaction No.",
receivedMarketName:"Received Market",
performanceMarket:"Performance Market",
goodsName:"Income Category",
goodNum:"Quantity",
payType:"Payment Method",
} }
}, },

91
src/components/locales/lang/zh-CN.js

@ -10,6 +10,7 @@ export default {
pleaseInputName: "请输入姓名", pleaseInputName: "请输入姓名",
customerName: "客户姓名", customerName: "客户姓名",
customerNamePlaceholder: "请输入客户姓名", customerNamePlaceholder: "请输入客户姓名",
customer: "客户",
jwcode: "精网号", jwcode: "精网号",
jwcodePlaceholder: "请输入精网号", jwcodePlaceholder: "请输入精网号",
activityName: "活动名称", activityName: "活动名称",
@ -107,7 +108,7 @@ export default {
add: "添加", add: "添加",
addUser: "新增用户", addUser: "新增用户",
addRole: "新增角色", addRole: "新增角色",
addCashFlow:"新增流水",
addCashFlow: "新增流水",
save: "保存", save: "保存",
saving: "保存中...", saving: "保存中...",
addActivity: "新增活动", addActivity: "新增活动",
@ -173,7 +174,7 @@ export default {
all: "全部", all: "全部",
unknownSubmitter: "未知提交人", unknownSubmitter: "未知提交人",
noAuditorRecorded: "未记录审核人", noAuditorRecorded: "未记录审核人",
noExecutorRecorded: "未记录执行人"
noExecutorRecorded: "未记录执行人",
}, },
// 权限模块 // 权限模块
@ -183,10 +184,11 @@ export default {
changeRoleConfirmContent1: "确认修改权限角色?<br>您正在将【", changeRoleConfirmContent1: "确认修改权限角色?<br>您正在将【",
changeRoleConfirmContent2: "】的权限角色从【", changeRoleConfirmContent2: "】的权限角色从【",
changeRoleConfirmContent3: "】修改为【", changeRoleConfirmContent3: "】修改为【",
changeRoleConfirmContent4: "】<br>变更后,该用户的可操作权限将同步更新为新角色配置,涉及数据访问、功能操作等权限变化,请谨慎确认。",
changeRoleConfirmContent4:
"】<br>变更后,该用户的可操作权限将同步更新为新角色配置,涉及数据访问、功能操作等权限变化,请谨慎确认。",
changeRoleSuccessContent1: "用户", changeRoleSuccessContent1: "用户",
changeRoleSuccessContent2: "的权限角色已更改为【", changeRoleSuccessContent2: "的权限角色已更改为【",
roleRegionNote: "此地区无实际意义,仅用于各分部负责人查看其地区角色"
roleRegionNote: "此地区无实际意义,仅用于各分部负责人查看其地区角色",
}, },
// 提示信息组 // 提示信息组
elmessage: { elmessage: {
@ -209,6 +211,7 @@ export default {
jumpSuccess: "跳转成功", jumpSuccess: "跳转成功",
jumpFailed: "跳转失败", jumpFailed: "跳转失败",
refundFailed: "退款失败", refundFailed: "退款失败",
refundagain:"已提交退款,请勿重复提交",
oldPasswordError: "原密码错误,请重新输入", oldPasswordError: "原密码错误,请重新输入",
addSuccess: "添加成功", // 大写是添加成功,小写是新增 addSuccess: "添加成功", // 大写是添加成功,小写是新增
addsuccess: "新增成功", addsuccess: "新增成功",
@ -407,7 +410,7 @@ export default {
activityLoadFailed: "活动列表加载失败,请稍后重试", activityLoadFailed: "活动列表加载失败,请稍后重试",
activityDataLoadFailed: "活动数据加载异常,请稍后重试", activityDataLoadFailed: "活动数据加载异常,请稍后重试",
getDataFailed: "获取数据失败", getDataFailed: "获取数据失败",
networkError:"网络错误",
networkError: "网络错误",
exportWalletDetailError: "导出钱包明细出错", exportWalletDetailError: "导出钱包明细出错",
selectCompanyWallet: "请选择公司钱包", selectCompanyWallet: "请选择公司钱包",
// 权限 // 权限
@ -473,9 +476,9 @@ export default {
activity: "活动名称", activity: "活动名称",
receiveArea: "到账地区", receiveArea: "到账地区",
performanceMarket: "业绩归属地区", performanceMarket: "业绩归属地区",
receiveType:"收入类别",
paymentMethod:"付款方式",
nums:"个数",
receiveType: "收入类别",
paymentMethod: "付款方式",
nums: "个数",
startTime: "开始时间", startTime: "开始时间",
endTime: "结束时间", endTime: "结束时间",
status: "状态", status: "状态",
@ -549,7 +552,7 @@ export default {
activityStatus: { activityStatus: {
notStarted: "未开始", notStarted: "未开始",
inProgress: "进行中", inProgress: "进行中",
ended: "已结束"
ended: "已结束",
}, },
operation: "操作", operation: "操作",
configTime: "配置时间", configTime: "配置时间",
@ -697,7 +700,7 @@ export default {
similarCosumeRecords: "检测到该用户近期有相似消耗记录", similarCosumeRecords: "检测到该用户近期有相似消耗记录",
rechargePermanentGold: "充值永久金币", rechargePermanentGold: "充值永久金币",
buy: "购买", buy: "购买",
orderStatus:'订单状态',
orderStatus: "订单状态",
operator: "操作人", operator: "操作人",
submitter: "提交人", submitter: "提交人",
continueOperation: "是否继续操作?", continueOperation: "是否继续操作?",
@ -1068,8 +1071,8 @@ export default {
placeholder: "请选择语言", placeholder: "请选择语言",
options: { options: {
zhCN: "中文(简体)", zhCN: "中文(简体)",
en: "English"
}
en: "English",
},
}, },
showStaffData: "显示员工数据", showStaffData: "显示员工数据",
hideStaffData: "隐藏员工数据", hideStaffData: "隐藏员工数据",
@ -1104,7 +1107,7 @@ export default {
againPasswordPlaceholder: "请再次输入新密码", againPasswordPlaceholder: "请再次输入新密码",
tips: { tips: {
lengthAndChars: "密码由8-16位数字、字母或符号组成", lengthAndChars: "密码由8-16位数字、字母或符号组成",
complexity: "至少含2种以上字符"
complexity: "至少含2种以上字符",
}, },
rules: { rules: {
allowedChars: "密码只能包含数字、字母或符号", allowedChars: "密码只能包含数字、字母或符号",
@ -1113,15 +1116,15 @@ export default {
complexity: "密码至少包含两种类型(数字、字母或符号)", complexity: "密码至少包含两种类型(数字、字母或符号)",
notMatch: "两次输入密码不一致", notMatch: "两次输入密码不一致",
newPasswordRequired: "新密码不能为空", newPasswordRequired: "新密码不能为空",
againPasswordRequired: "请再次输入新密码"
againPasswordRequired: "请再次输入新密码",
}, },
submitting: "修改中..."
submitting: "修改中...",
}, },
difftime: { difftime: {
minuteAgo: "分钟前", minuteAgo: "分钟前",
hourAgo: "小时前", hourAgo: "小时前",
yesterday: "昨天", yesterday: "昨天",
}
},
}, },
// 现金管理 // 现金管理
@ -1161,9 +1164,9 @@ export default {
paymentAsia: "PaymentAsia", paymentAsia: "PaymentAsia",
transfer: "E-Transfer", transfer: "E-Transfer",
iotPay: "IOT Pay", iotPay: "IOT Pay",
stripe3:'Stripe3',
paysolution:'paysolution',
stripe2:'Stripe2',
stripe3: "Stripe3",
paysolution: "paysolution",
stripe2: "Stripe2",
}, },
statusList: { statusList: {
submitted: "已提交", submitted: "已提交",
@ -1312,7 +1315,7 @@ export default {
refundConfirmTitle: "退款确认", refundConfirmTitle: "退款确认",
refundConfirmContent: "确定要对订单 {orderNo} 进行退款吗?", refundConfirmContent: "确定要对订单 {orderNo} 进行退款吗?",
//钱包 //钱包
wallet:{
wallet: {
HongKongWallet: "香港钱包", HongKongWallet: "香港钱包",
MalaysiaWallet: "马来西亚钱包", MalaysiaWallet: "马来西亚钱包",
CanadaWallet: "加拿大钱包", CanadaWallet: "加拿大钱包",
@ -1321,9 +1324,9 @@ export default {
ThailandHAWallet: "泰国HA钱包", ThailandHAWallet: "泰国HA钱包",
ThailandHSWallet: "泰国HS钱包", ThailandHSWallet: "泰国HS钱包",
VietnamHCMWallet: "越南钱包", VietnamHCMWallet: "越南钱包",
BeijingWallet: "北京公司钱包"
BeijingWallet: "北京公司钱包",
}, },
cashFlow:{
cashFlow: {
otherIncome:"其他收入", otherIncome:"其他收入",
addFee:"手续费补充", addFee:"手续费补充",
performanceMarket:"业绩归属地区", performanceMarket:"业绩归属地区",
@ -1352,20 +1355,36 @@ export default {
remarks:"备注", remarks:"备注",
remarksPlaceholder:"请输入备注 (选填,限制100字)", remarksPlaceholder:"请输入备注 (选填,限制100字)",
remarkPlaceholderDate:"需填写手续费结算周期(如“2026年3月12日iPay88手续费”)", remarkPlaceholderDate:"需填写手续费结算周期(如“2026年3月12日iPay88手续费”)",
cancel:"取消",
submit:"提交",
ipay88:"iPay88",
cardPayment:"刷卡",
fixedProcessingFee:"固定手续费",
settlementRegion:"到账地区",
Malaysia:"马来西亚",
processingFee:"手续费",
processingFeePlaceholder:"请输入手续费",
quantityMustBeNumber:"个数必须为数字",
invalidFormat:"金额格式不正确,最多两位小数",
paymentMust:"付款金额必须为0",
remarksexceed:"备注不能超过100字",
}
cancel: "取消",
submit: "提交",
ipay88: "iPay88",
cardPayment: "刷卡",
fixedProcessingFee: "固定手续费",
settlementRegion: "到账地区",
Malaysia: "马来西亚",
processingFee: "手续费",
processingFeePlaceholder: "请输入手续费",
quantityMustBeNumber: "个数必须为数字",
invalidFormat: "金额格式不正确,最多两位小数",
paymentMust: "付款金额必须为0",
remarksexceed: "备注不能超过100字",
marketConsumption: "市场消耗金币业绩调整",
time: "选择时间",
coefficient: "系数调整",
coefficientPlaceholder: "请输入系数调整",
adjustment: "调入",
adjustmentOut: "调出",
marketTeam: "市场团队",
total: "合计",
performanceAdjustment: "业绩调整",
payTime: "付款时间",
orderCode: "系统交易号",
receivedMarketName: "到账地区",
performanceMarket: "业绩归属地区",
goodsName: "收入类别",
goodNum: "个数",
payType: "付款方式",
},
}, },
// 消息 // 消息

3
src/utils/menuTreePermission.js

@ -175,6 +175,9 @@ export const permissionMapping = {
financial_accounting: 147, // 财务核算 financial_accounting: 147, // 财务核算
cash_flow_ledger: 148, // 资金流水账 cash_flow_ledger: 148, // 资金流水账
performance_attribution_accounting: 149, // 业绩归属台账 performance_attribution_accounting: 149, // 业绩归属台账
new_transaction_flow: 162, // 新增流水
performance_adjustment: 163, // 业绩调整
} }
// 递归查找菜单中是否存在目标id // 递归查找菜单中是否存在目标id

24
src/views/moneyManage/financialAccount/cashFlow.vue

@ -13,9 +13,10 @@ import { normalizePayType,MarketNameForId, CurrencyForId, } from '@/views/moneyM
import { isTemplate } from 'element-plus/es/utils/index.mjs' import { isTemplate } from 'element-plus/es/utils/index.mjs'
import { Row } from 'vxe-pc-ui' import { Row } from 'vxe-pc-ui'
import CashManagement from '@/components/workspace/CashManagement.vue' import CashManagement from '@/components/workspace/CashManagement.vue'
import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
const adminStore = useAdminStore() const adminStore = useAdminStore()
const { adminData } = storeToRefs(adminStore)
const { adminData, menuTree,flag } = storeToRefs(adminStore)
const { t } = useI18n() const { t } = useI18n()
const route = useRoute() const route = useRoute()
@ -38,6 +39,16 @@ const paytypeList = [
t('cash.payMethods.check'), // t('cash.payMethods.check'), //
] ]
//
const hasNewTransactionFlow = ref(false)
//
const initPermissions = async () => {
if (!menuTree.value || !menuTree.value.length) return;
//
hasNewTransactionFlow.value = hasMenuPermission(menuTree.value, permissionMapping.new_transaction_flow);
};
const payPlatformOptions = ref([...paytypeList]) const payPlatformOptions = ref([...paytypeList])
const marketFilter = (value) => { const marketFilter = (value) => {
@ -262,7 +273,6 @@ const openRefundConfirm = () => {
permanentGold: null, permanentGold: null,
freeGold: null, freeGold: null,
} }
} }
const openRefundDialog = () => { const openRefundDialog = () => {
refundDialog.value = true refundDialog.value = true
@ -286,6 +296,10 @@ const resetRefund = () => {
} }
const handleRefund = async () => { const handleRefund = async () => {
try { try {
if(refundFormData.value.status == 6){
ElMessage.error(t('elmessage.refundagain'))
return
}
if (refundFormData.value.refundModel == 1) { if (refundFormData.value.refundModel == 1) {
if (Number(refundFormData.value.permanentGold || 0) > Number(refundFormData.value.oldpermanentGold || 0)) { if (Number(refundFormData.value.permanentGold || 0) > Number(refundFormData.value.oldpermanentGold || 0)) {
ElMessage.error(t('elmessage.limitRefundGoldNotExceedOriginal')) ElMessage.error(t('elmessage.limitRefundGoldNotExceedOriginal'))
@ -665,6 +679,7 @@ const handlePreviewClick=()=>{
} }
} }
onMounted(async () => { onMounted(async () => {
await initPermissions()
await getMarket() await getMarket()
await getPayPlatformOptions() await getPayPlatformOptions()
// //
@ -736,7 +751,7 @@ onMounted(async () => {
<el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button> <el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
</div> </div>
<div class="newAdd"> <div class="newAdd">
<el-button class="newAdd_btn" @click="addCashFlow('other')">{{ t('common.addCashFlow') }}</el-button>
<el-button v-if="hasNewTransactionFlow" class="newAdd_btn" @click="addCashFlow('other')">{{ t('common.addCashFlow') }}</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -895,7 +910,7 @@ onMounted(async () => {
</el-form> </el-form>
<div style="display:flex;justify-content: center;margin-top: 5vh;" class="btnDiv"> <div style="display:flex;justify-content: center;margin-top: 5vh;" class="btnDiv">
<el-button type="default" style="background-color: #7E91FF;" @click="showDetail = false">{{t('common.cancel')}}</el-button> <el-button type="default" style="background-color: #7E91FF;" @click="showDetail = false">{{t('common.cancel')}}</el-button>
<el-button type="primary" style="background-color: #2741DE; margin-left: 2.5vw;" @click="openRefundConfirm">{{ t('common.refund') }}</el-button>
<el-button v-show="formDataRow.orderCode.slice(0, 4) == 'GOLD' && formDataRow.status === 4 " type="primary" style="background-color: #2741DE; margin-left: 2.5vw;" @click="openRefundConfirm">{{ t('common.refund') }}</el-button>
</div> </div>
</el-dialog> </el-dialog>
@ -1321,6 +1336,7 @@ onMounted(async () => {
} }
.newAdd { .newAdd {
margin-left: auto;
display: flex; display: flex;
width: 240px; width: 240px;
justify-content: flex-end; justify-content: flex-end;

286
src/views/moneyManage/financialAccount/performanceAttribution.vue

@ -4,31 +4,45 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/util/http.js' import request from '@/util/http.js'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { refundOnline,performanceSelect,exportPerformance,adjustment } from '@/api/cash/financialAccount.js'
import { refundOnline, performanceSelect, exportPerformance, adjustment } from '@/api/cash/financialAccount.js'
import { getUserInfo } from '@/api/common/common.js' import { getUserInfo } from '@/api/common/common.js'
import { useAdminStore } from '@/store/index.js'
import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
import { storeToRefs } from 'pinia'
const adminStore = useAdminStore()
const { menuTree, flag } = storeToRefs(adminStore)
const adminData = ref({}) const adminData = ref({})
const { t } = useI18n() const { t } = useI18n()
const paytypeList = [ const paytypeList = [
t('cash.payMethods.stripe'),
t('cash.payMethods.paymentAsia'),
t('cash.payMethods.ipay88'),
t('cash.payMethods.bankTransfer'),
t('cash.payMethods.card'),
t('cash.payMethods.cash'),
t('cash.payMethods.check'),
t('cash.payMethods.grabpay'),
t('cash.payMethods.nets'),
t('cash.payMethods.transfer'),
t('cash.payMethods.iotPay'),
t('cash.payMethods.stripe3'),
t('cash.payMethods.paypal'),
t('cash.payMethods.stripe'),
t('cash.payMethods.paymentAsia'),
t('cash.payMethods.ipay88'),
t('cash.payMethods.bankTransfer'),
t('cash.payMethods.card'),
t('cash.payMethods.cash'),
t('cash.payMethods.check'),
t('cash.payMethods.grabpay'),
t('cash.payMethods.nets'),
t('cash.payMethods.transfer'),
t('cash.payMethods.iotPay'),
t('cash.payMethods.stripe3'),
t('cash.payMethods.paypal'),
] ]
const hasperformanceAdjustment = ref(false)
//
const initPermissions = async () => {
if (!menuTree.value || !menuTree.value.length) return;
//
hasperformanceAdjustment.value = hasMenuPermission(menuTree.value, permissionMapping.performance_adjustment);
console.log('业绩调整权限', hasperformanceAdjustment.value);
};
const payPlatformOptions = ref([...paytypeList]) const payPlatformOptions = ref([...paytypeList])
const statusOptions = [ const statusOptions = [
@ -94,7 +108,7 @@ const fetchData = async () => {
const params = { const params = {
pageNum: queryParams.pageNum, pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize, pageSize: queryParams.pageSize,
performanceDTO:{
performanceDTO: {
jwcode: queryParams.jwcode, jwcode: queryParams.jwcode,
adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [], adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [],
customerMarket: queryParams.customerMarket, customerMarket: queryParams.customerMarket,
@ -102,7 +116,7 @@ const fetchData = async () => {
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '', endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
} }
} }
console.log('查询参数:', params) console.log('查询参数:', params)
const res = await performanceSelect(params) const res = await performanceSelect(params)
if (res.code == 200) { if (res.code == 200) {
@ -114,7 +128,7 @@ const fetchData = async () => {
} else { } else {
ElMessage.error(res.msg || t('elmessage.getDataFailed')) ElMessage.error(res.msg || t('elmessage.getDataFailed'))
loading.value = false loading.value = false
}
}
} catch (error) { } catch (error) {
console.error(error) console.error(error)
loading.value = false loading.value = false
@ -125,9 +139,9 @@ const fetchData = async () => {
const handleAdminInfo = async () => { const handleAdminInfo = async () => {
try { try {
const res = await getUserInfo() const res = await getUserInfo()
adminData.value = res || {}
console.log('adminData.value:', adminData.value);
adminData.value = res || {}
console.log('adminData.value:', adminData.value);
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error(t('elmessage.getDataFailed')) ElMessage.error(t('elmessage.getDataFailed'))
@ -168,7 +182,7 @@ const handleRefund = (row) => {
ElMessage.success(t('elmessage.refundSubmitSuccess')) ElMessage.success(t('elmessage.refundSubmitSuccess'))
// //
fetchData() fetchData()
}).catch(() => {})
}).catch(() => { })
} }
// ==================== ==================== // ==================== ====================
@ -178,12 +192,12 @@ const exportList = ref([])
const exportListLoading = ref(false) const exportListLoading = ref(false)
// Excel // Excel
const handleExport = async () => {
const handleExport = async () => {
try { try {
const params = {
const params = {
pageNum: queryParams.pageNum, pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize, pageSize: queryParams.pageSize,
performanceDTO:{
performanceDTO: {
jwcode: queryParams.jwcode, jwcode: queryParams.jwcode,
adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [], adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [],
customerMarket: queryParams.customerMarket, customerMarket: queryParams.customerMarket,
@ -191,15 +205,15 @@ const handleExport = async () => {
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '', endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
} }
} }
// TODO: URL // TODO: URL
const res = await exportPerformance(params) const res = await exportPerformance(params)
if(res.code == 200){
if (res.code == 200) {
console.log('导出参数', params)
ElMessage.success(t('elmessage.exportSuccess'))
}
console.log('导出参数', params)
ElMessage.success(t('elmessage.exportSuccess'))
}
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error(t('elmessage.exportError')) ElMessage.error(t('elmessage.exportError'))
@ -270,21 +284,21 @@ const adjustVisible = ref(false)
const adjustTime = ref('') const adjustTime = ref('')
const adjustCoefficient = ref('') const adjustCoefficient = ref('')
const matrixMarkets = [
{ key: 'sg', label: '新加坡' },
{ key: 'my', label: '马来西亚' },
{ key: 'hk', label: '香港' },
{ key: 'th', label: '泰国' },
{ key: 'vn', label: '越南' },
{ key: 'ca', label: '加拿大' }
]
const matrixMarkets = computed(() => [
{ key: 'sg', label: t('cash.markets.Singapore') },
{ key: 'my', label: t('cash.markets.Malaysia') },
{ key: 'hk', label: t('cash.markets.HongKong') },
{ key: 'th', label: t('cash.markets.Thailand') },
{ key: 'vn', label: t('clientCount.market.vnGold') },
{ key: 'ca', label: t('cash.markets.Canada') }
])
const adjustData = ref([]) const adjustData = ref([])
const initAdjustData = () => { const initAdjustData = () => {
adjustData.value = matrixMarkets.map(rowMarket => {
const row = { inMarket: rowMarket.label + '客户' }
matrixMarkets.forEach(colMarket => {
adjustData.value = matrixMarkets.value.map(rowMarket => {
const row = { inMarket: rowMarket.label + t('common.customer') }
matrixMarkets.value.forEach(colMarket => {
row[colMarket.key] = '' // row[colMarket.key] = '' //
}) })
return row return row
@ -300,9 +314,9 @@ const handleAdjustment = () => {
const computedAdjustData = computed(() => { const computedAdjustData = computed(() => {
const data = [...adjustData.value] const data = [...adjustData.value]
const sumRow = { inMarket: '合计', isSum: true }
const sumRow = { inMarket: t('cash.cashFlow.total'), isSum: true }
matrixMarkets.forEach(colMarket => {
matrixMarkets.value.forEach(colMarket => {
let colSum = 0 let colSum = 0
adjustData.value.forEach(row => { adjustData.value.forEach(row => {
const val = parseFloat(row[colMarket.key]) const val = parseFloat(row[colMarket.key])
@ -317,7 +331,7 @@ const computedAdjustData = computed(() => {
const getRowTotal = (row) => { const getRowTotal = (row) => {
let sum = 0 let sum = 0
matrixMarkets.forEach(colMarket => {
matrixMarkets.value.forEach(colMarket => {
const val = parseFloat(row[colMarket.key]) const val = parseFloat(row[colMarket.key])
if (!isNaN(val)) sum += val if (!isNaN(val)) sum += val
}) })
@ -335,18 +349,18 @@ const formatNumber = (val) => {
const submitAdjustment = async () => { const submitAdjustment = async () => {
if (!adjustTime.value) { if (!adjustTime.value) {
ElMessage.warning('请选择时间')
ElMessage.warning(t('cash.cashFlow.time'))
return return
} }
if (!adjustCoefficient.value) { if (!adjustCoefficient.value) {
ElMessage.warning('请输入系数')
ElMessage.warning(t('cash.cashFlow.coefficientPlaceholder'))
return return
} }
// matrix (66) // matrix (66)
// 0 // 0
const matrix = adjustData.value.map(row => { const matrix = adjustData.value.map(row => {
return matrixMarkets.map(colMarket => {
return matrixMarkets.value.map(colMarket => {
const val = parseFloat(row[colMarket.key]) const val = parseFloat(row[colMarket.key])
return isNaN(val) ? 0 : val return isNaN(val) ? 0 : val
}) })
@ -356,21 +370,22 @@ const submitAdjustment = async () => {
const payload = { const payload = {
matrix: matrix, matrix: matrix,
weight: parseFloat(adjustCoefficient.value), // weight: parseFloat(adjustCoefficient.value), //
createTime: adjustTime.value,
time: adjustTime.value,
submitterId: adminData.value.id || 1000063, // adminData submitterId: adminData.value.id || 1000063, // adminData
submitterMarket: adminData.value.marketName || '总部' // submitterMarket: adminData.value.marketName || '总部' //
} }
console.log('提交的封装数据:', JSON.stringify(payload, null, 2)) console.log('提交的封装数据:', JSON.stringify(payload, null, 2))
await adjustment(payload) await adjustment(payload)
ElMessage.success('提交成功')
ElMessage.success(t('common.submitSuccess'))
adjustVisible.value = false adjustVisible.value = false
fetchData() fetchData()
} }
onMounted( async() => {
await handleAdminInfo()
onMounted(async () => {
await initPermissions()
await handleAdminInfo()
getMarket() getMarket()
await fetchData() await fetchData()
}) })
@ -388,86 +403,66 @@ onMounted( async() => {
<el-input v-model="queryParams.jwcode" :placeholder="t('common.jwcodePlaceholder')" clearable /> <el-input v-model="queryParams.jwcode" :placeholder="t('common.jwcodePlaceholder')" clearable />
</div> </div>
<div class="search-item"> <div class="search-item">
<span class="label">{{ t('common.market') }}</span>
<span class="label">{{ t('common_list.market') }}</span>
<!-- 下拉多选使用 el-cascader 匹配地区树结构 --> <!-- 下拉多选使用 el-cascader 匹配地区树结构 -->
<el-cascader
v-model="queryParams.customerMarket"
:options="marketOptions"
:props="{ multiple: true, emitPath: false }"
collapse-tags
collapse-tags-tooltip
:placeholder="t('common.marketPlaceholder')"
clearable
style="width: 8vw;"
/>
<el-cascader v-model="queryParams.customerMarket" :options="marketOptions"
:props="{ multiple: true, emitPath: false }" collapse-tags collapse-tags-tooltip
:placeholder="t('common_list.marketPlaceholder')" clearable style="width: 8vw;" />
</div> </div>
<div class="search-item" style="width: auto;">
<div class="search-item" style="width: auto;">
<span class="label">{{ t('common.payTime2') }}</span> <span class="label">{{ t('common.payTime2') }}</span>
<el-date-picker
v-model="queryParams.timeRange"
type="datetimerange"
:range-separator="t('common.to')"
:start-placeholder="t('common.startTime')"
:end-placeholder="t('common.endTime')"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
style="width: 18vw;"
/>
<el-date-picker v-model="queryParams.timeRange" type="datetimerange" :range-separator="t('common.to')"
:start-placeholder="t('common.startTime')" :end-placeholder="t('common.endTime')"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" style="width: 18vw;" />
</div> </div>
</div> </div>
<div class="search-row">
<div class="search-row">
<el-button type="primary" @click="handleSearch">{{ t('common.search') }}</el-button> <el-button type="primary" @click="handleSearch">{{ t('common.search') }}</el-button>
<el-button type="primary" @click="handleExport">{{ t('common.exportExcel') }}</el-button>
<el-button type="primary" @click="openExportList">{{ t('common.viewExportList') }}</el-button>
<el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
<button class="adjust-btn" @click="handleAdjustment">业绩调整</button>
<el-button type="primary" @click="handleExport">{{ t('common.exportExcel') }}</el-button>
<el-button type="primary" @click="openExportList">{{ t('common.viewExportList') }}</el-button>
<el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
<button v-if="hasperformanceAdjustment" class="adjust-btn" @click="handleAdjustment">{{
t('cash.cashFlow.performanceAdjustment') }}</button>
</div> </div>
</div> </div>
</el-card> </el-card>
<!-- 表格区域 --> <!-- 表格区域 -->
<el-card class="table-card"> <el-card class="table-card">
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1;" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ background: '#F3FAFE', color: '#333',textAlign: 'center' }">
<el-table-column type="index" :label="t('common_list.id')" min-width="60" align="center" fixed="left" >
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1;"
:cell-style="{ textAlign: 'center' }"
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center' }">
<el-table-column type="index" :label="t('common_list.id')" min-width="60" align="center" fixed="left">
<template #default="scope"> <template #default="scope">
<span>{{ scope.$index + 1 + (queryParams.pageNum - 1) * queryParams.pageSize }}</span> <span>{{ scope.$index + 1 + (queryParams.pageNum - 1) * queryParams.pageSize }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" min-width="120" fixed="left" />
<el-table-column prop="payTime" :label="t('cash.cashFlow.payTime')" min-width="180" />
<el-table-column prop="orderCode" :label="t('cash.cashFlow.orderCode')" min-width="350" show-overflow-tooltip />
<el-table-column prop="receivedMarketName" :label="t('cash.cashFlow.receivedMarketName')" min-width="120"
show-overflow-tooltip />
<el-table-column prop="performanceMarketName" :label="t('cash.cashFlow.performanceMarket')" min-width="120"
show-overflow-tooltip />
<el-table-column prop="name" :label="t('common_list.name')" min-width="150" show-overflow-tooltip /> <el-table-column prop="name" :label="t('common_list.name')" min-width="150" show-overflow-tooltip />
<el-table-column prop="marketName" :label="t('common_list.market')" min-width="120" show-overflow-tooltip />
<el-table-column prop="orderCode" :label="t('common_list.orderCode')" min-width="280" show-overflow-tooltip />
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" min-width="150" align="right">
<!-- <template #default="{ row }">
{{ row.paymentAmount }} {{ row.paymentCurrency }}
</template> -->
</el-table-column>
<el-table-column prop="paymentCurrency" :label="t('common_list.payCurrency')" min-width="180" show-overflow-tooltip />
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" min-width="150" align="right">
<!-- <template #default="{ row }">
{{ row.receivedAmount }} {{ row.receivedCurrency }}
</template> -->
</el-table-column>
<el-table-column prop="receivedCurrency" :label="t('common_list.receiveCurrency')" min-width="180" show-overflow-tooltip />
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" min-width="100" align="right" />
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" min-width="120" />
<el-table-column prop="goodsName" :label="t('cash.cashFlow.goodsName')" min-width="120" show-overflow-tooltip />
<el-table-column prop="remark" :label="t('common_list.remark')" min-width="120" show-overflow-tooltip />
<el-table-column prop="goodNum" :label="t('cash.cashFlow.goodNum')" min-width="120" show-overflow-tooltip />
<el-table-column prop="payType" :label="t('cash.cashFlow.payType')" min-width="120" show-overflow-tooltip />
<el-table-column prop="receivedCurrency" :label="t('common_list.receiveCurrency')" min-width="180"
show-overflow-tooltip />
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" min-width="150" />
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" min-width="100" />
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" min-width="150" />
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<div class="pagination-container"> <div class="pagination-container">
<el-pagination
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
:current-page="queryParams.pageNum"
:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 50, 100]"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
/>
<el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
:current-page="queryParams.pageNum" :page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
@size-change="handlePageSizeChange" @current-change="handleCurrentChange" />
</div> </div>
</el-card> </el-card>
@ -504,47 +499,49 @@ onMounted( async() => {
</el-dialog> </el-dialog>
<!-- 业绩调整弹窗 --> <!-- 业绩调整弹窗 -->
<el-dialog v-model="adjustVisible" title="市场消耗金币业绩调整" width="80%" top="5vh" align-center class="custom-adjust-dialog">
<el-dialog v-model="adjustVisible" :title="t('cash.cashFlow.marketConsumption')" width="80%" top="5vh" align-center
class="custom-adjust-dialog">
<template #header="{ titleId, titleClass }"> <template #header="{ titleId, titleClass }">
<div style="text-align: center; font-weight: bold; font-size: 18px;" :id="titleId" :class="titleClass">市场消耗金币业绩调整</div>
<div style="text-align: center; font-weight: bold; font-size: 18px;" :id="titleId" :class="titleClass">{{
t('cash.cashFlow.marketConsumption') }}</div>
</template> </template>
<div style="display: flex; gap: 40px; margin-bottom: 20px; align-items: center;"> <div style="display: flex; gap: 40px; margin-bottom: 20px; align-items: center;">
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span style="margin-right: 10px; font-weight: bold;">选择时间</span>
<el-date-picker
v-model="adjustTime"
type="datetime"
placeholder="选择时间"
value-format="YYYY-MM-DD HH:mm:ss"
/>
<span style="margin-right: 10px; font-weight: bold;">{{ t('cash.cashFlow.time') }}</span>
<el-date-picker v-model="adjustTime" type="datetime" :placeholder="t('cash.cashFlow.time')"
value-format="YYYY-MM-DD HH:mm:ss" />
</div> </div>
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span style="margin-right: 10px; font-weight: bold;">系数调整</span>
<el-input v-model="adjustCoefficient" placeholder="请输入系数调整" style="width: 200px;" @input="adjustCoefficient = formatNumber(adjustCoefficient)" />
<span style="margin-right: 10px; font-weight: bold;">{{ t('cash.cashFlow.coefficient') }}</span>
<el-input v-model="adjustCoefficient" :placeholder="t('cash.cashFlow.coefficientPlaceholder')"
style="width: 200px;" @input="adjustCoefficient = formatNumber(adjustCoefficient)" />
</div> </div>
</div> </div>
<el-table :data="computedAdjustData" border style="width: 100%" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center', padding: '0' }">
<el-table :data="computedAdjustData" border style="width: 100%" :cell-style="{ textAlign: 'center' }"
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center', padding: '0' }">
<el-table-column width="150" align="center" fixed="left"> <el-table-column width="150" align="center" fixed="left">
<template #header> <template #header>
<div class="diagonal-header"> <div class="diagonal-header">
<span class="top-right">调入</span>
<span class="bottom-left">调出</span>
<span class="top-right">{{ t('cash.cashFlow.adjustment') }}</span>
<span class="bottom-left">{{ t('cash.cashFlow.adjustmentOut') }}</span>
</div> </div>
</template> </template>
<template #default="{ row }"> <template #default="{ row }">
<span style="font-weight: bold;">{{ row.inMarket }}</span> <span style="font-weight: bold;">{{ row.inMarket }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-for="col in matrixMarkets" :key="col.key" :label="col.label + '市场团队'" min-width="120" align="center">
<el-table-column v-for="col in matrixMarkets" :key="col.key" :label="col.label + ' ' + t('cash.cashFlow.marketTeam')"
min-width="120" align="center">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row.isSum">{{ row[col.key] }}</span> <span v-if="row.isSum">{{ row[col.key] }}</span>
<el-input v-else v-model="row[col.key]" @input="row[col.key] = formatNumber($event)" placeholder="" class="seamless-input" />
<el-input v-else v-model="row[col.key]" @input="row[col.key] = formatNumber($event)" placeholder=""
class="seamless-input" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="合计" min-width="120" align="center" fixed="right">
<el-table-column :label="t('cash.cashFlow.total')" min-width="120" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
{{ getRowTotal(row) }} {{ getRowTotal(row) }}
</template> </template>
@ -553,8 +550,8 @@ onMounted( async() => {
<template #footer> <template #footer>
<div class="dialog-footer" style="text-align: center;"> <div class="dialog-footer" style="text-align: center;">
<el-button type="primary" plain @click="adjustVisible = false" style="width: 100px;">取消</el-button>
<el-button type="primary" @click="submitAdjustment" style="width: 100px;">提交</el-button>
<el-button type="primary" plain @click="adjustVisible = false" style="width: 100px;">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="submitAdjustment" style="width: 100px;">{{ t('common.submit') }}</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -563,16 +560,16 @@ onMounted( async() => {
<style scoped lang="scss"> <style scoped lang="scss">
.cash-flow-container { .cash-flow-container {
display: flex;
flex-direction: column;
height: 100%;
display: flex;
flex-direction: column;
height: 100%;
} }
.search-card { .search-card {
margin-bottom: 10px; margin-bottom: 10px;
background: #F3FAFE; // background: #F3FAFE; //
border: none; border: none;
:deep(.el-card__body) { :deep(.el-card__body) {
padding: 15px; padding: 15px;
} }
@ -604,13 +601,14 @@ onMounted( async() => {
text-align: right; text-align: right;
} }
.el-input, .el-select {
.el-input,
.el-select {
width: 8vw; width: 8vw;
} }
} }
.search-btn-group { .search-btn-group {
margin-left: 2vw;
margin-left: 2vw;
display: flex; display: flex;
gap: 10px; gap: 10px;
} }
@ -631,7 +629,7 @@ onMounted( async() => {
border: none; border: none;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
:deep(.el-card__body) { :deep(.el-card__body) {
padding: 20px; padding: 20px;
flex: 1; flex: 1;
@ -662,15 +660,18 @@ onMounted( async() => {
.diagonal-header { .diagonal-header {
position: relative; position: relative;
width: 100%; width: 100%;
height: 50px; /* Set a fixed height to make diagonal line work well */
height: 50px;
/* Set a fixed height to make diagonal line work well */
background: linear-gradient(to top right, transparent 49.5%, #dcdfe6 49.5%, #dcdfe6 50.5%, transparent 50.5%); background: linear-gradient(to top right, transparent 49.5%, #dcdfe6 49.5%, #dcdfe6 50.5%, transparent 50.5%);
} }
.diagonal-header .top-right { .diagonal-header .top-right {
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 15px; right: 15px;
font-weight: bold; font-weight: bold;
} }
.diagonal-header .bottom-left { .diagonal-header .bottom-left {
position: absolute; position: absolute;
bottom: 5px; bottom: 5px;
@ -680,7 +681,8 @@ onMounted( async() => {
/* 业绩调整弹窗全局样式 */ /* 业绩调整弹窗全局样式 */
:deep(.custom-adjust-dialog) { :deep(.custom-adjust-dialog) {
background-color: #f3fafe !important; /* 统一淡蓝色背景 */
background-color: #f3fafe !important;
/* 统一淡蓝色背景 */
border-radius: 8px; border-radius: 8px;
} }
@ -700,11 +702,13 @@ onMounted( async() => {
background-color: transparent !important; background-color: transparent !important;
padding: 0; padding: 0;
} }
.seamless-input :deep(.el-input__inner) { .seamless-input :deep(.el-input__inner) {
text-align: center; text-align: center;
font-size: 14px; font-size: 14px;
height: 100%; height: 100%;
} }
.seamless-input :deep(.el-input__inner:focus) { .seamless-input :deep(.el-input__inner:focus) {
outline: none; outline: none;
} }

2
src/views/walletManage/components/WalletDetailTemplate.vue

@ -316,7 +316,7 @@ onMounted(() => {
<div class="head-card"> <div class="head-card">
<div class="head-card-element"> <div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common_list.jwcode') }}</el-text> <el-text class="mx-1" size="large">{{ $t('common_list.jwcode') }}</el-text>
<el-input v-model="selectData.jwcode" style="width: 12.5vw" placeholder="请输入精网号" clearable />
<el-input v-model="selectData.jwcode" style="width: 12.5vw" :placeholder="$t('common.jwcodePlaceholder')" clearable />
</div> </div>
<div class="head-card-element"> <div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common_list.market') }}</el-text> <el-text class="mx-1" size="large">{{ $t('common_list.market') }}</el-text>

Loading…
Cancel
Save