Commit 8fd3df19 by Sweet Zhang

对接接口,封装搜索组件

parent f97f6052
......@@ -290,3 +290,13 @@ export function policyNoCommissionPayRecord(data) {
data: data
})
}
// 应收款导出
export function exportReceivedFortune(data) {
return request({
url: '/csf/api/CommissionExpected/export',
method: 'post',
data: data,
responseType: 'blob'
})
}
<!-- components/SearchForm.vue -->
<template>
<el-form :model="formModel" label-width="100px" size="default" label-position="top">
<el-row :gutter="20">
<template v-for="item in config" :key="item.prop">
<!-- 所有字段都用相同的响应式布局 -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-if="item.type === 'input'">
<el-form-item :label="item.label" :prop="item.prop">
<el-input
v-model="formModel[item.prop]"
:placeholder="item.placeholder || `请输入${item.label}`"
clearable
/>
</el-form-item>
</el-col>
<el-form :model="formModel" label-width="100px" size="default" label-position="top">
<el-row :gutter="20">
<template v-for="item in config" :key="item.prop">
<!-- Input -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-if="item.type === 'input'">
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
<el-input :model-value="formModel[item.prop]" @input="(val) => handleNumberInput(val, item)"
:placeholder="item.placeholder || `请输入${item.label}`" clearable style="width: 100%" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select' && item.api">
<el-form-item :label="item.label" :prop="item.prop">
<el-select
v-model="formModel[item.prop]"
:placeholder="item.placeholder || `请选择${item.label}`"
clearable
filterable
:filter-method="getFilterMethod(item)"
:loading="item.loading"
@focus="handleFocus(item)"
>
<el-option
v-for="opt in item.options"
:key="opt[item.valueKey || 'value']"
:label="opt[item.labelKey || 'label']"
:value="opt[item.valueKey || 'value']"
/>
</el-select>
</el-form-item>
</el-col>
<!-- Remote Select (带 api 的 select) -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select' && item.api">
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
<el-select ref="selectRefs[item.prop]" v-model="formModel[item.prop]"
:placeholder="item.placeholder || `请选择${item.label}`" clearable filterable
:multiple="item.multiple" :loading="item.loading"
:no-match-text="item.noMatchText || '无匹配数据'" @filter="handleSelectFilter(item)"
@visible-change="handleVisibleChange(item)" @change="(val) => handleChange(item, val)"
style="width: 100%">
<el-option v-for="opt in item._allOptions" :key="opt[item.valueKey || 'value']"
:label="opt[item.labelKey || 'label']" :value="opt[item.valueKey || 'value']" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select'">
<el-form-item :label="item.label" :prop="item.prop">
<el-select
v-model="formModel[item.prop]"
:placeholder="item.placeholder || `请选择${item.label}`"
clearable
:filterable="item.filterable !== false"
:multiple="item.multiple"
>
<el-option
v-for="opt in item.options"
:key="opt[item.valueKey || 'value']"
:label="opt[item.labelKey || 'label']"
:value="opt[item.valueKey || 'value']"
/>
</el-select>
</el-form-item>
</el-col>
<!-- Static Select / Dict Select -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select'">
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
<el-select v-model="formModel[item.prop]" :placeholder="item.placeholder || `请选择${item.label}`"
clearable :filterable="item.filterable !== false" :multiple="item.multiple"
:no-match-text="item.noMatchText || '无匹配数据'">
<el-option v-for="opt in item.options" :key="opt[item.valueKey || 'value']"
:label="opt[item.labelKey || 'label']" :value="opt[item.valueKey || 'value']" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'checkbox-group'">
<el-form-item :label="item.label" :prop="item.prop">
<el-checkbox-group v-model="formModel[item.prop]">
<el-checkbox
v-for="opt in item.options"
:key="opt[item.valueKey || 'value']"
:label="opt[item.valueKey || 'value']"
>
{{ opt[item.labelKey || 'label'] }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<!-- Checkbox Group -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'checkbox-group'">
<el-form-item :label="item.label" :prop="item.prop">
<el-checkbox-group v-model="formModel[item.prop]">
<el-checkbox v-for="opt in item.options" :key="opt[item.valueKey || 'value']"
:label="opt[item.valueKey || 'value']">
{{ opt[item.labelKey || 'label'] }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'date'">
<el-form-item :label="item.label" :prop="item.prop">
<el-date-picker
v-model="formModel[item.prop]"
type="date"
:placeholder="item.placeholder || `请选择${item.label}`"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%"
clearable
/>
</el-form-item>
</el-col>
<!-- Date -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'date'">
<el-form-item :label="item.label" :prop="item.prop">
<el-date-picker v-model="formModel[item.prop]" type="date"
:placeholder="item.placeholder || `请选择${item.label}`" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" style="width: 100%" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'daterange'">
<el-form-item :label="item.label" :prop="item.prop">
<el-date-picker
v-model="formModel[item.prop]"
type="daterange"
:range-separator="item.rangeSeparator || '至'"
:start-placeholder="item.startPlaceholder || '开始日期'"
:end-placeholder="item.endPlaceholder || '结束日期'"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
clearable
/>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
<!-- Date Range -->
<el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'daterange'">
<el-form-item :label="item.label" :prop="item.prop">
<el-date-picker v-model="formModel[item.prop]" type="daterange"
:range-separator="item.rangeSeparator || '至'"
:start-placeholder="item.startPlaceholder || '开始日期'"
:end-placeholder="item.endPlaceholder || '结束日期'" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" clearable />
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
import { reactive, onMounted, onUnmounted } from 'vue'
import request from '@/utils/request'
import { loadDicts, getDictOptions } from '@/utils/useDict'
function debounce(func, wait) {
let timeout
return function (...args) {
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(this, args), wait)
}
}
const selectRefs = reactive({})
// 新增 handleChange
function handleChange(item, value) {
// 如果是多选,value 是数组;单选是值
// 这里不需要处理值,因为 v-model 已绑定
// 清空 filter 输入框
nextTick(() => {
const ref = selectRefs[item.prop]
if (ref && typeof ref.inputValue === 'string') {
ref.inputValue = ''
}
})
}
// ========================
// 工具函数
// ========================
const formModel = reactive({})
const props = defineProps({
config: { type: Array, required: true }
})
const formModel = reactive({})
// 防抖定时器 Map
const debounceMap = new Map()
// 搜索缓存 Map: key = `${prop}:${keyword}`, value = option list
const searchCache = new Map()
// ========================
// 数字输入处理
// ========================
function handleNumberInput(value, item) {
const { inputType = 'text', decimalDigits = 2 } = item
if (inputType === 'text') {
formModel[item.prop] = value
return
}
let result = String(value)
if (inputType === 'integer') {
result = result.replace(/[^\d]/g, '')
} else if (inputType === 'decimal') {
result = result.replace(/[^\d.]/g, '').replace(/^\./, '')
const parts = result.split('.')
if (parts.length > 2) result = parts[0] + '.' + parts.slice(1).join('')
} else if (inputType === 'signed-decimal') {
result = result.replace(/[^\d.-]/g, '')
if (result.startsWith('--')) result = '-' + result.slice(2)
if (result.includes('-') && !result.startsWith('-')) result = result.replace(/-/g, '')
result = result.replace(/^\./, '')
const parts = result.split('.')
if (parts.length > 2) result = parts[0] + '.' + parts.slice(1).join('')
}
if ((inputType === 'decimal' || inputType === 'signed-decimal') && decimalDigits >= 0) {
const dotIndex = result.indexOf('.')
if (dotIndex !== -1) {
const integerPart = result.slice(0, dotIndex)
let decimalPart = result.slice(dotIndex + 1).slice(0, decimalDigits)
result = integerPart + (decimalPart ? '.' + decimalPart : '')
}
}
formModel[item.prop] = result
}
// ========================
// 公共请求方法
// 远程选项请求
// ========================
async function fetchOptions(item, keyword = '') {
const payload = {
......@@ -130,7 +154,6 @@ async function fetchOptions(item, keyword = '') {
pageNo: item.pageNo || 1,
pageSize: item.pageSize || 20
}
if (keyword) {
const keyField = item.keywordField || 'keyword'
payload[keyField] = keyword.trim()
......@@ -154,39 +177,80 @@ async function fetchOptions(item, keyword = '') {
} else if (res?.data?.data && Array.isArray(res.data.data)) {
list = res.data.data
}
return list
}
// ========================
// 创建搜索函数(带防抖)
// 远程搜索逻辑
// ========================
function createSearchFn(item) {
const search = async (keyword) => {
item.loading = true
try {
if (!keyword) {
// 关键词清空 → 恢复默认选项(从缓存)
item.options = item._defaultOptions ? [...item._defaultOptions] : []
} else {
// 有关键词 → 远程搜索
const list = await fetchOptions(item, keyword)
item.options = list
}
} catch (e) {
console.error(`${item.label} 搜索失败`, e)
item.options = []
} finally {
item.loading = false
function handleSelectFilter(item, query) {
// 清除旧防抖
if (debounceMap.has(item.prop)) {
clearTimeout(debounceMap.get(item.prop))
}
const timer = setTimeout(() => {
doRemoteSearch(item, query)
}, item.debounceWait ?? 300)
debounceMap.set(item.prop, timer)
}
async function doRemoteSearch(item, keyword) {
const cacheKey = `${item.prop}:${keyword}`
if (searchCache.has(cacheKey)) {
item._allOptions = searchCache.get(cacheKey)
return
}
item.loading = true
try {
let list = []
if (!keyword.trim()) {
list = item._fullOptions || []
} else {
list = await fetchOptions(item, keyword)
}
item._allOptions = list
searchCache.set(cacheKey, list)
} catch (e) {
console.error(`${item.label} 搜索失败`, e)
item._allOptions = item._fullOptions || []
} finally {
item.loading = false
}
}
// ========================
// 下拉展开时懒加载全量
// ========================
function handleVisibleChange(item, visible) {
if (visible && !item._hasLoadedFull) {
item.loading = true
fetchOptions(item, '')
.then(list => {
item._allOptions = list
item._fullOptions = list
item._hasLoadedFull = true
searchCache.set(`${item.prop}:`, list) // 缓存空关键词
})
.catch(e => {
console.error('加载默认选项失败', e)
item._allOptions = []
})
.finally(() => {
item.loading = false
})
}
return debounce(search, item.debounceWait ?? 300)
}
// ========================
// 初始化
// ========================
onMounted(async () => {
const dictTypes = []
const dictItems = []
for (const item of props.config) {
// 初始化表单值
if (['checkbox-group', 'daterange'].includes(item.type)) {
......@@ -194,49 +258,61 @@ onMounted(async () => {
} else {
formModel[item.prop] = item.defaultValue ?? ''
}
// 处理带 api 的 select(hybrid 模式)
if (item.type === 'select' && item.api) {
item.options = []
item._allOptions = []
item._fullOptions = []
item.loading = true
try {
// 1. 加载默认数据(不传 keyword)
const defaultList = await fetchOptions(item, '')
item._defaultOptions = [...defaultList] // 缓存
item.options = defaultList
const list = await fetchOptions(item, '') // 无关键词,加载默认列表
item._allOptions = list
item._fullOptions = list
item._hasLoadedFull = true
searchCache.set(`${item.prop}:`, list) // 缓存空关键词结果
} catch (e) {
console.error(`加载 ${item.label} 默认选项失败`, e)
item.options = []
console.error(`加载 ${item.label} 默认选项失败`, e)
item._allOptions = []
} finally {
item.loading = false
}
}
// 处理数字输入
if (item.type === 'input' && item.inputType && item.inputType !== 'text') {
handleNumberInput(formModel[item.prop], item)
}
// 收集字典项
if (item.type === 'select' && item.dictType) {
dictTypes.push(item.dictType)
dictItems.push(item)
}
}
// 加载字典
if (dictTypes.length > 0) {
await loadDicts(dictTypes)
for (const item of dictItems) {
item.options = getDictOptions(item.dictType)
}
}
})
// ========================
// 提供给 el-select 的 filter-method
// 清理
// ========================
function getFilterMethod(item) {
if (!item._searchFn) {
item._searchFn = createSearchFn(item)
}
return (keyword) => {
item._searchFn(keyword)
return true // 必须返回 true,否则下拉框会关闭
}
}
// 可选:聚焦时确保有数据(一般不需要,因为 onMounted 已加载)
function handleFocus(item) {
// 如果意外为空,可重试
if (item.type === 'select' && item.api && (!item.options || item.options.length === 0)) {
// 可加 loading 重试逻辑(略)
}
}
onUnmounted(() => {
debounceMap.forEach(timer => clearTimeout(timer))
debounceMap.clear()
searchCache.clear()
})
// ========================
// 暴露方法
// ========================
defineExpose({
async validate() {
// 如果你有 el-form ref,可加校验;否则直接返回
return formModel
},
getSearchParams() {
const params = {}
for (const key in formModel) {
......
......@@ -51,25 +51,4 @@ export function useDictLists(typeLists) {
}
})
})()
}
// /**
// * 获取字典数据
// */
// export function useDict(...args) {
// const res = ref({})
// return (() => {
// args.forEach((dictType, index) => {
// res.value[dictType] = []
// const dicts = useDictStore().getDict(dictType)
// if (dicts) {
// res.value[dictType] = dicts
// } else {
// getDicts(dictType).then(resp => {
// res.value[dictType] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass }))
// useDictStore().setDict(dictType, res.value[dictType])
// })
// }
// })
// return toRefs(res.value)
// })()
// }
}
\ No newline at end of file
......@@ -149,6 +149,7 @@ service.interceptors.response.use(
// 通用下载方法
export function download(url, params, filename, config) {
console.log(url, params, filename, config)
downloadLoadingInstance = ElLoading.service({
text: '正在下载数据,请稍候',
background: 'rgba(0, 0, 0, 0.7)'
......@@ -160,7 +161,7 @@ export function download(url, params, filename, config) {
return tansParams(params)
}
],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
headers: { 'Content-Type': 'application/json' },
responseType: 'blob',
...config
})
......
// utils/safeDownload.js
import { ElMessage } from 'element-plus'
/**
* 安全下载函数:适用于后端返回 Blob 文件流 或 JSON 错误 的场景
* @param {Blob} blobData - 接口返回的响应数据(必须是 responseType: 'blob')
* @param {string} defaultFilename - 默认文件名(如 'data.xlsx')
* @param {string} [mimeType] - MIME 类型(用于兜底创建 Blob)
*/
export async function safeDownload(blobData, defaultFilename, mimeType = 'application/octet-stream') {
if (!(blobData instanceof Blob)) {
ElMessage.error('无效的下载数据')
return
}
try {
// 👇 关键:先 peek 前 100 字节,判断是否是 JSON 错误
const firstChunk = await blobData.slice(0, 100).text()
const trimmed = firstChunk.trim()
// 如果看起来像 JSON(以 { 或 [ 开头),尝试解析
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
const fullText = await blobData.text()
let parsed
try {
parsed = JSON.parse(fullText)
} catch (e) {
// 解析失败,当作正常文件(比如内容就是纯文本)
parsed = null
}
// 如果解析成功,且包含错误字段(根据你后端约定)
if (parsed && (parsed.code !== undefined || parsed.msg || parsed.message)) {
const errorMsg = parsed.msg || parsed.message || '导出失败'
ElMessage.error(errorMsg)
return
}
}
// ✅ 是合法文件流,执行下载(使用你已验证的逻辑)
const url = window.URL.createObjectURL(blobData)
const link = document.createElement('a')
link.href = url
link.download = defaultFilename
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
ElMessage.success('下载成功')
} catch (error) {
console.error('safeDownload error:', error)
ElMessage.error('下载过程中发生错误')
}
}
\ No newline at end of file
// dictUtils.js
import request from '@/utils/request'
// 全局缓存:key 为 dictType,value 为 { label: value } 映射对象
const dictCache = new Map()
// 批量加载字典(支持多个 type)
export async function loadDicts(typeList) {
// 过滤已缓存的类型,避免重复请求
const needLoadTypes = typeList.filter(type => !dictCache.has(type))
if (needLoadTypes.length === 0) return
try {
const res = await request({
url: '/user/api/sysDict/type/list', // 替换为你的实际接口地址
method: 'POST',
data: {
typeList: needLoadTypes
}
})
// 替换 loadDicts 中的缓存部分
if (res.code === 200 && Array.isArray(res.data)) {
for (const dict of res.data) {
const { dictType, dictItemList = [] } = dict
if (!dictType) continue
// 缓存完整列表(并可选排序 + 过滤)
const validItems = dictItemList
.filter(item => item.status === 1) // 只取启用的
.sort((a, b) => a.orderNum - b.orderNum) // 按序号排序
dictCache.set(dictType, validItems) // 👈 缓存完整 item 列表
}
}
} catch (error) {
console.error('字典加载失败:', error)
throw error
}
}
// 可选:提供清除缓存方法(用于权限切换等场景)
export function clearDictCache() {
dictCache.clear()
}
export function getDictOptions(dictType) {
const items = dictCache.get(dictType) || []
// console.log('getDictOptions',items)
return items.map(item => ({
value: item.itemValue,
label: item.itemLabel
// 如果需要,还可以加其他字段:disabled, key 等
}))
}
// 同时更新 getDictLabel
export function getDictLabel(dictType, value) {
const items = dictCache.get(dictType) || []
const item = items.find(i => i.itemValue === value)
return item ? item.itemLabel : value
}
\ No newline at end of file
......@@ -5,33 +5,7 @@
:page-size='pageSize' @size-change='handleSizeChange' @current-change='handleCurrentChange'>
<!-- 搜索区域 -->
<template #searchForm>
<el-form :model="queryParams" label-width="80px">
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="转介人" label-position="top">
<el-select v-model="queryParams.broker" placeholder="请选择转介人" clearable :remote-method="loadBrokers"
:loading="searchLoading" filterable remote reserve-keyword>
<el-option v-for="item in brokerOptions" :key="item.userSaleBizId" :label="item.realName + '(' + item.phone + ')'"
:value="item.realName"/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="出账日期" label-position="top">
<el-date-picker v-model="queryParams.accountDate" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="出账状态" label-position="top">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="item in dictLists" :key="item.itemValue" :label="item.itemLabel"
:value="item.itemValue" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<SearchForm ref="searchFormRef" :config="searchConfig" />
</template>
<!-- 列表区域 -->
<template #table>
......@@ -47,7 +21,7 @@
</el-row>
</div>
<el-table :data="tableData" @selection-change="handleSelectionChange" v-loading="loading" ref="tableRef"
row-key="fortuneAccountBizId" :reserve-selection="true" border="true">
row-key="fortuneAccountBizId" :reserve-selection="true" :border="true">
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column prop="broker" label="转介人" min-width="120" sortable />
<el-table-column prop="team" label="所属团队" min-width="120" sortable />
......@@ -68,6 +42,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="fortuneAccountDate" label="出账日" min-width="150" show-overflow-tooltip />
<el-table-column prop="remark" label="备注" min-width="150" show-overflow-tooltip />
</el-table>
</template>
......@@ -107,10 +82,44 @@ import {
getReferrerFortuneList,
salaryStatistics,
} from '@/api/financial/commission'
import { searchIntermediaries } from '@/api/search'
// import { searchIntermediaries } from '@/api/search'
import { formatCurrency } from '@/utils/number'
import { debounce } from '@/utils/index';
import {ElMessageBox} from 'element-plus'
import { ElMessageBox } from 'element-plus'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
const searchFormRef = ref(null)
const searchParams = ref({})
const searchConfig = ref([
{
type: 'select',
prop: 'brokerBizIdList',
label: '转介人',
api: '/insurance/base/api/userSaleExpand/page',
keywordField: 'realName',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入转介人名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'userSaleBizId',
labelKey: 'realName',
multiple: true,
transform: (res) => {
return res?.data.records || []
}
},
{
type: 'daterange',
prop: 'payoutDate',
label: '出账日(实)',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间'
},
{
type: 'select',
prop: 'status',
label: '出账状态',
dictType: 'csf_fortune_account_status'
}
])
// 添加表格引用
const tableRef = ref()
// 存储所有选中的行数据(用于跨页保持选择)
......@@ -120,16 +129,7 @@ const statisticInfo = ref({
totalAmount: 0,
brokerCount: 0
})
// 查询参数
const queryParams = reactive({
broker: '',
accountDate: [],
accountDateStart: '',
accountDateEnd: '',
sortField: '',
sortOrder: 'desc',
status: '6'
})
// 表格数据
const tableData = ref([])
const loading = ref(false)
......@@ -221,16 +221,14 @@ const clearAllSelection = () => {
// 获取数据列表
const getList = async () => {
const getList = async (searchParams = {}) => {
loading.value = true
try {
if (queryParams.accountDate.length > 0) {
queryParams.accountDateStart = queryParams.accountDate[0]
queryParams.accountDateEnd = queryParams.accountDate[1]
}
const params = {
...queryParams,
accountDate:undefined,
...searchParams,
accountDateStart: searchParams.payoutDate?.[0] || undefined,
accountDateEnd: searchParams.payoutDate?.[1] || undefined,
payoutDate:undefined,
pageNo: currentPage.value,
pageSize: pageSize.value
}
......@@ -241,7 +239,7 @@ const getList = async () => {
pageTotal.value = response.data.page.total
loading.value = false
}
if (response.data.statisticsVO && isSearch.value) {
if (response.data.statisticsVO) {
statisticInfo.value = response.data.statisticsVO
}
// 数据加载完成后,设置当前页的选中状态
......@@ -266,32 +264,19 @@ const getStatusType = status => {
// 查询
const handleQuery = () => {
queryParams.pageNo = 1
Object.values(queryParams).some(value => {
if (Array.isArray(value) && value.length > 0) {
isSearch.value = true
}
if (value !== '' && value != null) {
isSearch.value = true
}
})
const params = searchFormRef.value.getSearchParams()
console.log('父组件发起查询:', params)
clearAllSelection()
getList()
getList(params)
}
// 重置查询
const handleReset = () => {
Object.assign(queryParams, {
broker: '',
accountDateStart: '',
accountDateEnd: '',
sortField: '',
sortOrder: 'desc'
})
isSearch.value = false
// 清空选择
clearAllSelection()
getList()
// 重置搜索表单
searchFormRef.value.resetForm()
searchParams.value = {}
console.log('表单已重置')
getList(searchParams.value)
}
// 选择行变化
......@@ -391,7 +376,7 @@ const fetchCompletePolicyFortune = async row => {
const searchLoading = ref(false)
const brokerOptions = ref([])
// 获取转介人列表
const loadBrokers = async (query='') => {
const loadBrokers = async (query = '') => {
searchLoading.value = true
const params = {
realName: query,
......@@ -399,18 +384,18 @@ const loadBrokers = async (query='') => {
pageSize: 1000,
}
try {
const res = await searchIntermediaries(params)
if (res.code === 200) {
brokerOptions.value = res.data.records || []
searchLoading.value = false
} else {
brokerOptions.value = []
searchLoading.value = false
}
// const res = await searchIntermediaries(params)
// if (res.code === 200) {
// brokerOptions.value = res.data.records || []
// searchLoading.value = false
// } else {
// brokerOptions.value = []
// searchLoading.value = false
// }
} catch (error) { }
}
debounce(loadBrokers, 500,false)
debounce(loadBrokers, 500, false)
const visibleDefaultButtons = ref(['reset', 'query'])
// 按钮配置
const operationBtnList = ref([
......
......@@ -64,20 +64,24 @@
</div>
<!-- 应付款管理列表 -->
<el-table :data="tableData" height="400" border highlight-current-row style="width: 100%" v-loading="loading">
<el-table-column prop="commissionBizType" label="应付款类型" width="120" fixed="left" sortable />
<el-table-column prop="payableNo" label="应付款编号" width="120" />
<el-table-column prop="policyNo" label="保单号" width="120" />
<el-table-column prop="fortuneBizType" label="应付款类型" width="120" fixed="left" sortable>
<template #default="{ row }">
{{ getFortuneBizTypeLabel(row.fortuneBizType) }}
</template>
</el-table-column>
<el-table-column prop="payableNo" label="应付款编号" width="120" sortable/>
<el-table-column prop="policyNo" label="保单号" width="120" sortable/>
<el-table-column prop="status" label="出账状态" width="120" sortable>
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : 'warning'">
{{ row.status === '1' ? '已入账' : '待入账' }}
</el-tag>
{{ getDictLabel('csf_expected_fortune_status', row.status) }}
</template>
</el-table-column>
<el-table-column prop="currency" label="出账币种" width="120" sortable />
<el-table-column prop="fortunePeriod" label="出账期数" width="120" sortable />
<el-table-column prop="fortuneTotalPeriod" label="出账总期数" width="120" sortable />
<el-table-column prop="fortuneType" label="出账项目" width="120" sortable />
<el-table-column prop="fortuneName" label="出账项目" width="120" sortable />
<el-table-column prop="payoutDate" label="出账日(估)" width="120" sortable />
<el-table-column prop="actualPayoutDate" label="出账日(实)" width="120" sortable />
<el-table-column prop="commissionRatio" label="出账比例(估)" width="140" sortable>
<template #default="{ row }">
{{ (row.commissionRatio || 0) + '%' }}
......@@ -85,7 +89,7 @@
</el-table-column>
<el-table-column prop="amount" label="出账金额(估)" width="140" sortable>
<template #default="{ row }">
{{ formatCurrency(row.expectedAmount) }}
{{ formatCurrency(row.amount) }}
</template>
</el-table-column>
<el-table-column prop="paidRatio" label="已出账比例" width="120" sortable>
......@@ -153,6 +157,18 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { formatCurrency } from '@/utils/number'
import { expectedFortuneList, payRecordList } from '@/api/financial/commission'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import {getDictLabel} from '@/utils/useDict';
// 应收单类型
const fortuneBizTypeOptions = [
{ value: 'R', label: '关联保单应付单' },
{ value: 'U', label: '非关联保单应付单' }
]
// 应付单类型通过value转成label
const getFortuneBizTypeLabel = (value) => {
const item = fortuneBizTypeOptions.find(item => item.value === value)
return item?.label || ''
}
const searchFormRef = ref(null)
const searchParams = ref({})
const searchConfig = ref([
......@@ -173,39 +189,22 @@ const searchConfig = ref([
prop: 'statusList',
label: '出账状态',
multiple: true,
options: [
{ value: '1', label: '启用' },
{ value: '0', label: '禁用' }
]
dictType: 'csf_expected_fortune_status'
},
{
type: 'input',
prop: 'fortunePeriod',
label: '出账期数'
label: '出账期数',
inputType: 'decimal',
rules: [
{ pattern: /^\d+$/, message: '只能输入正整数', trigger: 'blur' }
]
},
{
type: 'select',
prop: 'fortuneName',
label: '出账项目',
options: [
{ value: '1', label: '启用' },
{ value: '0', label: '禁用' }
]
},
{
type: 'select',
prop: 'insurerBizId',
label: '对账公司',
api: '/insurance/base/api/insuranceReconciliationCompany/page',
keywordField: 'name',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入对账公司名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'reconciliationCompanyBizId',
labelKey: 'name',
transform: (res) => {
return res?.data.records || []
}
dictType: 'csf_fortune_type'
},
{
type: 'select',
......@@ -219,6 +218,7 @@ const searchConfig = ref([
valueKey: 'insuranceCompanyBizId',
labelKey: 'abbreviation',
transform: (res) => {
console.log(res)
return res?.data.records || []
}
}, {
......@@ -227,7 +227,7 @@ const searchConfig = ref([
label: '产品计划',
api: '/product/api/relProjectProductLaunch/parameter/page',
keywordField: 'productName',
requestParams: { fieldBizId:'field_olk1qZe81qHHKXbw',fieldValueBizId:'field_value_uOfJH5ucA2YwJpbn',pageNo: 1, pageSize: 20 },
requestParams: { fieldBizId: 'field_olk1qZe81qHHKXbw', fieldValueBizId: 'field_value_uOfJH5ucA2YwJpbn', pageNo: 1, pageSize: 20 },
placeholder: '输入产品计划名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'productLaunchBizId',
......@@ -353,14 +353,15 @@ const handleCurrentChange = (val) => {
}
// 加载表格数据
const loadTableData = async (searchParams={}) => {
const loadTableData = async (searchParams = {}) => {
console.log(searchFormRef.value)
loading.value = true
try {
const params = {
...searchParams,
payoutDateStart: searchParams.payoutDate?.[0] || undefined,
payoutDateEnd: searchParams.payoutDate?.[1] || undefined,
payoutDate:undefined,
payoutDate: undefined,
pageNo: currentPage.value,
pageSize: pageSize.value
}
......
<template>
<div>
<CommonPage
:operationBtnList="operationBtnList"
:showSearchForm="true"
:show-pagination="true"
:total="pageTotal"
:current-page="currentPage"
:page-size="pageSize"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<CommonPage :operationBtnList="operationBtnList" :showSearchForm="true" :show-pagination="true"
:total="pageTotal" :current-page="currentPage" :page-size="pageSize" @size-change="handleSizeChange"
@current-change="handleCurrentChange">
<!-- 搜索区域 -->
<template #searchForm>
<el-form :model="searchFormData" label-width="120px">
<el-row :gutter="20">
<!-- 原有搜索项 -->
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="保单号" prop="policyNo" label-position="top">
<el-input v-model="searchFormData.policyNo" placeholder="请输入保单号" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="入账日(估)" prop="incomeDateRange" label-position="top">
<el-date-picker
v-model="searchFormData.incomeDateRange"
type="daterange"
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="入账状态" prop="statusList" label-position="top">
<el-select v-model="searchFormData.statusList" placeholder="请选择入账状态" clearable multiple>
<el-option label="待入账" value="0" />
<el-option label="完成入账" value="1" />
<el-option label="部分入账" value="2" />
<el-option label="已失效" value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="入账期数" prop="commissionPeriod" label-position="top">
<el-input v-model="searchFormData.commissionPeriod" placeholder="请输入入账期数" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="入账项目" prop="commissionName" label-position="top">
<el-input v-model="searchFormData.commissionName" placeholder="请输入入账项目" clearable />
</el-form-item>
</el-col>
<!-- 新增:保险公司远程搜索下拉 -->
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="保险公司" prop="insurerBizId" label-position="top">
<el-select
v-model="searchFormData.insurerBizId"
placeholder="请选择保险公司"
clearable
:remote-method="(keyword) => remoteMethod('insurer', keyword)"
:loading="options.insurer.loading"
filterable
remote
reserve-keyword
>
<el-option
v-for="item in options.insurer.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<!-- 新增:产品计划远程搜索下拉 -->
<!-- <el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="产品计划" prop="productLaunchBizId" label-position="top">
<el-select
v-model="searchFormData.productLaunchBizId"
placeholder="请选择产品计划"
clearable
:remote-method="(keyword) => remoteMethod('product', keyword)"
:loading="options.product.loading"
filterable
remote
reserve-keyword
>
<el-option
v-for="item in options.product.options"
:key="item.bizId"
:label="item.productName"
:value="item.bizId"
/>
</el-select>
</el-form-item>
</el-col> -->
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="应收单类型" prop="commissionBizType" label-position="top">
<el-select v-model="searchFormData.commissionBizType" placeholder="请选择应收单类型" clearable>
<el-option label="关联保单应收单" value="R" />
<el-option label="非关联保单应收单" value="U" />
</el-select>
</el-form-item>
</el-col>
<!-- 新增:出单团队远程搜索下拉 -->
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="对账公司" prop="reconciliationCompanyBizId" label-position="top">
<el-select
v-model="searchFormData.reconciliationCompany"
placeholder="请选择对账公司"
clearable
:remote-method="(keyword) => remoteMethod('reconciliationCompany', keyword)"
:loading="options.reconciliationCompany.loading"
filterable
remote
reserve-keyword
>
<el-option
v-for="item in options.reconciliationCompany.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<!-- 新增:出单团队远程搜索下拉 -->
<!-- <el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="出单团队" prop="outTeamBizId" label-position="top">
<el-select
v-model="searchFormData.outTeamBizId"
placeholder="请选择出单团队"
clearable
:remote-method="(keyword) => remoteMethod('team', keyword)"
:loading="options.team.loading"
filterable
remote
reserve-keyword
>
<el-option
v-for="item in options.team.options"
:key="item.teamBizId"
:label="item.teamName"
:value="item.teamBizId"
/>
</el-select>
</el-form-item>
</el-col> -->
</el-row>
</el-form>
<SearchForm ref="searchFormRef" :config="searchConfig" />
</template>
<!-- 列表区域(原有代码不变) -->
<!-- 列表区域 -->
<template #table>
<div class="statistics-container" v-if="statisticsData.totalPolicyCount > 0">
<el-row :gutter="20">
......@@ -176,16 +29,19 @@
</el-col>
</el-row>
</div>
<el-table :data="tableData" height="400" border highlight-current-row style="width: 100%" v-loading="loading">
<el-table-column prop="commissionBizType" label="应收款类型" width="120" sortable />
<el-table :data="tableData" height="400" border highlight-current-row style="width: 100%"
v-loading="loading">
<el-table-column prop="commissionBizType" label="应收单类型" width="130" sortable>
<template #default="{ row }">
{{ getCommissionBizTypeLabel(row.commissionBizType) }}
</template>
</el-table-column>
<el-table-column prop="receivableNo" label="应收款编号" width="120" />
<el-table-column prop="policyNo" label="保单号" width="120" fixed="left" sortable />
<el-table-column prop="reconciliationCompany" label="对账公司" width="120" sortable />
<el-table-column prop="status" label="入账状态" width="120" sortable>
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : row.status === '0' ? 'warning' : row.status === '2' ? 'info' : 'danger'">
{{ row.status === '1' ? '完成入账' : row.status === '0' ? '待入账' : row.status === '2' ? '部分入账' : '已失效' }}
</el-tag>
{{ getDictLabel('csf_expected_commission_status', row.status) }}
</template>
</el-table-column>
<el-table-column prop="commissionPeriod" label="入账期数" width="120" sortable />
......@@ -236,7 +92,9 @@
<template #default="{ row }">
<el-popover placement="right" :width="200" trigger="click">
<template #reference>
<el-icon><MoreFilled /></el-icon>
<el-icon>
<MoreFilled />
</el-icon>
</template>
<el-menu @select="handleSelect($event, row)" popper-class="custom-menu">
<el-menu-item :index="item.value" v-for="item in dropdownItems" :key="item.value">
......@@ -251,22 +109,11 @@
</CommonPage>
<!-- 原有弹窗(不变) -->
<CommonDialog
dialogTitle="入账记录"
dialogWidth="80%"
:openDialog="entryRecordDialogTableVisible"
:showAction="false"
:showClose="true"
@close="entryRecordDialogTableVisible = false"
>
<CommonDialog dialogTitle="入账记录" dialogWidth="80%" :openDialog="entryRecordDialogTableVisible"
:showAction="false" :showClose="true" @close="entryRecordDialogTableVisible = false">
<el-table :data="entryRecordDialogTableData" border style="width: 100%">
<el-table-column
v-for="item in entryRecordDialogTableColumns"
:key="item.property"
:prop="item.property"
:label="item.label"
:width="item.width"
/>
<el-table-column v-for="item in entryRecordDialogTableColumns" :key="item.property"
:prop="item.property" :label="item.label" :width="item.width" />
<el-table-column fixed="right" label="操作" min-width="120">
<template #default>
<el-button link type="primary" size="small" @click="handleClick">
......@@ -277,32 +124,16 @@
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle="操作记录"
dialogWidth="80%"
:openDialog="actionRecordsDialogVisible"
:showAction="false"
:showClose="true"
@close="actionRecordsDialogVisible = false"
>
<CommonDialog dialogTitle="操作记录" dialogWidth="80%" :openDialog="actionRecordsDialogVisible" :showAction="false"
:showClose="true" @close="actionRecordsDialogVisible = false">
<el-table :data="actionRecordsDialogTableData" border style="width: 100%">
<el-table-column
v-for="item in actionRecordsDialogTableColumns"
:key="item.property"
:prop="item.property"
:label="item.label"
:width="item.width"
/>
<el-table-column v-for="item in actionRecordsDialogTableColumns" :key="item.property"
:prop="item.property" :label="item.label" :width="item.width" />
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle="设置入账状态"
dialogWidth="80%"
:openDialog="setStatusDialogTableVisible"
@close="setStatusDialogTableVisible = false"
@confirm="setStatusDialogTableVisible = false"
>
<CommonDialog dialogTitle="设置入账状态" dialogWidth="80%" :openDialog="setStatusDialogTableVisible"
@close="setStatusDialogTableVisible = false" @confirm="setStatusDialogTableVisible = false">
<el-form :model="form">
<el-form-item label="入账状态" label-width="120">
<el-select v-model="form.status" placeholder="请选择入账状态">
......@@ -332,11 +163,121 @@ import CommonDialog from '@/components/commonDialog'
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { MoreFilled } from '@element-plus/icons-vue'
import { numberWithCommas, debounce } from '@/utils/index'
import { receivedFortuneList, commissionEntryRecord, commissionEntryEditRecords } from '@/api/financial/commission'
import { receivedFortuneList, commissionEntryRecord, commissionEntryEditRecords, exportReceivedFortune } from '@/api/financial/commission'
import { numberWithCommas } from '@/utils/index'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import { getDictLabel } from '@/utils/useDict';
import { safeDownload } from '@/utils/safeDownload'
// 应收单类型
const commissionBizTypeOptions = [
{ value: 'R', label: '关联保单应收单' },
{ value: 'U', label: '非关联保单应收单' }
]
// 查询下拉列表数据
import { searchInsurers,searchReconciliationCompanies } from '@/api/search'
const searchFormRef = ref(null)
const searchParams = ref({})
const searchConfig = ref([
{
type: 'input',
prop: 'policyNo',
label: '保单号'
},
{
type: 'daterange',
prop: 'entryDate',
label: '入账日(估)',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间'
},
{
type: 'select',
prop: 'statusList',
label: '入账状态',
multiple: true,
dictType: 'csf_expected_commission_status'
},
{
type: 'input',
prop: 'commissionPeriod',
label: '入账期数',
inputType: 'decimal',
rules: [
{ pattern: /^\d+$/, message: '只能输入正整数', trigger: 'blur' }
]
},
{
type: 'select',
prop: 'fortuneName',
label: '入账项目',
dictType: 'csf_commission_type'
},
{
type: 'select',
prop: 'reconciliationCompanyBizIdList',
label: '对账公司',
api: '/insurance/base/api/insuranceReconciliationCompany/page',
keywordField: 'name',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入对账公司名称搜索',
debounceWait: 500, // 自定义防抖时间
multiple: true,
valueKey: 'reconciliationCompanyBizId',
labelKey: 'name',
transform: (res) => {
console.log(res)
return res?.data.records || []
}
},
{
type: 'select',
prop: 'insurerCompanyBizIdList',
label: '保险公司',
api: '/insurance/base/api/insuranceCompany/page',
keywordField: 'queryContent',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入保险公司名称搜索',
debounceWait: 500, // 自定义防抖时间
multiple: true,
valueKey: 'insuranceCompanyBizId',
labelKey: 'abbreviation',
transform: (res) => {
return res?.data.records || []
}
}, {
type: 'select',
prop: 'productLaunchBizId',
label: '产品计划',
api: '/product/api/relProjectProductLaunch/parameter/page',
keywordField: 'productName',
requestParams: { fieldBizId: 'field_olk1qZe81qHHKXbw', fieldValueBizId: 'field_value_uOfJH5ucA2YwJpbn', pageNo: 1, pageSize: 20 },
placeholder: '输入产品计划名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'productLaunchBizId',
labelKey: 'productName',
transform: (res) => {
return res?.data.records || []
}
}, {
type: 'select',
prop: 'commissionBizType',
label: '应收单类型',
options: commissionBizTypeOptions,
}, {
type: 'select',
prop: 'teamBizId',
label: '出单团队',
api: '/csf/api/team/page',
keywordField: 'teamName',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入出单团队名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'teamBizId',
labelKey: 'teamName',
transform: (res) => {
return res?.data.records || []
}
},
])
// 分页相关
const currentPage = ref(1)
......@@ -344,6 +285,13 @@ const pageSize = ref(10)
const pageTotal = ref(0)
const loading = ref(false)
// 应收单类型通过value转成label
const getCommissionBizTypeLabel = (value) => {
const item = commissionBizTypeOptions.find(item => item.value === value)
return item?.label || ''
}
// 表格操作菜单
const dropdownItems = [
{ label: '入账记录', value: 'entryRecord' },
......@@ -361,13 +309,6 @@ const entryRecordDialogTableData = ref([])
const entryRecordDialogTableColumns = ref([])
const actionRecordsDialogTableColumns = ref([])
// 新增:下拉框选项状态管理(loading + 选项列表)
const options = reactive({
insurer: { loading: false, options: [] }, // 保险公司
product: { loading: false, options: [] }, // 产品计划
reconciliationCompany: { loading: false, options: [] }, // 对账公司
})
// 设置入账状态表单
const form = reactive({
status: '',
......@@ -376,20 +317,6 @@ const form = reactive({
const selectedRow = ref(null)
// 搜索表单数据(新增下拉框绑定字段)
const searchFormData = reactive({
policyNo: '',
incomeDateRange: [],
statusList: [],
commissionName: '',
commissionPeriod: '',
reconciliationCompany: '',
insurerBizId: '', // 保险公司ID
productLaunchBizId: '', // 产品计划ID
commissionBizType: '',
outTeamBizId: '' // 出单团队ID(替换原outTeam)
})
// 表格数据
const tableData = ref([])
......@@ -402,80 +329,36 @@ const statisticsData = ref({
totalPolicyCount: 0
})
// 新增:防抖处理远程搜索(延迟300ms,避免频繁请求)
const debouncedRemoteMethod = debounce(async (type, keyword) => {
try {
// 根据类型设置加载状态
options[type].loading = true
let res = []
// 不同类型调用不同接口
switch (type) {
case 'insurer':
res = await searchInsurers({ queryContent: keyword, pageSize: 20 }) // 保险公司搜索
options.insurer.options = res.data.records.map(item=>{
return {
label: item.abbreviation,
value: item.insuranceCompanyBizId
}
}) || []
break
case 'reconciliationCompany':
res = await searchReconciliationCompanies({ name: keyword, pageSize: 20 }) // 对账公司搜索
options.reconciliationCompany.options = res.data.records.map(item=>{
return {
label: item.name,
value: item.reconciliationCompanyBizId
}
}) || []
break
default:
break
}
} catch (error) {
console.error(`搜索${type}失败:`, error)
ElMessage.error(`加载${type === 'insurer' ? '保险公司' : type === 'product' ? '产品计划' : '出单团队'}失败`)
} finally {
// 关闭加载状态
options[type].loading = false
}
console.log(options)
}, 300)
// 新增:远程搜索方法(对外暴露)
const remoteMethod = (type, keyword) => {
// if (!keyword) {
// // 关键词为空时清空选项(可选)
// options[type].options = []
// return
// }
debouncedRemoteMethod(type, keyword)
}
// remoteMethod('reconciliationCompany', searchFormData.reconciliationCompany)
// remoteMethod('insurer', searchFormData.insurerBizId)
// 按钮事件处理
const handleAdd = () => ElMessage.info('点击新增按钮')
const handleImport = () => ElMessage.info('点击导入按钮')
const handleExport = () => ElMessage.info('点击导出按钮')
const handleExport = async () => {
// 获取搜索参数
const params = searchFormRef.value?.getSearchParams() || {}
const response = await exportReceivedFortune(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 = () => {
// 重置搜索表单
Object.keys(searchFormData).forEach(key => {
if (Array.isArray(searchFormData[key])) {
searchFormData[key] = []
} else {
searchFormData[key] = ''
}
})
// 重置下拉框选项
Object.keys(options).forEach(key => {
options[key].options = []
})
ElMessage.success('搜索条件已重置')
searchFormRef.value.resetForm()
searchParams.value = {}
console.log('表单已重置')
loadTableData()
}
const handleQuery = () => loadTableData()
const handleQuery = () => {
const params = searchFormRef.value.getSearchParams()
loadTableData(params)
}
// 按钮配置
const operationBtnList = ref([
......@@ -498,14 +381,14 @@ const handleCurrentChange = (val) => {
}
// 加载表格数据
const loadTableData = async () => {
const loadTableData = async (searchParams = {}) => {
loading.value = true
try {
const params = {
...searchFormData,
commissionDateStart: searchFormData.incomeDateRange[0] || '',
commissionDateEnd: searchFormData.incomeDateRange[1] || '',
incomeDateRange: undefined,
...searchParams,
commissionDateStart: searchParams?.entryDate?.[0] || undefined,
commissionDateEnd: searchParams?.entryDate?.[1] || undefined,
entryDate: undefined,
pageNo: currentPage.value,
pageSize: pageSize.value
}
......@@ -646,11 +529,7 @@ const handleConfirmSetStatus = () => {
}
// 初始化加载数据
onMounted(() => {
loadTableData()
})
loadTableData()
</script>
<style scoped lang="scss">
</style>
\ No newline at end of file
<style scoped lang="scss"></style>
\ No newline at end of file
......@@ -52,6 +52,17 @@ export default defineConfig(({ mode, command }) => {
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
},
'/csf': {
target: 'http://139.224.145.34:9002',
changeOrigin: true,
secure: false,
// 如果后端需要 host 头
// configure: (proxy, options) => {
// proxy.on('proxyReq', (proxyReq, req, res) => {
// proxyReq.setHeader('host', '139.224.145.34:9002')
// })
// }
},
// springdoc proxy
'^/v3/api-docs/(.*)': {
target: baseUrl,
......
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