Commit d4982277 by yuzhenWang

Merge branch 'test' into 'feature-20250827wyz-写业务'

Test

See merge request !38
parents 92304c31 10d9b14a
......@@ -403,3 +403,12 @@ export function updatePayRecord(data){
data: data
})
}
// 应付款导出
export function exportPayRecord(data) {
return request({
url: '/csf/api/expectedFortune/export',
method: 'post',
data: data,
responseType: 'blob'
})
}
<template>
<el-form ref="formRef" :model="localModel" :rules="formRules" label-width="auto" v-bind="$attrs" :validate-on-rule-change="false">
<el-form ref="formRef" :model="localModel" :rules="formRules" label-width="auto" v-bind="$attrs"
:validate-on-rule-change="false">
<el-row :gutter="20">
<el-col v-for="item in visibleConfig" :key="item.prop" :span="item.span || 6">
<el-form-item :label="item.label" :prop="item.prop" :class="{ 'search-form-item': isSearch }">
<el-form-item :label="item.label" :prop="item.prop" :class="{ 'search-form-item': isSearch }"
:label-position="item.labelPosition || 'top'">
<!-- Input -->
<el-input v-if="item.type === 'input'" v-model="localModel[item.prop]"
:placeholder="item.placeholder || `请输入${item.label}`" :clearable="true"
......@@ -194,25 +196,99 @@ watch(
}
}
localModel.value = initialModel
// ✅ 在这里同步 modelValue(包括 extra 字段)
localModel.value = syncModelFromProps(props.modelValue, internalConfig.value)
},
{ immediate: true }
)
console.log('🚀 子组件 props.modelValue 初始值:', props.modelValue)
// 监听 modelValue(用于后续外部更新)
watch(
() => props.modelValue,
(newVal) => {
if (!newVal) return
// 只同步存在的字段,避免污染
for (const item of internalConfig.value) {
if (!newVal || !internalConfig.value) return
// ✅ 同样使用 sync 函数
localModel.value = syncModelFromProps(newVal, internalConfig.value)
},
{ deep: true }
)
// 提取同步逻辑
function syncModelFromProps(newModelValue, newConfig) {
if (!newModelValue || !newConfig) return {}
const synced = {}
// 1. 同步主字段
for (const item of newConfig) {
const key = item.prop
if (newVal.hasOwnProperty(key)) {
localModel.value[key] = newVal[key]
if (newModelValue.hasOwnProperty(key)) {
synced[key] = newModelValue[key]
} else if (item.multiple || ['checkbox-group', 'daterange'].includes(item.type)) {
synced[key] = item.defaultValue ?? []
} else {
synced[key] = item.defaultValue ?? ''
}
}
// 2. 同步 extra 字段(从 newModelValue 中的 sourceField 重新计算)
for (const item of newConfig) {
const sourceField = item.prop
const extraMap = item.onChangeExtraFields
if (!extraMap || typeof extraMap !== 'object') continue
const sourceObj = newModelValue[sourceField]
if (sourceObj && typeof sourceObj === 'object') {
// newModelValue 中有 sourceField → 重新计算 extra
for (const [targetKey, subPath] of Object.entries(extraMap)) {
const val = getNestedValue(sourceObj, subPath)
if (val !== undefined) {
synced[targetKey] = val
}
}
}
}
)
// 3. 保留 localModel 中的 extra 字段(仅当 newModelValue 中没有对应的 sourceField 时)
for (const item of newConfig) {
const sourceField = item.prop
const extraMap = item.onChangeExtraFields
if (!extraMap || typeof extraMap !== 'object') continue
// 如果 newModelValue 中没有 sourceField,说明没有重新计算
if (newModelValue[sourceField] === undefined) {
// 那么保留 localModel 中对应的 extra 字段
for (const [targetKey, subPath] of Object.entries(extraMap)) {
if (localModel.value.hasOwnProperty(targetKey)) {
synced[targetKey] = localModel.value[targetKey]
}
}
}
}
// 4. 保留其他不在 config 中的字段
for (const key in newModelValue) {
if (
!synced.hasOwnProperty(key) &&
!newConfig.some(item => item.prop === key)
) {
const isExtraTarget = newConfig.some(item =>
item.onChangeExtraFields && item.onChangeExtraFields.hasOwnProperty(key)
)
if (!isExtraTarget) {
synced[key] = newModelValue[key]
}
}
}
return synced
}
function getNestedValue(obj, path) {
return path.split('.').reduce((current, key) => current?.[key], obj)
}
// 当字典加载完成时,触发同步
function markDictLoaded(prop) {
dictLoaded.value.add(prop)
......@@ -222,27 +298,44 @@ function markDictLoaded(prop) {
}
}
// 2. 用户操作导致 localModel 变化时,emit(防抖可选)
function handleModelChange(value, item) {
console.log('✅ handleModelChange 被调用', { prop: item?.prop, value })
// 同步额外字段
console.group('🔄 handleModelChange')
console.log('输入 value:', value)
console.log('item:', item)
console.log('当前 localModel:', localModel.value)
const newModel = { ...localModel.value, [item.prop]: value }
if (item?.type === 'select' && item.onChangeExtraFields) {
const options = getSelectOptions(item)
const opt = options.find(o => o.value === value) // ✅ 现在 value 和 o.value 类型一致
if (opt) {
console.log('可用 options:', options)
const opt = options.find(o => o.value === value)
console.log('匹配的 opt:', opt)
if (opt?.raw) {
for (const [targetProp, sourceKey] of Object.entries(item.onChangeExtraFields)) {
localModel.value[targetProp] = opt.raw[sourceKey]
console.log(`✅ 同步 ${targetProp} =`, opt.raw[sourceKey])
const extraValue = opt.raw[sourceKey]
newModel[targetProp] = extraValue
console.log(`✅ 设置 ${targetProp} =`, extraValue)
}
}
}
// emit 更新
console.log('🆕 newModel:', newModel)
console.log('📦 props.modelValue:', props.modelValue)
console.log('isEqualShallow?', isEqualShallow(props.modelValue, newModel))
localModel.value = newModel
nextTick(() => {
if (!isEqualShallow(props.modelValue, localModel.value)) {
console.log('准备 emit modelValue:', localModel.value)
emit('update:modelValue', { ...localModel.value })
if (!isEqualShallow(props.modelValue, newModel)) {
console.log('📤 emit update:modelValue:', newModel)
emit('update:modelValue', newModel)
} else {
console.log('🚫 跳过 emit:认为相等')
}
})
console.groupEnd()
}
// 辅助函数:浅比较两个对象
function isEqualShallow(a, b) {
......
......@@ -73,7 +73,7 @@
<el-table-column prop="policyNo" label="保单号" width="120" sortable />
<el-table-column prop="insuranceCompany" label="保险公司" width="120" sortable />
<el-table-column prop="commissionPaidAmount" label="累积已入账金额" width="120" sortable />
<el-table-column prop="commissionPaidRatio" label="累积已入账比例" width="120" sortable />
<el-table-column prop="commissionPaidRatio" label="累积已入账比例" width="120" sortable :formatter="(row) => `${row.commissionPaidRatio }%`" />
<el-table-column prop="fortuneName" label="出账项目" width="130" sortable />
<el-table-column prop="fortunePeriod" label="出账期数" width="130" sortable />
<el-table-column prop="fortuneTotalPeriod" label="总期数" width="120" sortable />
......@@ -83,14 +83,15 @@
<el-table-column prop="currency" label="出账币种" width="130" sortable />
<el-table-column prop="fortunePaidAmount" label="已出账金额" width="120" sortable />
<el-table-column prop="fortuneUnpaidAmount" label="剩余出账金额" width="120" sortable />
<el-table-column prop="currentPaymentAmount" label="本期出账金额" width="120" sortable />
<el-table-column prop="fortuneUnpaidRatio" label="剩余出账比例" width="120" sortable />
<el-table-column prop="currentPaymentAmount" label="本期出账金额" width="120" sortable/>
<el-table-column prop="fortuneUnpaidRatio" label="剩余出账比例" width="120" sortable :formatter="(row) => `${row.fortuneUnpaidRatio }%`" />
<el-table-column prop="status" label="出账状态" width="120" sortable>
<template #default="{ row }">
{{ getDictLabel('csf_fortune_status', row.status) }}
</template>
</el-table-column>
<el-table-column prop="premium" label="期交保费" width="120" sortable />
<el-table-column prop="policyCurrency" label="保单币种" width="120" sortable />
<el-table-column prop="payoutDate" label="出账日(实)" width="120" sortable />
<el-table-column prop="remark" label="备注" width="120" sortable />
<el-table-column fixed="right" label="操作" min-width="120">
......@@ -143,6 +144,7 @@ import CommonDialog from '@/components/commonDialog'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import { ElMessage } from 'element-plus'
import { formatCurrency } from '@/utils/number'
import { Select } from '@element-plus/icons-vue'
// 接口
import { getPolicyFortuneList, addCheckRecordaddBatch, updatePayoutAmount, downloadPolicyFortuneAccount } from '@/api/financial/commission'
import useUserStore from '@/store/modules/user'
......@@ -162,7 +164,8 @@ const searchConfig = ref([
type: 'input',
prop: 'policyNo',
label: '保单号'
}, {
},
{
type: 'select',
prop: 'statusList',
label: '出账状态',
......@@ -209,13 +212,13 @@ const searchConfig = ref([
startPlaceholder: '开始时间',
endPlaceholder: '结束时间'
},
// {
// type: 'select',
// prop: 'status',
// label: '入账状态',
// multiple: true,
// dictType: 'csf_expected_commission_status'
// },
{
type: 'select',
prop: 'commissionStatusList',
label: '入账状态',
multiple: true,
dictType: 'csf_expected_commission_status'
},
])
// 表格操作菜单
const dropdownItems = [
......@@ -340,7 +343,13 @@ const setPayoutAmountConfig = [
prop: 'status',
label: '出账状态',
dictType: 'csf_expected_fortune_status'
}
},
// {
// type: 'input',
// prop: 'exchangeRate',
// label: '结算汇率',
// defaultValue: 1
// }
]
......@@ -370,7 +379,7 @@ const handleQuery = async () => {
const params = searchFormRef.value.getFormData()
loadTableData(params)
}
const visibleDefaultButtons = ref(['add', 'import', 'export', 'reset', 'query'])
const visibleDefaultButtons = ref(['add', 'export', 'reset', 'query'])
// 按钮配置
const operationBtnList = ref([
{
......@@ -378,11 +387,6 @@ const operationBtnList = ref([
direction: 'left',
label: '新增出账',
click: handleAdd
}, {
key: 'import',
direction: 'left',
label: '导入出账',
click: handleImport
},
{
key: 'export',
......@@ -481,6 +485,7 @@ const updatePayoutAmountapi = async (data) => {
if (res.code === 200) {
ElMessage.success('设置本期出账金额成功')
loadTableData()
setPayoutAmountDialogFlag.value = false
} else {
ElMessage.error(res.msg || '设置本期出账金额失败')
}
......
<template>
<div>
<CommonPage :operationBtnList="operationBtnList" :showSearchForm="true" :show-pagination="true" :total="pageTotal"
<CommonPage :operationBtnList="operationBtnList" :visibleDefaultButtons="visibleDefaultButtons" :showSearchForm="true" :show-pagination="true" :total="pageTotal"
:current-page="currentPage" :page-size="pageSize" @size-change="handleSizeChange"
@current-change="handleCurrentChange">
<!-- 搜索区域 -->
......@@ -15,8 +15,8 @@
<el-col :xs="24" :sm="12" :md="4" :lg="4">
<el-card shadow="hover" class="statistics-card">
<div class="card-content">
<div class="card-label">应出总金额</div>
<div class="card-value">{{ formatCurrency(statisticsData.totalAmount) }}</div>
<div class="card-label">应出总金额</div>
<div class="card-value">{{ formatCurrency(statisticsData.totalExpectedAmount) }}</div>
</div>
</el-card>
</el-col>
......@@ -32,7 +32,7 @@
<el-card shadow="hover" class="statistics-card">
<div class="card-content">
<div class="card-label">待出账金额</div>
<div class="card-value">{{ formatCurrency(statisticsData.pendingPaidAmount) }}</div>
<div class="card-value">{{ formatCurrency(statisticsData.totalUnpaidAmount) }}</div>
</div>
</el-card>
</el-col>
......@@ -56,7 +56,7 @@
<el-card shadow="hover" class="statistics-card">
<div class="card-content">
<div class="card-label">总保费</div>
<div class="card-value">{{ statisticsData.totalPolicyCount }}</div>
<div class="card-value">{{ formatCurrency(statisticsData.totalPremiumAmount) }}</div>
</div>
</el-card>
</el-col>
......@@ -113,9 +113,13 @@
{{ formatCurrency(row.unpaidAmount) }}
</template>
</el-table-column>
<el-table-column prop="broker_ratio" label="持有比例" width="120" sortable />
<el-table-column prop="insurerBizId" label="保险公司" width="120" sortable />
<el-table-column prop="productLaunchBizId" label="产品计划" width="120" sortable />
<el-table-column prop="brokerRatio" label="持有比例" width="120" sortable >
<template #default="{ row }">
{{ (row.brokerRatio || 0) + '%' }}
</template>
</el-table-column>
<el-table-column prop="insuranceCompany" label="保险公司" width="120" sortable />
<el-table-column prop="productName" label="产品计划" width="120" sortable />
<el-table-column prop="premium" label="期交保费" width="120" sortable>
<template #default="{ row }">
{{ formatCurrency(row.premium) }}
......@@ -147,13 +151,13 @@
:showClose="true" @close="payRecordDialogTableVisible = false">
<el-table :data="payRecordDialogTableData" border style="width: 100%">
<el-table-column v-for="item in payRecordDialogTableColumns" :key="item.property" :property="item.property"
:label="item.label" :width="item.width" />
:label="item.label" :width="item.width" :formatter="item.formatter" />
</el-table>
</CommonDialog>
<!-- 新增出账记录 -->
<CommonDialog :dialogTitle="editStatus === 'add' ? '新增出账记录' : '修改出账记录'" dialogWidth="80%"
:openDialog="addPayRecordDialogVisible" :showAction="true" :showClose="true"
@close="addPayRecordDialogVisible = false; editStatus = 'add'" @confirm="handleConfirmAddPayRecord">
@close="resetAddPayRecordForm" @confirm="handleConfirmAddPayRecord">
<SearchForm ref="addPayRecordFormRef" :config="addPayRecordFormConfig" v-model="addPayRecordFormModel" />
</CommonDialog>
<!-- 设置出账状态 -->
......@@ -171,11 +175,12 @@ import CommonPage from '@/components/commonPage'
import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { formatCurrency } from '@/utils/number'
import { expectedFortuneList, payRecordList, addPayRecord, updatePayRecord } from '@/api/financial/commission'
import { expectedFortuneList, payRecordList, addPayRecord, updatePayRecord, exportPayRecord } from '@/api/financial/commission'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import CommonDialog from '@/components/commonDialog'
import { loadDicts, getDictLabel } from '@/utils/useDict'
import useUserStore from '@/store/modules/user'
import { safeDownload } from '@/utils/safeDownload'
// 设置出账状态
const setPayRecordStatusDialogVisible = ref(false)
const selectedRow = ref(null)
......@@ -192,7 +197,9 @@ const setPayRecordStatusFormConfig = ref([
label: '修改理由',
},
])
const visibleDefaultButtons = ref([
'add', 'export', 'reset', 'query'
])
const userStore = useUserStore()
// 应收单类型
const fortuneBizTypeOptions = [
......@@ -297,6 +304,8 @@ const searchConfig = ref([
}
},
])
const payRecordDialogTableVisible = ref(false)
// 新增出账记录
const addPayRecordFormModel = ref({
......@@ -419,6 +428,12 @@ const handleConfirmAddPayRecord = async () => {
}
}
// 弹窗表单重置
const resetAddPayRecordForm = () => {
addPayRecordFormRef.value.resetForm()
editStatus.value = 'add'
addPayRecordDialogVisible.value = false
}
const editStatus = ref('add')
......@@ -433,13 +448,13 @@ const handleSelect = async (e, row) => {
payRecordDialogTableColumns.value = [
{ property: 'broker', label: '转介人', width: '100', },
{ property: 'fortuneName', label: '出账项目', width: '150' },
{ property: 'amount', label: '出账金额', width: '150' },
{ property: 'currentPaymentAmount', label: '出账金额', width: '150' },
{ property: 'currency', label: '出账币种', width: '150' },
{ property: 'amount', label: '出账比例', width: '150' },
{ property: 'currentCommissionRatio', label: '待出账比例', width: '150' },
{ property: 'currentPaymentRatio', label: '出账比例', width: '150',formatter: (row) => `${row.currentPaymentRatio }%` },
{ property: 'fortuneUnpaidRatio', label: '待出账比例', width: '150',formatter: (row) => `${row.fortuneUnpaidRatio }%` },
{ property: 'fortunePeriod', label: '佣金期数', width: '150' },
{ property: 'fortuneTotalPeriod', label: '总期数', width: '150' },
{ property: 'updaterId', label: '操作人', width: '150' },
{ property: 'reconciliationOperator', label: '操作人', width: '150' },
{ property: 'updateTime', label: '操作时间', width: '150' }
]
} else if (e === 'setStatus') {
......@@ -501,8 +516,17 @@ const handleImport = () => {
ElMessage.info('点击导入按钮')
}
const handleExport = () => {
ElMessage.info('点击导出按钮')
const handleExport = async () => {
// 获取搜索参数
const params = searchFormRef.value?.getFormData() || {}
const response = await exportPayRecord(params)
// 文件名设置为应收款导出_yyyy-MM-dd hh:mm:ss.xlsx,不需要-,用字符串
const fileName = `应付款导出_${new Date().toLocaleString().replace(/\//g, '').replace(/:/g, '').replace(/\s/g, '')}.xlsx`
await safeDownload(
response,
fileName,
'application/vnd.ms-excel;charset=utf-8'
)
}
const handleReset = () => {
......@@ -525,11 +549,11 @@ const operationBtnList = ref([
direction: 'left',
click: handleAdd
},
{
key: 'import',
direction: 'left',
click: handleImport
},
// {
// key: 'import',
// direction: 'left',
// click: handleImport
// },
{
key: 'export',
direction: 'right',
......
......@@ -69,9 +69,9 @@
{{ (row.pendingRatio || 0) + '%' }}
</template>
</el-table-column>
<el-table-column prop="pendingPaidAmount" label="待入账金额(估)" width="160" sortable>
<el-table-column prop="pendingAmount" label="待入账金额(估)" width="160" sortable>
<template #default="{ row }">
{{ numberWithCommas(row.pendingPaidAmount) }}
{{ numberWithCommas(row.pendingAmount) }}
</template>
</el-table-column>
<el-table-column prop="currency" label="入账币种" width="100" />
......@@ -618,7 +618,7 @@ const handleSelect = async (e, row) => {
{ property: 'amount', label: '入账金额', width: '150' },
{ property: 'currentCommissionRatio', label: '入账比例', width: '150' },
{ property: 'commissionDate', label: '入账日', width: '150' },
{ property: 'status', label: '入账状态', width: '150' }
{ property: 'commissionStatus', label: '入账状态', width: '150' }
]
// 加载真实数据
const records = await loadEntryRecordData(row.commissionExpectedBizId)
......
......@@ -5,7 +5,7 @@
<el-col :sm="12" :lg="12" :xs="24">
<div class="headerLeft">
<div class="top">欢迎!</div>
<div class="bottom">王力群,wangliqun@bytedance.com</div>
<div class="bottom">王力群</div>
</div>
</el-col>
<el-col :sm="12" :lg="12" :xs="24" class="right">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment