refactor(AdminIndex): 统一字段命名并优化数据映射逻辑

重构表单字段命名以保持前后端一致性,优化数据映射逻辑确保正确回显。
移除未使用的导入并简化状态管理,提升代码可维护性。
This commit is contained in:
2026-03-18 20:02:02 +08:00
parent f32be38b8f
commit d9a7f824f4

View File

@@ -74,7 +74,7 @@
<n-space align="center">
<span class="table-title">数据列表</span>
<n-text depth="3" style="font-size: 12px; font-weight: normal;">共找到 {{ pagination.itemCount
}}
}}
条记录</n-text>
</n-space>
</template>
@@ -104,10 +104,10 @@
</n-icon> 执行分配</div>
<n-form label-placement="left" label-width="100">
<n-form-item label="分配指导师">
<n-input v-model:value="editingRow.guideName" placeholder="输入指导师姓名" />
<n-input v-model:value="editingRow.assignee_name" placeholder="输入指导师姓名" />
</n-form-item>
<n-form-item label="联系电话">
<n-input v-model:value="editingRow.guidePhone" placeholder="输入指导师手机号" />
<n-input v-model:value="editingRow.assignee_phone" placeholder="输入指导师手机号" />
</n-form-item>
</n-form>
</div>
@@ -119,23 +119,24 @@
</n-icon> 客户及成交信息</div>
<n-descriptions label-placement="left" :column="2" bordered size="small"
class="custom-desc">
<n-descriptions-item label="分析师主管">{{ editingRow.analystSupervisor
}}</n-descriptions-item>
<n-descriptions-item label="分析师部门">{{ editingRow.analystDepartment
}}</n-descriptions-item>
<n-descriptions-item label="分析师姓名">{{ editingRow.analystName
}}</n-descriptions-item>
<n-descriptions-item label="家长姓名">{{ editingRow.parentName }}</n-descriptions-item>
<n-descriptions-item label="家长电话">{{ editingRow.parentPhone }}</n-descriptions-item>
<n-descriptions-item label="身份证号">{{ editingRow.parentIdCard
}}</n-descriptions-item>
<n-descriptions-item label="成交日期">{{ editingRow.transactionDate
<n-descriptions-item label="分析师主管">{{ editingRow.analyst_supervisor
}}</n-descriptions-item>
<n-descriptions-item label="分析师部门">{{ editingRow.analyst_department
}}</n-descriptions-item>
<n-descriptions-item label="分析师姓名">{{ editingRow.analyst_name
}}</n-descriptions-item>
<n-descriptions-item label="家长姓名">{{ editingRow.parent_name }}</n-descriptions-item>
<n-descriptions-item label="家长电话">{{ editingRow.parent_phone
}}</n-descriptions-item>
<n-descriptions-item label="身份证号">{{ editingRow.parent_id_card
}}</n-descriptions-item>
<n-descriptions-item label="成交日期">{{ editingRow.transaction_date
}}</n-descriptions-item>
<n-descriptions-item label="成交金额"><span class="price-text">¥{{
editingRow.transactionAmount
editingRow.transaction_amount
}}</span></n-descriptions-item>
<n-descriptions-item label="指导周期" :span="2">{{ editingRow.guidancePeriod
}}</n-descriptions-item>
<n-descriptions-item label="指导周期" :span="2">{{ editingRow.guidance_period
}}</n-descriptions-item>
</n-descriptions>
</div>
@@ -143,7 +144,7 @@
<div class="group-title"><n-icon>
<FileTrayOutline />
</n-icon> 附件文档</div>
<div class="file-box" v-if="editingRow.files?.length && editingRow.files[0]">
<div class="file-box" v-if="editingRow.attachment_file_url">
<n-button block secondary type="primary" @click="downloadFile">下载附件文档</n-button>
</div>
<n-empty v-else description="未上传附件" size="small" />
@@ -155,7 +156,7 @@
</n-icon> 付款截图</div>
<n-image-group>
<n-space>
<n-image v-for="(img, i) in editingRow.paymentImages" :key="i" width="120"
<n-image v-for="(img, i) in editingRow.payment_image_urls" :key="i" width="120"
height="120" fit="cover" class="preview-img" :src="img" />
</n-space>
</n-image-group>
@@ -166,7 +167,8 @@
<BrushOutline />
</n-icon> 电子签名</div>
<div class="signature-wrapper">
<n-image v-if="editingRow.signature" width="240" :src="editingRow.signature" />
<n-image v-if="editingRow.signature_image_url" width="240"
:src="editingRow.signature_image_url" />
<n-text v-else depth="3">暂无签名数据</n-text>
</div>
</div>
@@ -196,7 +198,7 @@ import {
import {
SearchOutline, LogOutOutline, DownloadOutline, PersonOutline, FileTrayOutline,
ImagesOutline, BrushOutline, ReaderOutline, EyeOutline, CheckmarkCircleOutline
ImagesOutline, BrushOutline, ReaderOutline, EyeOutline
} from '@vicons/ionicons5'
const router = useRouter()
@@ -204,7 +206,6 @@ const message = useMessage()
const loading = ref(false)
const submitLoading = ref(false)
// 搜索参数
const searchParams = reactive({
wecom_id: '',
parentInfo: '',
@@ -219,7 +220,6 @@ const statusOptions = [
const displayData = ref([])
// 分页配置
const pagination = reactive({
page: 1,
pageSize: 10,
@@ -237,7 +237,7 @@ const pagination = reactive({
}
})
// 1. 获取列表数据
// 1. 获取列表数据并映射回显
const fetchData = async () => {
loading.value = true
try {
@@ -256,24 +256,35 @@ const fetchData = async () => {
if (res.success) {
displayData.value = res.data.map(item => ({
id: item.wecom_id,
analystSupervisor: item.analyst_supervisor,
analystDepartment: item.analyst_department,
analystName: item.analyst_name,
parentName: item.parent_name,
parentPhone: item.parent_phone,
parentIdCard: item.parent_id_card,
transactionDate: item.transaction_date,
transactionAmount: item.transaction_amount || '0',
guidancePeriod: item.guidance_period,
submissionTime: item.submission_time,
// 基础信息
wecom_id: item.wecom_id,
analyst_supervisor: item.analyst_supervisor,
analyst_department: item.analyst_department,
analyst_name: item.analyst_name,
parent_name: item.parent_name,
parent_phone: item.parent_phone,
parent_id_card: item.parent_id_card || '',
transaction_date: item.transaction_date,
transaction_amount: item.transaction_amount || '0',
guidance_period: item.guidance_period || '',
submission_time: item.submission_time,
status: item.status,
paymentImages: item.payment_image_url ? [item.payment_image_url] : [],
signature: item.signature_image_url,
files: item.attachment_file_url ? [item.attachment_file_url] : [],
// 交互字段
guideName: '',
guidePhone: '',
// --- 修复关键:直接映射分配人信息以实现回显 ---
assignee_name: item.assignee_name || '',
assignee_phone: item.assignee_phone || '',
// 存储原始 Object Names (用于提交接口)
payment_object_names: Array.isArray(item.payment_object_names) ? item.payment_object_names : [],
signature_object_name: item.signature_object_name || '',
attachment_object_name: item.attachment_object_name || '',
// 带有签名的展示 URL
payment_image_urls: item.payment_image_url || [],
signature_image_url: item.signature_image_url,
attachment_file_url: item.attachment_file_url,
// 交互状态
isSubmitting: false
}))
pagination.itemCount = res.pagination.total
@@ -287,36 +298,32 @@ const fetchData = async () => {
}
}
// 2. 提交分配请求函数
// 2. 提交分配请求
const submitAssignment = async (row) => {
if (!row.guideName || !row.guidePhone) {
message.warning('请填写完整的指导师信息')
return
if (!row.assignee_name || !row.assignee_phone) {
message.warning('请填写指导师姓名和电话')
return false
}
row.isSubmitting = true
try {
// --- 修改开始 ---
// 构建与 curl 命令匹配的 payload
const payload = {
wecom_id: row.id,
// payment_object_names 需要是一个数组
payment_object_names: row.paymentImages || [],
signature_object_name: row.signature || "",
attachment_object_name: row.files?.[0] || "",
analyst_supervisor: row.analystSupervisor,
analyst_department: row.analystDepartment,
analyst_name: row.analystName,
parent_name: row.parentName,
parent_phone: row.parentPhone,
parent_id_card: row.parentIdCard,
transaction_date: row.transactionDate,
transaction_amount: String(row.transactionAmount),
guidance_period: row.guidancePeriod,
assignee_name: row.guideName,
assignee_phone: row.guidePhone
wecom_id: String(row.wecom_id),
payment_object_names: row.payment_object_names,
signature_object_name: row.signature_object_name,
attachment_object_name: row.attachment_object_name,
analyst_supervisor: row.analyst_supervisor,
analyst_department: row.analyst_department,
analyst_name: row.analyst_name,
parent_name: row.parent_name,
parent_phone: row.parent_phone,
parent_id_card: row.parent_id_card,
transaction_date: row.transaction_date,
transaction_amount: String(row.transaction_amount),
guidance_period: row.guidance_period,
assignee_name: row.assignee_name,
assignee_phone: row.assignee_phone
}
// --- 修改结束 ---
const response = await fetch('http://192.168.15.115:5636/api/v1/material/submit', {
method: 'POST',
@@ -328,27 +335,35 @@ const submitAssignment = async (row) => {
})
const res = await response.json()
if (res.success || res.code === 200) {
message.success('分配成功')
row.status = 'processed' // 本地更新状态
if (response.ok && (res.success || res.code === 200)) {
message.success('分配并提报成功')
row.status = 'processed'
return true
} else {
message.error(res.message || '提交失败')
return false
}
} catch (error) {
message.error('提交请求失败,请检查网络')
message.error('网络请求异常')
return false
} finally {
row.isSubmitting = false
}
}
const handleDrawerSubmit = async () => {
submitLoading.value = true
const success = await submitAssignment(editingRow.value)
submitLoading.value = false
if (success) showDrawer.value = false
}
// 表格列定义
const columns = [
{ title: '分析师', key: 'analystName', width: 90, fixed: 'left' },
{ title: '家长姓名', key: 'parentName', width: 90 },
{ title: '家长电话', key: 'parentPhone', width: 120 },
{ title: '分析师', key: 'analyst_name', width: 90, fixed: 'left' },
{ title: '家长姓名', key: 'parent_name', width: 90 },
{ title: '家长电话', key: 'parent_phone', width: 120 },
{
title: '状态',
key: 'status',
@@ -358,27 +373,27 @@ const columns = [
round: true, size: 'small'
}, { default: () => row.status === 'pending' ? '待处理' : '已处理' })
},
{ title: '成交金额', key: 'transactionAmount', width: 100, render: (row) => h('span', { class: 'price-text' }, `¥${row.transactionAmount}`) },
{ title: '成交金额', key: 'transaction_amount', width: 100, render: (row) => h('span', { class: 'price-text' }, `¥${row.transaction_amount}`) },
{
title: '分配指导师姓名',
key: 'guideName',
key: 'assignee_name',
width: 130,
render: (row) => h(NInput, {
value: row.guideName,
value: row.assignee_name,
size: 'small',
placeholder: '输入姓名',
onUpdateValue: (v) => { row.guideName = v }
onUpdateValue: (v) => { row.assignee_name = v }
})
},
{
title: '指导师电话',
key: 'guidePhone',
key: 'assignee_phone',
width: 160,
render: (row) => h(NInput, {
value: row.guidePhone,
value: row.assignee_phone,
size: 'small',
placeholder: '输入手机号',
onUpdateValue: (v) => { row.guidePhone = v }
onUpdateValue: (v) => { row.assignee_phone = v }
})
},
{
@@ -405,22 +420,13 @@ const columns = [
}
]
// 抽屉逻辑
const showDrawer = ref(false)
const editingRow = ref({})
const openDetails = (row) => {
editingRow.value = row // 这里使用引用,方便同步修改
editingRow.value = row
showDrawer.value = true
}
const handleDrawerSubmit = async () => {
submitLoading.value = true
const success = await submitAssignment(editingRow.value)
submitLoading.value = false
if (success) showDrawer.value = false
}
// 搜索逻辑
const handleSearch = () => { pagination.page = 1; fetchData() }
const resetSearch = () => {
Object.assign(searchParams, { wecom_id: '', parentInfo: '', dateRange: null, status: null })
@@ -431,7 +437,7 @@ const resetSearch = () => {
onMounted(() => fetchData())
const logout = () => { localStorage.clear(); router.push('/login') }
const downloadFile = () => { if (editingRow.value.files?.[0]) window.open(editingRow.value.files[0]) }
const downloadFile = () => { if (editingRow.value.attachment_file_url) window.open(editingRow.value.attachment_file_url) }
</script>
<style scoped>