232 lines
9.3 KiB
Vue
232 lines
9.3 KiB
Vue
<template>
|
||
<el-card shadow="never">
|
||
<el-tabs v-model="tab">
|
||
<el-tab-pane label="价格等级" name="levels">
|
||
<div class="toolbar">
|
||
<el-button type="primary" @click="openLevelCreate">新建等级</el-button>
|
||
</div>
|
||
<el-table :data="levels" v-loading="levelsLoading" size="small" stripe>
|
||
<el-table-column prop="code" label="等级编码" width="140" />
|
||
<el-table-column prop="name" label="等级名称" min-width="160" />
|
||
<el-table-column prop="discount_rate" label="折扣率" width="120" />
|
||
<el-table-column prop="sort_order" label="排序" width="100" />
|
||
<el-table-column label="操作" width="150">
|
||
<template #default="{ row }">
|
||
<el-button link type="primary" size="small" @click="openLevelEdit(row)">编辑</el-button>
|
||
<el-button link type="danger" size="small" @click="removeLevel(row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="联系人" name="contacts">
|
||
<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"
|
||
layout="prev, pager, next, total"
|
||
:total="contactsCount"
|
||
:page-size="20"
|
||
v-model:current-page="contactsPage"
|
||
@current-change="loadContacts"
|
||
/>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
|
||
<el-dialog v-model="dialogVisible" :title="editing ? '编辑价格等级' : '新建价格等级'" width="480px">
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||
<el-form-item label="等级编码" prop="code"><el-input v-model="form.code" /></el-form-item>
|
||
<el-form-item label="等级名称" prop="name"><el-input v-model="form.name" /></el-form-item>
|
||
<el-form-item label="折扣率" prop="discount_rate">
|
||
<el-input-number v-model="form.discount_rate" :min="0" :max="1" :precision="4" style="width: 100%" />
|
||
</el-form-item>
|
||
<el-form-item label="排序" prop="sort_order">
|
||
<el-input-number v-model="form.sort_order" :precision="0" style="width: 100%" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="dialogVisible = false">取消</el-button>
|
||
<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>
|
||
|
||
<script setup>
|
||
import { onMounted, ref, reactive } from 'vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import api from '../api/client'
|
||
|
||
const tab = ref('levels')
|
||
const levels = ref([])
|
||
const levelsLoading = ref(false)
|
||
const contacts = ref([])
|
||
const contactsCount = ref(0)
|
||
const contactsPage = ref(1)
|
||
const contactSearch = ref('')
|
||
const contactsLoading = ref(false)
|
||
const dialogVisible = ref(false)
|
||
const editing = ref(null)
|
||
const saving = ref(false)
|
||
const formRef = ref(null)
|
||
const form = reactive({ code: '', name: '', discount_rate: 0, sort_order: 0 })
|
||
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
|
||
try {
|
||
const data = await api.get('/partner/price-levels/', { params: { page_size: 100 } })
|
||
levels.value = data.results || []
|
||
} finally {
|
||
levelsLoading.value = false
|
||
}
|
||
}
|
||
|
||
async function loadContacts() {
|
||
contactsLoading.value = true
|
||
try {
|
||
const data = await api.get('/partner/contacts/', {
|
||
params: { page: contactsPage.value, page_size: 20, search: contactSearch.value },
|
||
})
|
||
contacts.value = data.results || []
|
||
contactsCount.value = data.count || 0
|
||
} finally {
|
||
contactsLoading.value = false
|
||
}
|
||
}
|
||
|
||
function openLevelCreate() {
|
||
editing.value = null
|
||
Object.assign(form, { code: '', name: '', discount_rate: 0, sort_order: 0 })
|
||
dialogVisible.value = true
|
||
}
|
||
|
||
function openLevelEdit(row) {
|
||
editing.value = row
|
||
Object.assign(form, { code: row.code, name: row.name, discount_rate: Number(row.discount_rate), sort_order: row.sort_order })
|
||
dialogVisible.value = true
|
||
}
|
||
|
||
async function saveLevel() {
|
||
const ok = await formRef.value.validate().catch(() => false)
|
||
if (!ok) return
|
||
saving.value = true
|
||
try {
|
||
if (editing.value) await api.patch(`/partner/price-levels/${editing.value.id}/`, { ...form })
|
||
else await api.post('/partner/price-levels/', { ...form })
|
||
ElMessage.success('已保存')
|
||
dialogVisible.value = false
|
||
await loadLevels()
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
async function removeLevel(row) {
|
||
try {
|
||
await ElMessageBox.confirm(`删除等级 ${row.code}(${row.name})?`, '删除确认', { type: 'warning' })
|
||
} catch (e) { return }
|
||
await api.delete(`/partner/price-levels/${row.id}/`)
|
||
ElMessage.success('已删除')
|
||
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>
|
||
|
||
<style scoped>
|
||
.toolbar { display: flex; gap: 10px; margin-bottom: 14px; align-items: center; }
|
||
</style>
|