Commit 858059e9 by yuzhenWang

Merge branch 'wyz' into 'test'

优化6

See merge request !150
parents 30e12ba2 6cf093b5
......@@ -44,7 +44,7 @@
/>
<!-- Select (支持 dictType / api / options) -->
<el-select
<!-- <el-select
v-else-if="item.type === 'select'"
v-model="localModel[item.prop]"
:multiple="!!item.multiple"
......@@ -63,6 +63,32 @@
:label="opt.label"
:value="opt.value"
/>
</el-select> -->
<!-- @focus="() => loadRemoteOptions(item, '')" -->
<el-select
v-else-if="item.type === 'select'"
:ref="
el => {
if (el) selectRefs[item.prop] = el
}
"
v-model="localModel[item.prop]"
:multiple="!!item.multiple"
:placeholder="item.placeholder || `请选择${item.label}`"
:clearable="true"
filterable
:remote="!!item.api"
:remote-method="query => handleRemoteSearch(query, item)"
:loading="remoteLoading[item.prop] || false"
:disabled="item.disabled"
@change="val => handleModelChange(val, item)"
>
<el-option
v-for="opt in getSelectOptions(item)"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<!-- Date -->
<el-date-picker
......@@ -293,6 +319,21 @@ import dayjs from 'dayjs'
import * as PDFJS from 'pdfjs-dist'
PDFJS.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.mjs'
// ==================== select ====================
const selectRefs = ref({})
// 新增远程搜索入口(带防抖)
let remoteSearchTimer = null
function handleRemoteSearch(query, item) {
if (!item.api) return
// 🔥 关键修改:如果 query 为空且当前已有选项数据,则不重新加载
if (query === '' && remoteOptions.value[item.prop] && remoteOptions.value[item.prop].length > 0) {
return
}
clearTimeout(remoteSearchTimer)
remoteSearchTimer = setTimeout(async () => {
await loadRemoteOptions(item, query)
}, item.debounceWait || 300)
}
// ==================== 文件预览弹窗 ====================
const filePreviewRef = ref(null)
const previewDialogVisible = ref(false)
......@@ -307,7 +348,6 @@ function previewFile(file, item) {
})
}
// 删除文件(复用原有删除逻辑)
function removeFile(file, item) {
const fileList = localModel.value[item.prop] || []
......@@ -659,6 +699,19 @@ function handleModelChange(value, item) {
}
}
localModel.value = newModel
// 🔥 新增:多选远程 select,选中后清空搜索关键词
if (item.type === 'select' && item.multiple && item.api && selectRefs.value[item.prop]) {
const selectInstance = selectRefs.value[item.prop]
// 获取 el-select 内部的 input 元素
const inputElement = selectInstance.$el?.querySelector('input')
if (inputElement && inputElement.value) {
inputElement.value = ''
// 触发 input 事件,让组件内部同步状态
inputElement.dispatchEvent(new Event('input', { bubbles: true }))
loadRemoteOptions(item, '')
}
}
nextTick(() => {
if (!isEqualShallow(props.modelValue, newModel)) {
emit('update:modelValue', newModel)
......@@ -766,40 +819,80 @@ async function loadRemoteOptionsForInit(item) {
}
// 加载远程 API 选项(focus 时调用,无搜索词)
async function loadRemoteOptions(item) {
const { prop, api, requestParams } = item
// async function loadRemoteOptions(item) {
// const { prop, api, requestParams } = item
// if (!api) return
// // 如果已经有选项且不是强制刷新,可跳过;但为了保证初次加载,remoteOptions[prop] 为空时才加载
// if (remoteOptions.value[prop] && remoteOptions.value[prop].length > 0) return
// try {
// remoteLoading.value[prop] = true
// const payload = {
// ...(typeof requestParams === 'function' ? requestParams() : requestParams || {})
// }
// const res = await request({
// url: api,
// method: 'post',
// data: payload
// })
// const list =
// typeof item.transform === 'function'
// ? item.transform(res)
// : res.data?.records || res.data || []
// const newOptions = list.map(i => ({
// value: String(i[item.valueKey || 'value']),
// label: i[item.labelKey || 'label'],
// raw: i
// }))
// remoteOptions.value[prop] = newOptions
// markDictLoaded(prop)
// // 同步 extra 字段
// const currentVal = localModel.value[prop]
// if (currentVal !== undefined && currentVal !== null && currentVal !== '') {
// syncExtraFieldsForProp(prop, currentVal)
// }
// } catch (err) {
// ElMessage.error(`加载 ${item.label} 失败`)
// remoteOptions.value[prop] = []
// } finally {
// remoteLoading.value[prop] = false
// }
// }
// 修改原有的 loadRemoteOptions,使其支持关键词参数
async function loadRemoteOptions(item, keyword = '') {
const { prop, api, requestParams, keywordField = 'keyword' } = item
if (!api) return
// 如果已经有选项且不是强制刷新,可跳过;但为了保证初次加载,remoteOptions[prop] 为空时才加载
if (remoteOptions.value[prop] && remoteOptions.value[prop].length > 0) return
try {
remoteLoading.value[prop] = true
const payload = {
...(typeof requestParams === 'function' ? requestParams() : requestParams || {})
let params = typeof requestParams === 'function' ? requestParams() : requestParams || {}
if (keyword) {
params = { ...params, [keywordField]: keyword }
} else {
// 可选:重置分页参数为第一页
params = { ...params, pageNo: 1 }
}
const res = await request({
url: api,
method: 'post',
data: payload
})
const res = await request({ url: api, method: 'post', data: params })
const list =
typeof item.transform === 'function'
? item.transform(res)
: res.data?.records || res.data || []
const newOptions = list.map(i => ({
remoteOptions.value[prop] = list.map(i => ({
value: String(i[item.valueKey || 'value']),
label: i[item.labelKey || 'label'],
raw: i
}))
remoteOptions.value[prop] = newOptions
markDictLoaded(prop)
// 同步 extra 字段
const currentVal = localModel.value[prop]
if (currentVal !== undefined && currentVal !== null && currentVal !== '') {
syncExtraFieldsForProp(prop, currentVal)
......@@ -811,7 +904,6 @@ async function loadRemoteOptions(item) {
remoteLoading.value[prop] = false
}
}
// 远程搜索(带关键词,防抖)
let searchTimeout = null
function handleFilterChange(keyword, item) {
......@@ -938,7 +1030,7 @@ onMounted(async () => {
})
)
} else if (item.type === 'select' && item.api) {
apiPromises.push(loadRemoteOptionsForInit(item))
apiPromises.push(loadRemoteOptions(item, ''))
} else if (item.type === 'select' && item.options) {
remoteOptions.value[key] = [...item.options]
markDictLoaded(key)
......@@ -991,26 +1083,31 @@ defineExpose({
localModel.value = { ...resetData }
nextTick(() => formRef.value?.clearValidate())
},
// async refreshRemoteOptions(targetProp) {
// const item = internalConfig.value.find(i => i.prop === targetProp)
// if (!item) {
// console.warn(`[SearchForm] 未找到 prop 为 ${targetProp} 的配置项`)
// return
// }
// if (item.type !== 'select' || !item.api) {
// console.warn(`[SearchForm] 字段 ${targetProp} 不是远程 Select 或没有 API`)
// return
// }
// remoteOptions.value[targetProp] = []
// remoteLoading.value[targetProp] = true
// try {
// await loadRemoteOptions(item)
// } catch (error) {
// console.error(`[SearchForm] ${targetProp} 加载失败`, error)
// throw error
// } finally {
// remoteLoading.value[targetProp] = false
// }
// }
async refreshRemoteOptions(targetProp) {
const item = internalConfig.value.find(i => i.prop === targetProp)
if (!item) {
console.warn(`[SearchForm] 未找到 prop 为 ${targetProp} 的配置项`)
return
}
if (item.type !== 'select' || !item.api) {
console.warn(`[SearchForm] 字段 ${targetProp} 不是远程 Select 或没有 API`)
return
}
remoteOptions.value[targetProp] = []
remoteLoading.value[targetProp] = true
try {
await loadRemoteOptions(item)
} catch (error) {
console.error(`[SearchForm] ${targetProp} 加载失败`, error)
throw error
} finally {
remoteLoading.value[targetProp] = false
}
if (!item || item.type !== 'select' || !item.api) return
await loadRemoteOptions(item, '')
}
})
</script>
......
......@@ -1051,12 +1051,12 @@ const addCheckRecordFormModel = ref({})
const addCheckRecordFormRef = ref(null)
const addCheckRecordFormDialogFlag = ref(false)
const addCheckRecordConfig = [
{
type: 'month',
prop: 'reconciliationYearMonth',
label: '检核年月',
placeholder: '检核年月'
},
// {
// type: 'month',
// prop: 'reconciliationYearMonth',
// label: '检核年月',
// placeholder: '检核年月'
// },
{
type: 'select',
prop: 'fortuneBizType',
......
......@@ -456,11 +456,11 @@ const payableReportListTableColumns = ref([
formatter: row => getDictLabel('csf_expected_fortune_status', row.status) || '-'
},
{
prop: 'currencyName',
prop: 'payoutCurrency',
label: '出账币种',
sortable: true,
width: '100',
formatter: row => row.currencyName || '-'
formatter: row => row.payoutCurrency || '-'
},
{
prop: 'fortunePeriod',
......
......@@ -157,15 +157,14 @@
/>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
<div style="display: flex; gap: 8px;">
<div style="display: flex; gap: 8px">
<!-- 👇 新增:查看按钮 -->
<!-- <el-button
link
type="primary"
size="small"
@click="viewFile(scope.row)"
:disabled="!scope.row.fileUrl"
:disabled="!scope.row.fileUrl"
>
查看
</el-button> -->
......@@ -183,7 +182,6 @@
</el-button>
</template>
</el-popconfirm>
</div>
</template>
</el-table-column>
......@@ -209,14 +207,14 @@
:showClose="true"
@close="handleDialogClose"
>
<FileUploader
:tenant-biz-id="userStore.projectInfo.tenantBizId"
:project-biz-id="userStore.projectInfo.projectBizId"
:object-biz-id="props.policyBizId"
:object-type="'DOCUMENT'"
:project-type="'pc'"
:upload-concurrency="3"
ref="uploaderRef"
<FileUploader
:tenant-biz-id="userStore.projectInfo.tenantBizId"
:project-biz-id="userStore.projectInfo.projectBizId"
:object-biz-id="props.policyBizId"
:object-type="'DOCUMENT'"
:project-type="'pc'"
:upload-concurrency="3"
ref="uploaderRef"
/>
<!-- <FileUpload
v-model="files"
......@@ -239,7 +237,7 @@ import CommonDialog from '@/components/commonDialog'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue'
import { getPolicyfollow, getProductList } from '@/api/sign/underwritingMain'
import { uploadOssFileList,delUploadFile } from '@/api/common'
import { uploadOssFileList, delUploadFile } from '@/api/common'
import { getProcessDetail } from '@/api/sign/fna'
import { premiumReconciliationList } from '@/api/sign/policy'
import { loadDicts, getDictLabel } from '@/utils/useDict'
......@@ -247,7 +245,7 @@ import { getNowTime, formatToDate, formatToDateTime } from '@/utils/date'
import EditableTable from '@/components/csf-common/EditableTable.vue'
import useUserStore from '@/store/modules/user'
import FileUploader from '@/components/LargeFileUploader/index.vue';
import FileUploader from '@/components/LargeFileUploader/index.vue'
const { proxy } = getCurrentInstance()
proxy.useDictLists([
......@@ -289,17 +287,17 @@ const props = defineProps({
default: ''
}
})
const uploaderRef = ref(null);
const uploaderRef = ref(null)
// 【关键】当弹窗关闭时,强制清空上传组件列表
const handleDialogClose = () => {
if (uploaderRef.value) {
// 调用子组件暴露的清空方法
// 你需要在子组件中使用 defineExpose 暴露 clearList 方法
uploaderRef.value.clearList();
fileUploadDialogFlag.value = false
uploaderRef.value.clearList()
fileUploadDialogFlag.value = false
getAttachmentListDetail(props.policyBizId)
}
};
}
const emit = defineEmits(['update:modelValue', 'submit', 'cancel', 'saveRow'])
const introducerTableData = ref([])
......@@ -319,7 +317,7 @@ const introducerConfig = [
internalCode: 'internalNumber',
team: 'deptName',
phone: 'phone',
teamBizId:'deptBizId'
teamBizId: 'deptBizId'
},
transform: res => {
return (res?.data.records || []).map(item => ({
......@@ -541,7 +539,7 @@ const policyInfoFormConfig = ref([
type: 'select',
prop: 'professionalInvestor',
label: '专业投资者',
defaultValue :'No',
defaultValue: 'No',
options: [
{ label: '是', value: 'Yes' },
{ label: '否', value: 'No' }
......@@ -692,7 +690,8 @@ const basicPlanFormConfig = ref([
categoryCodeList: [basicPlanFormData.value.insuranceCategoryCode || ''],
insuranceCompanyBizIdList: [basicPlanFormData.value.insuranceCompanyBizId || ''],
pageNo: 1,
pageSize: 20
pageSize: 20,
productName: 'productName'
}),
placeholder: '请选择产品名称',
debounceWait: 500,
......@@ -1042,7 +1041,9 @@ const activeTab = ref('basic')
const handleBeforeLeave = async (newTabName, oldTabName) => {
// console.log('切换前确认-----------------------', newTabName, oldTabName)
// console.log(tabDirty.value)
if(props.mode === 'viewDetail'){return;}
if (props.mode === 'viewDetail') {
return
}
if (tabDirty.value[oldTabName]) {
try {
await ElMessageBox.confirm(`“${getTabLabel(oldTabName)}” 未提交,确定要切换吗?`, '提示', {
......@@ -1127,7 +1128,7 @@ const handleSubmit = () => {
activeTab: activeTab.value,
...localData.additionalPlans
})
}else if (activeTab.value === 'attachment'){
} else if (activeTab.value === 'attachment') {
tabDirty.value.attachment = false
emit('submit', {
activeTab: activeTab.value
......@@ -1141,17 +1142,16 @@ const handleCancel = () => {
emit('cancel')
}
// 删除附件
const deleteFile = (row)=>{
const deleteFile = row => {
console.log(row)
const fileBizId = row.fileBizId || '';
delUploadFile(fileBizId,userStore.projectInfo.projectBizId).then(res=>{
const fileBizId = row.fileBizId || ''
delUploadFile(fileBizId, userStore.projectInfo.projectBizId).then(res => {
console.log(res)
if(res.code===200){
if (res.code === 200) {
getAttachmentListDetail(props.policyBizId)
}else{
} else {
ElMessage.error('删除文件失败')
}
})
}
......
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