Commit e451de86 by Sweet Zhang

对接新单跟进

parent defd162d
<template>
<div class="editable-table">
<el-form
ref="formRef"
:model="{}"
label-width="120px"
size="small"
>
<el-table
:data="internalData"
border
style="width: 100%"
:row-style="{ height: '48px' }"
:cell-style="{ padding: '6px 0' }"
>
<el-table-column
v-for="field in rowConfig"
:key="field.prop"
:label="field.label"
:width="field.width"
:min-width="field.minWidth"
>
<template #default="{ row }">
<component
:is="getFieldComponent(field.type)"
v-bind="getFieldProps(field, row.data)"
@update:model-value="val => handleFieldChange(val, field, row)"
@option-change="option => handleOptionChange(option, field, row)"
@focus="() => loadRemoteOptions(field)"
@filter-change="keyword => handleFilterChange(keyword, field)"
:disabled="!!field.disabled || disabled"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="100" fixed="right">
<template #default="{ $index }">
<el-button
type="danger"
size="small"
link
@click="removeRow($index)"
:disabled="disabled"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-button
type="primary"
size="small"
style="margin-top: 12px"
@click="addRow"
:disabled="disabled"
>
添加一行
</el-button>
<!-- <el-button
type="success"
size="small"
style="margin-left: 12px"
@click="batchSave"
:disabled="disabled"
>
批量保存
</el-button> -->
</el-form>
</div>
</template>
<script setup>
import { ref, watch, nextTick } from 'vue'
import SelectField from '@/components/csf-form/fields/SelectField.vue'
import InputField from '@/components/csf-form/fields/InputField.vue'
import UploadField from '@/components/csf-form/fields/UploadField.vue'
import { deepEqual } from '@/utils/csf-deepEqual'
import request from '@/utils/request'
const props = defineProps({
modelValue: {
type: Array,
default: () => []
},
rowConfig: {
type: Array,
required: true
},
disabled: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue', 'batch-save'])
const formRef = ref()
const internalData = ref([])
// 远程加载状态 & 缓存
const remoteLoading = ref({})
const optionsCache = ref(new Map()) // prop -> options
// 初始化 internalData
watch(
() => props.modelValue,
(newVal) => {
if (!Array.isArray(newVal)) {
console.warn('[EditableTable] modelValue is not an array, reset to empty array')
internalData.value = []
return
}
const currentPlain = internalData.value.map(row => {
const { id, ...rest } = row.data
return { ...rest, id: row.id }
})
if (!deepEqual(newVal, currentPlain)) {
internalData.value = newVal.map((item, index) => ({
id: item.id || Symbol(`row-${index}`),
data: { ...(item || {}) }
}))
}
},
{ immediate: true }
)
// 同步 internalData → modelValue
let isEmitting = false
watch(
internalData,
(newVal) => {
if (isEmitting) return
const plainData = newVal.map(row => {
const { id, ...rest } = row.data
return { ...rest, id: row.id }
})
if (!deepEqual(plainData, props.modelValue)) {
isEmitting = true
emit('update:modelValue', plainData)
nextTick(() => {
isEmitting = false
})
}
},
{ deep: true }
)
// 字段组件映射
function getFieldComponent(type) {
switch (type) {
case 'select':
return SelectField
case 'input':
return InputField
case 'upload':
return UploadField
default:
return InputField
}
}
// 获取字段属性
function getFieldProps(field, rowData) {
const base = {
modelValue: rowData[field.prop],
'onUpdate:modelValue': (val) => {
rowData[field.prop] = val
}
}
switch (field.type) {
case 'select':
return {
...base,
multiple: !!field.multiple,
clearable: true,
filterable: true,
loading: remoteLoading.value[field.prop] || false,
options: optionsCache.value.get(field.prop) || field.options || [],
placeholder: field.placeholder || `请选择${field.label}`
}
case 'input':
return {
...base,
placeholder: field.placeholder || `请输入${field.label}`
}
case 'upload':
return {
...base,
uploadUrl: field.uploadUrl,
maxCount: field.maxCount || 1,
showFileList: field.showFileList !== false
}
default:
return base
}
}
// 处理字段变更(基础)
function handleFieldChange(val, field, row) {
row.data[field.prop] = val
}
// 处理 select 选中(带完整 option)
function handleOptionChange(option, field, row) {
if (!option || !field.onChangeExtraFields) return
// 兼容对象和数组格式
let extras = []
if (Array.isArray(field.onChangeExtraFields)) {
extras = field.onChangeExtraFields
} else if (typeof field.onChangeExtraFields === 'object') {
extras = Object.entries(field.onChangeExtraFields).map(([targetProp, sourceKey]) => ({
targetProp,
sourceKey
}))
}
for (const { targetProp, sourceKey } of extras) {
if (!targetProp || sourceKey == null) continue
const getValue = (obj, path) => path.split('.').reduce((o, k) => o?.[k], obj)
const extraValue = getValue(option, sourceKey)
row.data[targetProp] = extraValue
}
}
// 加载远程选项(初始加载)
async function loadRemoteOptions(field) {
if (!field.api || optionsCache.value.has(field.prop)) return
const key = field.prop
remoteLoading.value[key] = true
try {
const params = {
...(field.requestParams || {}),
[field.keywordField || 'keyword']: ''
}
const res = await request(field.api, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify(params)
}).then(r => r)
const list = field.transform ? field.transform(res) : (res?.data?.records || [])
optionsCache.value.set(key, list)
} catch (err) {
console.error(`Failed to load options for ${field.prop}:`, err)
} finally {
remoteLoading.value[key] = false
}
}
// 搜索过滤(暂不实现,可扩展)
function handleFilterChange(keyword, field) {
// 可在此实现远程搜索
}
// 行操作
function addRow() {
internalData.value.push({
data: {}
})
}
function removeRow(index) {
internalData.value.splice(index, 1)
}
function batchSave() {
emit('batch-save', internalData.value.map(row => ({ ...row.data, id: row.id })))
}
</script>
<style scoped>
.editable-table :deep(.el-input__wrapper),
.editable-table :deep(.el-select__wrapper) {
box-shadow: none !important;
}
</style>
\ No newline at end of file
<template>
<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"
:class="{ 'search-form-item': isSearch }"
>
<el-form-item
:label="item.label"
:prop="item.prop"
:label-position="item.labelPosition || 'top'"
>
<component
:is="getFieldComponent(item.type)"
v-bind="getFieldProps(item)"
@update:model-value="val => handleModelChange(val, item)"
@focus="() => loadRemoteOptions(item)"
@filter-change="keyword => handleFilterChange(keyword, item)"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup>
import { onMounted } from 'vue'
import { useSearchFormLogic } from '@/composables/useSearchFormLogic'
// 字段组件映射
import InputField from './fields/InputField.vue'
import SelectField from './fields/SelectField.vue'
import DateField from './fields/DateField.vue'
import MonthField from './fields/MonthField.vue'
import DateRangeField from './fields/DateRangeField.vue'
import CheckboxGroupField from './fields/CheckboxGroupField.vue'
import TextareaField from './fields/TextareaField.vue'
import UploadField from './fields/UploadField.vue'
const fieldMap = {
input: InputField,
select: SelectField,
date: DateField,
month: MonthField,
daterange: DateRangeField,
'checkbox-group': CheckboxGroupField,
textarea: TextareaField,
upload: UploadField
}
const props = defineProps({
modelValue: { type: Object, default: () => ({}) },
config: { type: Array, default: () => [] },
isSearch: { type: Boolean, default: false }
})
const emit = defineEmits([
'update:modelValue',
'selectChange',
'uploadSuccess'
])
const {
formRef,
localModel,
visibleConfig,
formRules,
handleModelChange,
getSelectOptions,
getDisabledDateFn,
loadRemoteOptions,
handleFilterChange,
remoteLoading,
init,
getFormData,
validate,
resetForm
} = useSearchFormLogic(props, emit)
// 暴露方法给父组件
defineExpose({ getFormData, validate, resetForm })
// 初始化
onMounted(() => {
init()
})
// 获取字段组件
function getFieldComponent(type) {
return fieldMap[type] || 'span'
}
// 构建字段 props
function getFieldProps(item) {
const base = {
modelValue: localModel.value[item.prop],
disabled: item.disabled,
placeholder: item.placeholder
}
switch (item.type) {
case 'input':
return {
...base,
inputType: item.inputType,
decimalDigits: item.decimalDigits
}
case 'select':
return {
...base,
multiple: !!item.multiple,
clearable: true,
filterable: true,
loading: remoteLoading.value[item.prop] || false,
options: getSelectOptions(item),
placeholder: item.placeholder || `请选择${item.label}`
}
case 'date':
return {
...base,
valueFormat: item.valueFormat || 'YYYY-MM-DD',
disabledDate: getDisabledDateFn(item),
placeholder: `选择${item.label}`
}
case 'month':
return {
...base,
valueFormat: item.valueFormat || 'YYYY-MM',
disabledDate: getDisabledDateFn(item),
placeholder: `选择${item.label}`
}
case 'daterange':
return {
...base,
valueFormat: item.valueFormat || 'YYYY-MM-DD',
disabledDate: getDisabledDateFn(item)
}
case 'checkbox-group':
return {
...base,
options: getSelectOptions(item)
}
case 'textarea':
return {
...base,
clearable: true
}
case 'upload':
return {
...base,
action: item.action,
headers: item.headers,
multiple: !!item.multiple,
limit: item.limit || (item.multiple ? 999 : 1),
accept: item.accept,
listType: item.listType || 'text',
showFileList: item.showFileList,
uploadType: item.uploadType,
link: item.link,
maxSize: item.maxSize
}
default:
return base
}
}
</script>
<style scoped>
.search-form-item {
margin-bottom: 20px;
}
</style>
\ No newline at end of file
<template>
<el-checkbox-group :model-value="modelValue" :disabled="disabled" @update:model-value="handleChange">
<el-checkbox v-for="opt in options" :key="opt.value" :label="opt.value">
{{ opt.label }}
</el-checkbox>
</el-checkbox-group>
</template>
<script setup>
const props = defineProps({
modelValue: String,
disabled: Boolean,
options: { type: Array, default: () => [] }
})
const emit = defineEmits(['update:modelValue'])
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<!-- src/components/search-form/fields/DateField.vue -->
<template>
<el-date-picker
:model-value="modelValue"
type="date"
:placeholder="placeholder"
:disabled="disabled"
:value-format="valueFormat"
:disabled-date="disabledDate"
style="width: 100%"
@update:model-value="handleChange"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String, // 注意:不能是 required,因为可能为 null
placeholder: String,
disabled: Boolean,
valueFormat: String,
disabledDate: Function
})
const emit = defineEmits(['update:modelValue'])
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<template>
<el-date-picker
:model-value="modelValue"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:value-format="valueFormat"
:disabled="disabled"
:disabled-date="disabledDate"
style="width: 100%"
@update:model-value="handleChange"
/>
</template>
<script setup>
const props = defineProps({
modelValue: Array,
valueFormat: String,
disabled: Boolean,
disabledDate: Function
})
const emit = defineEmits(['update:modelValue'])
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<template>
<el-input
:model-value="innerValue"
:placeholder="placeholder"
:clearable="clearable"
:disabled="disabled"
@input="handleInput"
@update:model-value="handleChange"
/>
</template>
<script setup>
import { ref, watch } from 'vue'
const props = defineProps({
modelValue: String,
placeholder: String,
clearable: Boolean,
disabled: Boolean,
inputType: { type: String, default: 'text' },
decimalDigits: { type: Number, default: 2 }
})
const emit = defineEmits(['update:modelValue'])
const innerValue = ref(props.modelValue)
watch(() => props.modelValue, val => {
innerValue.value = val
})
function handleInput(value) {
let result = String(value ?? '').trim()
if (props.inputType === 'integer') {
result = result.replace(/[^\d]/g, '')
} else if (props.inputType === 'decimal') {
result = result.replace(/[^\d.]/g, '')
if (result.startsWith('.')) result = '0.' + result.slice(1)
const parts = result.split('.')
if (parts.length > 2) result = parts[0] + '.' + parts.slice(1).join('')
if (result.includes('.')) {
const [int, dec] = result.split('.')
if (dec.length > props.decimalDigits) {
result = int + '.' + dec.slice(0, props.decimalDigits)
}
}
}
innerValue.value = result
emit('update:modelValue', result)
}
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<template>
<el-date-picker
:model-value="modelValue"
type="month"
:placeholder="placeholder"
:disabled="disabled"
:value-format="valueFormat"
:disabled-date="disabledDate"
style="width: 100%"
@update:model-value="handleChange"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String,
placeholder: String,
disabled: Boolean,
valueFormat: String,
disabledDate: Function
})
const emit = defineEmits(['update:modelValue'])
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<template>
<el-select
:model-value="modelValue"
:multiple="multiple"
:placeholder="placeholder"
:clearable="clearable"
:filterable="filterable"
:disabled="disabled"
:loading="loading"
@update:model-value="handleChange"
@change="handleChangeWithOption"
@focus="$emit('focus')"
@filter-change="$emit('filter-change', $event)"
>
<el-option
v-for="opt in options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
</template>
<script setup>
const props = defineProps({
modelValue: [String, Number, Array, null],
multiple: Boolean,
placeholder: String,
clearable: Boolean,
filterable: Boolean,
disabled: Boolean,
loading: Boolean,
options: {
type: Array,
default: () => []
}
})
const emit = defineEmits([
'update:modelValue',
'focus',
'filter-change',
'option-change' // 新增:emit 完整 option 对象
])
function handleChange(value) {
emit('update:modelValue', value)
}
function handleChangeWithOption(value) {
// 单选:value 是 primitive;多选:value 是 array
if (props.multiple) {
// 多选暂不支持 extra fields(可按需扩展)
return
}
const option = props.options.find(opt => opt.value === value)
emit('option-change', option)
}
</script>
\ No newline at end of file
<template>
<el-input
:model-value="modelValue"
type="textarea"
:autosize="{ minRows: 2 }"
:disabled="disabled"
:clearable="clearable"
placeholder="请输入"
style="width: 240px"
@update:model-value="handleChange"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String,
disabled: Boolean,
clearable: Boolean
})
const emit = defineEmits(['update:modelValue'])
function handleChange(value) {
emit('update:modelValue', value)
}
</script>
\ No newline at end of file
<!-- src/components/search-form/fields/UploadField.vue -->
<template>
<el-upload
:file-list="innerFileList"
:action="action"
:headers="headers"
:multiple="multiple"
:limit="limit"
:accept="accept"
:list-type="listType"
:disabled="disabled"
:auto-upload="true"
:show-file-list="showFileList"
:on-exceed="handleExceed"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-error="handleError"
:on-remove="handleRemove"
>
<el-icon v-if="uploadType === 'image'" class="iconStyle" :size="20">
<Upload />
</el-icon>
<el-button v-else size="small" type="primary" :link="link" :disabled="disabled">
点击上传文件
</el-button>
<template #tip v-if="maxSize || accept">
<div class="el-upload__tip">
<span v-if="maxSize">大小不超过 {{ formatFileSize(maxSize) }}</span>
<span v-if="accept">支持格式:{{ accept }}</span>
</div>
</template>
</el-upload>
</template>
<script setup>
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Upload } from '@element-plus/icons-vue'
import { deepEqual } from '@/utils/csf-deepEqual'
const props = defineProps({
modelValue: {
type: Array,
default: () => []
},
action: String,
headers: Object,
multiple: Boolean,
limit: Number,
accept: String,
listType: { type: String, default: 'text' },
disabled: Boolean,
showFileList: Boolean,
uploadType: String,
link: Boolean,
maxSize: Number
})
const emit = defineEmits(['update:modelValue'])
// 内部状态:不能直接改 props.modelValue
const innerFileList = ref([...props.modelValue])
// 监听外部 modelValue 变化(如重置表单)
watch(
() => props.modelValue,
(newVal, oldVal) => {
if (!deepEqual(newVal, oldVal)) {
innerFileList.value = [...(newVal || [])]
}
},
{ deep: true }
)
// 格式化文件大小
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
// 文件上传前校验
function beforeUpload(file) {
if (props.maxSize && file.size > props.maxSize) {
ElMessage.error(`文件 ${file.name} 超出大小限制(最大 ${formatFileSize(props.maxSize)})`)
return false
}
if (props.accept) {
const allowed = props.accept.split(',').map(ext => ext.trim().toLowerCase())
const fileExt = '.' + file.name.split('.').pop().toLowerCase()
if (!allowed.includes(fileExt)) {
ElMessage.error(`文件类型不支持,仅支持:${props.accept}`)
return false
}
}
return true
}
// 上传成功
function handleSuccess(response, file) {
const data = response.data || response
const url = data.url || data.fileUrl || data.path
const name = data.name || data.fileName || file.name
if (!url) {
ElMessage.error('上传成功但未返回文件地址')
return
}
// 找到当前文件并更新 url 和 name
const target = innerFileList.value.find(f => f.uid === file.uid)
if (target) {
target.url = url
target.name = name
}
// 同步回父组件
emit('update:modelValue', [...innerFileList.value])
ElMessage.success(`文件 ${file.name} 上传成功`)
}
// 超出数量限制
function handleExceed() {
ElMessage.warning('超出文件数量限制')
}
// 上传失败
function handleError(err, file) {
ElMessage.error(`文件 ${file.name} 上传失败`)
console.error('Upload error:', err)
}
// 删除文件
function handleRemove(file) {
emit('update:modelValue', [...innerFileList.value])
}
// 暴露内部 fileList(可选,用于高级控制)
defineExpose({
fileList: innerFileList
})
</script>
<style scoped>
.iconStyle {
color: #409eff;
}
</style>
\ No newline at end of file
// utils/deepEqual.js
export function deepEqual(a, b) {
if (a === b) return true
if (a == null || b == null) return false
if (typeof a !== typeof b) return false
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false
for (let i = 0; i < a.length; i++) {
if (!deepEqual(a[i], b[i])) return false
}
return true
}
if (typeof a === 'object' && typeof b === 'object') {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
if (keysA.length !== keysB.length) return false
for (const key of keysA) {
if (!deepEqual(a[key], b[key])) return false
}
return true
}
return false
}
\ No newline at end of file
......@@ -13,7 +13,7 @@
<el-table-column prop="policyNo" label="保单号" width="200" sortable />
<el-table-column prop="status" label="新单状态" width="120" sortable>
<template #default="{ row }">
{{ getDictLabel('csf_policy_follow_status', row.status) }}
{{ getDictLabel('csf_policy_follow_status_new', row.status) }}
</template>
</el-table-column>
<el-table-column prop="appointmentNo" label="预约编号" width="200" sortable />
......@@ -68,9 +68,11 @@
</CommonDialog>
<!-- 查看详情、更新数据 -->
<CommonDialog :dialogTitle='mode === "viewDetail" ? "查看详情" : "更新数据"' dialogWidth='80%' :openDialog=viewDetailDialogFlag :showAction='false'
:showClose='true' @close='viewDetailDialogFlag = false' @confirm='handleUpdateSubmit'>
<PolicyDetail v-model="policyDetailFormData" ref="policyDetailFormRef" @submit="onSubmit" @cancel="showDialog = false"/>
<CommonDialog :dialogTitle='mode === "viewDetail" ? "查看详情" : "更新数据"' dialogWidth='80%'
:openDialog=viewDetailDialogFlag :showAction='false' :showClose='true' @close='viewDetailDialogFlag = false'
@confirm='handleUpdateSubmit'>
<PolicyDetail v-model="policyDetailFormData" ref="policyDetailFormRef" @submit="onSubmit"
@cancel="viewDetailDialogFlag = false" />
</CommonDialog>
......@@ -78,7 +80,7 @@
</template>
<script setup>
import { ref, reactive, computed, watch ,nextTick} from 'vue'
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import CommonPage from '@/components/commonPage'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
......@@ -90,7 +92,8 @@ import {
getPolicyFollowList,
getExpectedCommissionList,
changePolicyStatus,
policyFollowReport
policyFollowReport,
saveMailingInfo, updatePolicyfollow, batchSaveBrokers, saveInitialPayment
} from '@/api/sign/underwritingMain'
import PolicyDetail from './policyDetail.vue'
......@@ -115,7 +118,7 @@ const editStatusFormConfig = ref([
type: 'select',
prop: 'status',
label: '新单状态',
dictType: 'csf_policy_follow_status'
dictType: 'csf_policy_follow_status_new'
}, {
type: 'date',
prop: 'policyEffectiveDate',
......@@ -155,20 +158,94 @@ const handleEditStatusSubmit = async () => {
// 查看详情、更新数据
const viewDetailDialogFlag = ref(false)
const onSubmit = (data) => {
const onSubmit = async (data) => {
console.log('提交的数据:', data)
// 调用 API 保存
alert('提交成功!')
viewDetailDialogFlag.value = false
// alert('提交成功!')
let params = {}
if (data.activeTab === 'postal') {
params = {
policyBizId: selectedRow.value.policyBizId,
...data,
activeTab: undefined
}
const res = await saveMailingInfo(params)
if (res.code === 200) {
ElMessage.success('保存邮寄信息成功')
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || '保存邮寄信息失败')
}
} else if (data.activeTab === 'basic' || data.activeTab === 'productPlan') {
params = {
policyBizId: selectedRow.value.policyBizId,
...data,
activeTab: undefined
}
const res = await updatePolicyfollow(params)
if (res.code === 200) {
ElMessage.success('保存基本信息成功')
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || '保存基本信息失败')
}
} else if (data.activeTab === 'introducer') {
params = {
policyBizId: selectedRow.value.policyBizId,
brokerList: normalizeIntroducerData(data),
activeTab: undefined
}
const res = await batchSaveBrokers(params)
if (res.code === 200) {
ElMessage.success('保存转介人成功')
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || '保存转介人失败')
}
} else if (data.activeTab === 'attachment') {
} else if (data.activeTab === 'firstPayment') {
try {
params = {
policyBizId: selectedRow.value.policyBizId,
...data,
activeTab: undefined
}
const res = await saveInitialPayment(params)
if (res.code === 200) {
ElMessage.success('保存首期缴费成功')
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || '保存首期缴费失败')
}
} catch (error) {
console.error('首期缴费表单验证失败', error)
return
}
}
}
const handleClose = () => {
// 可选:清空数据
}
const normalizeIntroducerData = (data) => {
if (Array.isArray(data)) return data
if (data && typeof data === 'object') {
const keys = Object.keys(data).filter(k => /^\d+$/.test(k))
if (keys.length > 0) {
return keys.sort((a, b) => a - b).map(k => data[k])
}
}
return []
}
// 获取新单状态,字典值转化方法
onMounted(async () => {
try {
await loadDicts(['csf_policy_follow_status'])
await loadDicts(['csf_policy_follow_status_new'])
} catch (error) {
console.error('字典加载失败', error)
} finally {
......@@ -234,7 +311,7 @@ const searchConfig = ref([
type: 'select',
prop: 'status',
label: '新单状态',
dictType: 'csf_policy_follow_status'
dictType: 'csf_policy_follow_status_new'
},
{
type: 'input',
......@@ -342,9 +419,9 @@ const handleSelect = async (e, row) => {
case 'viewDetail':
// ElMessage.info('查看详情')
viewDetailDialogFlag.value = true
// 等待 DOM 更新完成
// 等待 DOM 更新完成
await nextTick()
if(policyDetailFormRef.value) {
if (policyDetailFormRef.value) {
// 调用子组件详情查询接口
const data = await policyDetailFormRef.value.getPolicyfollowDetail(row.policyBizId)
}
......@@ -412,8 +489,35 @@ const handleUpdateSubmit = async () => {
}
}
// 保存邮寄信息
const saveMailingInfoapi = async () => {
if (!basicInfoFormData.value.policyNo) {
ElMessage.error('请先输入保单号')
return
}
try {
const params = {
policyBizId: basicInfoFormData.value.policyBizId,
mailingMethod: postalFormData.value.mailingMethod,
deliveryNo: postalFormData.value.deliveryNo,
brokerSignDate: postalFormData.value.brokerSignDate,
customerSignDate: postalFormData.value.customerSignDate,
}
const res = await savePostalInfo(params)
if (res.code === 200) {
ElMessage.success('保存邮寄信息成功')
} else {
ElMessage.error(res.msg || '保存邮寄信息失败')
}
} catch (error) {
console.error('保存邮寄信息失败', error)
} finally {
}
}
......
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