|
|
|
@ -1,10 +1,10 @@ |
|
|
|
<script setup> |
|
|
|
import { ref, reactive, onMounted, toRefs, nextTick } from 'vue' |
|
|
|
import { ref, reactive, onMounted, toRefs, nextTick, computed } from 'vue' |
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus' |
|
|
|
import request from '@/util/http.js' |
|
|
|
import dayjs from 'dayjs' |
|
|
|
import { useI18n } from 'vue-i18n' |
|
|
|
import { refundOnline,performanceSelect,exportPerformance } from '@/api/cash/financialAccount.js' |
|
|
|
import { refundOnline,performanceSelect,exportPerformance,adjustment } from '@/api/cash/financialAccount.js' |
|
|
|
import { getUserInfo } from '@/api/common/common.js' |
|
|
|
|
|
|
|
|
|
|
|
@ -157,6 +157,7 @@ const handleCurrentChange = (val) => { |
|
|
|
fetchData() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 退款操作 |
|
|
|
const handleRefund = (row) => { |
|
|
|
ElMessageBox.confirm(t('elmessage.refundConfirmContent', { orderNo: row.systemTradeNo }), t('elmessage.refundConfirmTitle'), { |
|
|
|
@ -264,6 +265,110 @@ const getTagText = (state) => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ==================== 业绩调整弹窗相关逻辑 ==================== |
|
|
|
const adjustVisible = ref(false) |
|
|
|
const adjustTime = 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 adjustData = ref([]) |
|
|
|
|
|
|
|
const initAdjustData = () => { |
|
|
|
adjustData.value = matrixMarkets.map(rowMarket => { |
|
|
|
const row = { inMarket: rowMarket.label + '客户' } |
|
|
|
matrixMarkets.forEach(colMarket => { |
|
|
|
row[colMarket.key] = '' // 默认空 |
|
|
|
}) |
|
|
|
return row |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
const handleAdjustment = () => { |
|
|
|
adjustTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss') |
|
|
|
adjustCoefficient.value = '' |
|
|
|
initAdjustData() |
|
|
|
adjustVisible.value = true |
|
|
|
} |
|
|
|
|
|
|
|
const computedAdjustData = computed(() => { |
|
|
|
const data = [...adjustData.value] |
|
|
|
const sumRow = { inMarket: '合计', isSum: true } |
|
|
|
|
|
|
|
matrixMarkets.forEach(colMarket => { |
|
|
|
let colSum = 0 |
|
|
|
adjustData.value.forEach(row => { |
|
|
|
const val = parseFloat(row[colMarket.key]) |
|
|
|
if (!isNaN(val)) colSum += val |
|
|
|
}) |
|
|
|
sumRow[colMarket.key] = colSum |
|
|
|
}) |
|
|
|
|
|
|
|
data.push(sumRow) |
|
|
|
return data |
|
|
|
}) |
|
|
|
|
|
|
|
const getRowTotal = (row) => { |
|
|
|
let sum = 0 |
|
|
|
matrixMarkets.forEach(colMarket => { |
|
|
|
const val = parseFloat(row[colMarket.key]) |
|
|
|
if (!isNaN(val)) sum += val |
|
|
|
}) |
|
|
|
return sum |
|
|
|
} |
|
|
|
|
|
|
|
const formatNumber = (val) => { |
|
|
|
if (val === '' || val === '-' || val === undefined || val === null) return val; |
|
|
|
val = String(val); |
|
|
|
let formatted = val.replace(/[^\d.-]/g, ''); // 移除非数字、点和负号 |
|
|
|
formatted = formatted.replace(/(?!^)-/g, ''); // 负号只能在开头 |
|
|
|
formatted = formatted.replace(/(\..*?)\..*/g, '$1'); // 只能有一个点 |
|
|
|
return formatted; |
|
|
|
} |
|
|
|
|
|
|
|
const submitAdjustment = async () => { |
|
|
|
if (!adjustTime.value) { |
|
|
|
ElMessage.warning('请选择时间') |
|
|
|
return |
|
|
|
} |
|
|
|
if (!adjustCoefficient.value) { |
|
|
|
ElMessage.warning('请输入系数') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 组装矩阵数据 matrix (二维数组,6行6列) |
|
|
|
// 如果单元格为空或者非数字,默认为 0 |
|
|
|
const matrix = adjustData.value.map(row => { |
|
|
|
return matrixMarkets.map(colMarket => { |
|
|
|
const val = parseFloat(row[colMarket.key]) |
|
|
|
return isNaN(val) ? 0 : val |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
// 构造最终提交的数据结构 |
|
|
|
const payload = { |
|
|
|
matrix: matrix, |
|
|
|
weight: parseFloat(adjustCoefficient.value), // 系数 |
|
|
|
createTime: adjustTime.value, |
|
|
|
submitterId: adminData.value.id || 1000063, // 从全局 adminData 获取 |
|
|
|
submitterMarket: adminData.value.marketName || '总部' // 如果为空默认传总部 |
|
|
|
} |
|
|
|
|
|
|
|
console.log('提交的封装数据:', JSON.stringify(payload, null, 2)) |
|
|
|
|
|
|
|
await adjustment(payload) |
|
|
|
ElMessage.success('提交成功') |
|
|
|
adjustVisible.value = false |
|
|
|
fetchData() |
|
|
|
} |
|
|
|
|
|
|
|
onMounted( async() => { |
|
|
|
await handleAdminInfo() |
|
|
|
getMarket() |
|
|
|
@ -309,11 +414,14 @@ onMounted( async() => { |
|
|
|
style="width: 18vw;" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<el-button type="primary" @click="handleSearch">{{ t('common.search') }}</el-button> |
|
|
|
<div class="search-row"> |
|
|
|
<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> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</el-card> |
|
|
|
@ -394,6 +502,62 @@ onMounted( async() => { |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-dialog> |
|
|
|
|
|
|
|
<!-- 业绩调整弹窗 --> |
|
|
|
<el-dialog v-model="adjustVisible" title="市场消耗金币业绩调整" width="80%" top="5vh" align-center class="custom-adjust-dialog"> |
|
|
|
<template #header="{ titleId, titleClass }"> |
|
|
|
<div style="text-align: center; font-weight: bold; font-size: 18px;" :id="titleId" :class="titleClass">市场消耗金币业绩调整</div> |
|
|
|
</template> |
|
|
|
<div style="display: flex; gap: 40px; margin-bottom: 20px; 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" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<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)" /> |
|
|
|
</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-column width="150" align="center" fixed="left"> |
|
|
|
<template #header> |
|
|
|
<div class="diagonal-header"> |
|
|
|
<span class="top-right">调入</span> |
|
|
|
<span class="bottom-left">调出</span> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<template #default="{ row }"> |
|
|
|
<span style="font-weight: bold;">{{ row.inMarket }}</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
|
|
|
|
<el-table-column v-for="col in matrixMarkets" :key="col.key" :label="col.label + '市场团队'" min-width="120" align="center"> |
|
|
|
<template #default="{ row }"> |
|
|
|
<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" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
|
|
|
|
<el-table-column label="合计" min-width="120" align="center" fixed="right"> |
|
|
|
<template #default="{ row }"> |
|
|
|
{{ getRowTotal(row) }} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
|
|
|
|
<template #footer> |
|
|
|
<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> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-dialog> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -451,6 +615,15 @@ onMounted( async() => { |
|
|
|
gap: 10px; |
|
|
|
} |
|
|
|
|
|
|
|
.adjust-btn { |
|
|
|
color: #fff; |
|
|
|
padding: 8px 15px; |
|
|
|
border-radius: 4px; |
|
|
|
cursor: pointer; |
|
|
|
border: none; |
|
|
|
background-color: #7349ad; |
|
|
|
} |
|
|
|
|
|
|
|
.table-card { |
|
|
|
background: #E7F4FD; |
|
|
|
flex: 1; |
|
|
|
@ -484,4 +657,54 @@ onMounted( async() => { |
|
|
|
:deep(.el-table__row:hover > .el-table__cell) { |
|
|
|
background-color: #E5EBFE !important; |
|
|
|
} |
|
|
|
|
|
|
|
.diagonal-header { |
|
|
|
position: relative; |
|
|
|
width: 100%; |
|
|
|
height: 50px; /* Set a fixed height to make diagonal line work well */ |
|
|
|
background: linear-gradient(to bottom right, transparent 49.5%, #dcdfe6 49.5%, #dcdfe6 50.5%, transparent 50.5%); |
|
|
|
} |
|
|
|
.diagonal-header .top-right { |
|
|
|
position: absolute; |
|
|
|
top: 5px; |
|
|
|
right: 15px; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
.diagonal-header .bottom-left { |
|
|
|
position: absolute; |
|
|
|
bottom: 5px; |
|
|
|
left: 15px; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
/* 业绩调整弹窗全局样式 */ |
|
|
|
:deep(.custom-adjust-dialog) { |
|
|
|
background-color: #f3fafe !important; /* 统一淡蓝色背景 */ |
|
|
|
border-radius: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.custom-adjust-dialog .el-dialog__header) { |
|
|
|
padding-bottom: 20px; |
|
|
|
border-bottom: 1px solid #EBEEF5; |
|
|
|
margin-right: 0; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.custom-adjust-dialog .el-dialog__body) { |
|
|
|
padding-top: 20px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 无缝输入框样式(去除边框和背景) */ |
|
|
|
.seamless-input :deep(.el-input__wrapper) { |
|
|
|
box-shadow: none !important; |
|
|
|
background-color: transparent !important; |
|
|
|
padding: 0; |
|
|
|
} |
|
|
|
.seamless-input :deep(.el-input__inner) { |
|
|
|
text-align: center; |
|
|
|
font-size: 14px; |
|
|
|
height: 100%; |
|
|
|
} |
|
|
|
.seamless-input :deep(.el-input__inner:focus) { |
|
|
|
outline: none; |
|
|
|
} |
|
|
|
</style> |