yunzer_go/pc/src/views/apps/crm/supplier/index.vue
2026-01-07 08:43:14 +08:00

293 lines
8.2 KiB
Vue

<template>
<div class="crm-customer">
<div class="customer-container">
<!-- 顶部操作栏 -->
<div class="toolbar">
<el-button type="primary" @click="handleAdd">新增供应商</el-button>
<el-button @click="handleRefresh">刷新</el-button>
<div class="search-bar">
<el-input
v-model="searchQuery"
placeholder="搜索供应商名称/联系人/电话"
clearable
@clear="handleSearch"
>
<template #append>
<el-button :icon="Search" @click="handleSearch" />
</template>
</el-input>
</div>
</div>
<!-- 供应商列表 -->
<el-table
:data="customerList"
v-loading="loading"
stripe
border
style="width: 100%"
>
<el-table-column prop="supplier_name" label="供应商名称" width="360" fixed="left">
<template #default="{ row }">
<div style="display: flex; align-items: center; gap: 8px;">
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
{{ row.status === '1' ? '正常' : '停用' }}
</el-tag>
<el-link type="primary" @click="handleView(row)">{{ row.supplier_name }}</el-link>
</div>
</template>
</el-table-column>
<el-table-column prop="contact_person" label="法人" width="100" />
<el-table-column prop="contact_phone" label="联系电话" width="160" />
<el-table-column prop="contact_email" label="邮箱" min-width="180" />
<el-table-column prop="address" label="地址" min-width="300" show-overflow-tooltip />
<el-table-column label="操作" width="250" fixed="right">
<template #default="{ row }">
<el-button link type="info" @click="handleContactView(row)">联系人</el-button>
<el-button link type="info" @click="handleInvoiceView(row)">开票信息</el-button>
<el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<!-- 编辑弹窗 -->
<Edit
v-model="dialogVisible"
:is-edit="isEdit"
:model="currentRow"
@saved="onSaved"
/>
<!-- 详情抽屉 -->
<Detail v-model="detailVisible" :model="currentRow" />
<!-- 联系人抽屉 -->
<Contact v-model="contactVisible" :model="currentRow" />
<!-- 开票信息抽屉 -->
<Invoice v-model="invoiceVisible" :model="currentRow" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Search } from '@element-plus/icons-vue';
import Edit from './components/edit.vue'
import Detail from './components/detail.vue'
import Contact from './components/contact.vue'
import Invoice from './components/invoice.vue'
import { listSuppliers, getSupplier, deleteSupplier } from '../../../../api/supplier.js'
const loading = ref(false);
const customerList = ref([]);
const searchQuery = ref('');
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);
const dialogVisible = ref(false);
const detailVisible = ref(false);
const contactVisible = ref(false);
const invoiceVisible = ref(false);
const isEdit = ref(false);
const currentRow = ref(null);
async function fetchCustomerList() {
loading.value = true
try {
const { data } = await listSuppliers({
keyword: searchQuery.value,
page: currentPage.value,
pageSize: pageSize.value,
})
customerList.value = data.list || []
total.value = data.total || 0
} finally {
loading.value = false
}
}
function handleAdd() {
isEdit.value = false;
currentRow.value = null;
dialogVisible.value = true;
}
function handleEdit(row) {
isEdit.value = true;
currentRow.value = { ...row };
dialogVisible.value = true;
}
function handleView(row) {
currentRow.value = { ...row }
detailVisible.value = true
getSupplier(row.id).then((res) => {
const resp = res && res.data ? res.data : res
if (resp && resp.code === 0 && resp.data) {
const m = resp.data
currentRow.value = {
id: m.id,
name: m.supplier_name || m.name || '',
contact: m.contact_person || m.contact || '',
phone: m.contact_phone || m.phone || '',
email: m.contact_email || m.email || '',
address: m.address || '',
status: typeof m.status === 'number' ? m.status : (m.status === '0' ? 0 : 1),
_raw: m,
}
}
})
}
function handleContactView(row) {
currentRow.value = { ...row }
contactVisible.value = true
getSupplier(row.id).then((res) => {
const resp = res && res.data ? res.data : res
if (resp && resp.code === 0 && resp.data) {
const m = resp.data
currentRow.value = {
id: m.id,
name: m.supplier_name || m.name || '',
contact: m.contact_person || m.contact || '',
phone: m.contact_phone || m.phone || '',
email: m.contact_email || m.email || '',
address: m.address || '',
status: typeof m.status === 'number' ? m.status : (m.status === '0' ? 0 : 1),
supplier_type: m.supplier_type,
supplier_level: m.supplier_level,
industry: m.industry,
_raw: m,
}
}
})
}
function handleInvoiceView(row) {
currentRow.value = { ...row }
invoiceVisible.value = true
getSupplier(row.id).then((res) => {
const resp = res && res.data ? res.data : res
if (resp && resp.code === 0 && resp.data) {
const m = resp.data
currentRow.value = {
id: m.id,
name: m.supplier_name || m.name || '',
contact: m.contact_person || m.contact || '',
phone: m.contact_phone || m.phone || '',
email: m.contact_email || m.email || '',
address: m.address || '',
status: typeof m.status === 'number' ? m.status : (m.status === '0' ? 0 : 1),
supplier_type: m.supplier_type,
supplier_level: m.supplier_level,
industry: m.industry,
// 开票相关(如果后端返回则透传给抽屉)
invoice_title: m.invoice_title,
tax_number: m.tax_number,
bank_name: m.bank_name,
bank_account: m.bank_account,
registered_address: m.registered_address,
registered_phone: m.registered_phone,
_raw: m,
}
}
})
}
function handleDelete(row) {
ElMessageBox.confirm('确定要删除该供应商吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteSupplier(row.id)
.then((res) => {
const resp = res && res.data ? res.data : res
if (resp && resp.code === 0) {
ElMessage.success('删除成功');
fetchCustomerList();
} else {
ElMessage.error((resp && resp.message) || '删除失败')
}
})
});
}
function onSaved() {
fetchCustomerList();
}
function handleSearch() {
currentPage.value = 1;
fetchCustomerList();
}
function handleRefresh() {
searchQuery.value = '';
currentPage.value = 1;
fetchCustomerList();
}
function handleSizeChange() {
fetchCustomerList();
}
function handleCurrentChange() {
fetchCustomerList();
}
onMounted(() => {
fetchCustomerList();
});
</script>
<style lang="scss" scoped>
.crm-customer {
padding: 20px;
height: 100%;
background: #f5f7fa;
.customer-container {
background: #fff;
border-radius: 8px;
padding: 20px;
height: 100%;
display: flex;
flex-direction: column;
.toolbar {
display: flex;
gap: 10px;
margin-bottom: 20px;
.search-bar {
margin-left: auto;
width: 300px;
}
}
.pagination {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
}
}
</style>