feat(收尾): 附录A#10联系人CRUD补齐(serializer可写FK+前端dialog+test_contact_crud) / D2真机重跑全绿 / 后端512+PG4

This commit is contained in:
seagull
2026-09-14 02:01:59 +08:00
parent e0e1430e8d
commit 2973776dc3
4 changed files with 245 additions and 1 deletions
+82
View File
@@ -22,12 +22,24 @@
<div class="toolbar">
<el-input v-model="contactSearch" placeholder="搜索联系人姓名" style="width: 240px" clearable @keyup.enter="loadContacts" />
<el-button type="primary" @click="loadContacts">查询</el-button>
<el-button type="primary" @click="openContactCreate">新建联系人</el-button>
</div>
<el-table :data="contacts" v-loading="contactsLoading" size="small" stripe>
<el-table-column prop="name" label="姓名" width="140" />
<el-table-column prop="phone" label="电话" width="150" />
<el-table-column prop="email" label="邮箱" min-width="160" />
<el-table-column prop="title" label="职位" width="140" />
<el-table-column label="归属" width="180">
<template #default="{ row }">
{{ row.customer_code || row.supplier_code || '—' }}
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="openContactEdit(row)">编辑</el-button>
<el-button link type="danger" size="small" @click="removeContact(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 14px"
@@ -56,6 +68,25 @@
<el-button type="primary" :loading="saving" @click="saveLevel">保存</el-button>
</template>
</el-dialog>
<el-dialog v-model="contactDialogVisible" :title="contactEditing ? '编辑联系人' : '新建联系人'" width="480px">
<el-form ref="contactFormRef" :model="contactForm" :rules="contactRules" label-width="100px">
<el-form-item label="姓名" prop="name"><el-input v-model="contactForm.name" /></el-form-item>
<el-form-item label="电话" prop="phone"><el-input v-model="contactForm.phone" /></el-form-item>
<el-form-item label="邮箱" prop="email"><el-input v-model="contactForm.email" /></el-form-item>
<el-form-item label="职位" prop="title"><el-input v-model="contactForm.title" /></el-form-item>
<el-form-item label="客户ID" prop="customer">
<el-input-number v-model="contactForm.customer" :min="0" :precision="0" style="width: 100%" placeholder="可选:挂靠客户" />
</el-form-item>
<el-form-item label="供应商ID" prop="supplier">
<el-input-number v-model="contactForm.supplier" :min="0" :precision="0" style="width: 100%" placeholder="可选:挂靠供应商" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="contactDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="contactSaving" @click="saveContact">保存</el-button>
</template>
</el-dialog>
</el-card>
</template>
@@ -81,6 +112,15 @@ const rules = {
code: [{ required: true, message: '请输入等级编码', trigger: 'blur' }],
name: [{ required: true, message: '请输入等级名称', trigger: 'blur' }],
}
const contactDialogVisible = ref(false)
const contactEditing = ref(null)
const contactSaving = ref(false)
const contactFormRef = ref(null)
const contactForm = reactive({ name: '', phone: '', email: '', title: '', customer: null, supplier: null })
const contactRules = {
name: [{ required: true, message: '请输入联系人姓名', trigger: 'blur' }],
email: [{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }],
}
async function loadLevels() {
levelsLoading.value = true
@@ -141,6 +181,48 @@ async function removeLevel(row) {
await loadLevels()
}
function openContactCreate() {
contactEditing.value = null
Object.assign(contactForm, { name: '', phone: '', email: '', title: '', customer: null, supplier: null })
contactDialogVisible.value = true
}
function openContactEdit(row) {
contactEditing.value = row
Object.assign(contactForm, {
name: row.name || '', phone: row.phone || '', email: row.email || '',
title: row.title || '', customer: row.customer || null, supplier: row.supplier || null,
})
contactDialogVisible.value = true
}
async function saveContact() {
const ok = await contactFormRef.value.validate().catch(() => false)
if (!ok) return
contactSaving.value = true
try {
const payload = { ...contactForm }
if (!payload.customer) delete payload.customer
if (!payload.supplier) delete payload.supplier
if (contactEditing.value) await api.patch(`/partner/contacts/${contactEditing.value.id}/`, payload)
else await api.post('/partner/contacts/', payload)
ElMessage.success('已保存')
contactDialogVisible.value = false
await loadContacts()
} finally {
contactSaving.value = false
}
}
async function removeContact(row) {
try {
await ElMessageBox.confirm(`删除联系人 ${row.name}?`, '删除确认', { type: 'warning' })
} catch (e) { return }
await api.delete(`/partner/contacts/${row.id}/`)
ElMessage.success('已删除')
await loadContacts()
}
onMounted(() => { loadLevels(); loadContacts() })
</script>