This commit is contained in:
ChoChoX
2026-06-28 00:36:03 +08:00
parent 63b6cc93c6
commit 27ca129096
10 changed files with 367 additions and 218 deletions

View File

@@ -1,14 +1,14 @@
<template> <template>
<div class="login-container"> <div class="login-container">
<!-- 背景视频 --> <!-- 背景视频 -->
<video src="../../public/登陆界面背景.mp4" autoplay muted loop class="bg-video"></video> <video src="/登陆界面背景.mp4" autoplay muted loop class="bg-video"></video>
<div class="video-overlay"></div> <div class="video-overlay"></div>
<!-- 登录卡片 --> <!-- 登录卡片 -->
<el-card class="login-card" shadow="always"> <el-card class="login-card" shadow="always">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<img src="../../public/logo.png" alt="logo" class="login-logo"> <img src="/logo.png" alt="logo" class="login-logo">
<h2>蜜雪冰城管理系统</h2> <h2>蜜雪冰城管理系统</h2>
<p class="subtitle">请输入您的账号信息</p> <p class="subtitle">请输入您的账号信息</p>
</div> </div>

View File

@@ -16,13 +16,16 @@ import { hasPermission, getUserInfo } from '../store/user'
const search = ref('') const search = ref('')
const select = ref('1') const select = ref('1')
const dateRange = ref([]) const filterType = ref('')
const filterStatus = ref('')
const loading = ref(false) const loading = ref(false)
const searchResults = ref([]) const searchResults = ref([])
const showSearchResults = ref(false) const showSearchResults = ref(false)
const showAddForm = ref(false) const showAddForm = ref(false)
const isEditMode = ref(false) const isEditMode = ref(false)
const currentContractId = ref(null) const currentContractId = ref(null)
const showDetailDialog = ref(false)
const currentDetail = ref(null)
const customerList = ref([]) const customerList = ref([])
const employeeList = ref([]) const employeeList = ref([])
const supplierList = ref([]) const supplierList = ref([])
@@ -30,6 +33,7 @@ const supplierList = ref([])
// 分页相关 // 分页相关
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0)
// 采购经理只能操作采购合同,招商经理只能操作加盟合同(提前定义,供 form 初始化使用) // 采购经理只能操作采购合同,招商经理只能操作加盟合同(提前定义,供 form 初始化使用)
const isProcurementManager = computed(() => getUserInfo()?.departmentName === 'procurement_manager') const isProcurementManager = computed(() => getUserInfo()?.departmentName === 'procurement_manager')
@@ -50,7 +54,7 @@ const form = reactive({
effective_date: '', effective_date: '',
expiry_date: '', expiry_date: '',
amount: 0, amount: 0,
status: '生效', status: '生效',
remark: '' remark: ''
}) })
@@ -59,30 +63,19 @@ onMounted(() => {
fetchOptions() fetchOptions()
}) })
// 监听搜索结果变化,重置页码 // 监听筛选变化(与 user.vue 一致)
watch(searchResults, () => { watch([filterType, filterStatus], () => {
currentPage.value = 1 currentPage.value = 1
handleSearch()
}) })
// 分页后的数据 // 分页后的数据服务端已分页searchResults 即为当前页数据)
const filteredResults = computed(() => { const paginatedData = computed(() => searchResults.value)
if (!isFranchiseManager.value && !isProcurementManager.value) return searchResults.value
return searchResults.value.filter(row => {
if (row.type === 'supply' && isProcurementManager.value) return true
if (row.type === 'franchise' && isFranchiseManager.value) return true
return false
})
})
const paginatedData = computed(() => { // 页码变化(服务端分页:重新请求后端)
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return filteredResults.value.slice(start, end)
})
// 页码变化
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
currentPage.value = val currentPage.value = val
fetchData(val)
} }
// 获取客户、员工、供应商和用户列表供下拉选择 // 获取客户、员工、供应商和用户列表供下拉选择
@@ -106,12 +99,22 @@ const fetchOptions = async () => {
} }
} }
// 获取合同列表 // 获取合同列表(服务端分页)
const fetchData = async () => { const fetchData = async (page) => {
loading.value = true loading.value = true
const res = await getContractList() const params = {
page: page || currentPage.value,
pageSize: pageSize.value
}
const res = await getContractList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -124,40 +127,74 @@ const handleSearch = async () => {
cancelAdd() cancelAdd()
} }
currentPage.value = 1
loading.value = true loading.value = true
const params = {} const params = {
page: 1,
pageSize: pageSize.value
}
// 只在有搜索内容时才添加搜索参数(与 user.vue 一致)
if (search.value) {
if (select.value === '1') { if (select.value === '1') {
params.id = Number(search.value) params.id = Number(search.value)
} else if (select.value === '2') { } else if (select.value === '2') {
params.contract_name = search.value params.contract_name = search.value
} }
if (dateRange.value && dateRange.value.length === 2) { }
params.effective_date_start = formatDate(dateRange.value[0]) if (filterType.value) {
params.effective_date_end = formatDate(dateRange.value[1]) params.type = filterType.value
}
if (filterStatus.value) {
params.status = filterStatus.value
} }
try {
const res = await getContractList(params) const res = await getContractList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} else {
console.warn('[contract] handleSearch 响应异常:', res)
searchResults.value = []
total.value = 0
}
} catch (e) {
console.error('[contract] handleSearch 请求失败:', e)
searchResults.value = []
total.value = 0
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
} }
// 日期变更处理
const handleDateChange = () => {
handleSearch()
}
// 重置搜索 // 重置搜索
const resetSearch = () => { const resetSearch = () => {
search.value = '' search.value = ''
select.value = '1' select.value = '1'
dateRange.value = [] filterType.value = ''
filterStatus.value = ''
currentPage.value = 1
fetchData() fetchData()
} }
// 双击行查看详情
const handleRowDblClick = (row) => {
currentDetail.value = { ...row }
showDetailDialog.value = true
}
// 关闭详情弹窗
const closeDetail = () => {
showDetailDialog.value = false
currentDetail.value = null
}
// 新增合同 // 新增合同
const addContract = () => { const addContract = () => {
resetForm() resetForm()
@@ -257,7 +294,7 @@ const resetForm = () => {
effective_date: '', effective_date: '',
expiry_date: '', expiry_date: '',
amount: 0, amount: 0,
status: '生效', status: '生效',
remark: '' remark: ''
}) })
isEditMode.value = false isEditMode.value = false
@@ -268,9 +305,7 @@ const resetForm = () => {
const getStatusType = (status) => { const getStatusType = (status) => {
const map = { const map = {
'草稿': 'info', '草稿': 'info',
'生效中': 'success',
'生效': 'success', '生效': 'success',
'完成': 'success',
'已完成': 'success', '已完成': 'success',
'作废': 'danger' '作废': 'danger'
} }
@@ -339,8 +374,8 @@ const canDeleteRow = (row) => {
@keyup.enter="handleSearch"> @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="编号" value="1" /> <el-option label="合同编号" value="1" />
<el-option label="名称" value="2" /> <el-option label="合同名称" value="2" />
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
@@ -358,8 +393,17 @@ const canDeleteRow = (row) => {
<div class="filter-row"> <div class="filter-row">
<span class="filter-label">筛选条件</span> <span class="filter-label">筛选条件</span>
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="生效日期" <el-select v-model="filterType" placeholder="合同类型" clearable style="width: 150px; margin-left: 10px;">
end-placeholder="到期日期" style="margin-left: 10px;" @change="handleDateChange" /> <el-option label="加盟合同" value="franchise" />
<el-option label="采购合同" value="supply" />
</el-select>
<el-select v-model="filterStatus" placeholder="合同状态" clearable style="width: 150px; margin-left: 10px;">
<el-option label="草稿" value="草稿" />
<el-option label="生效" value="生效" />
<el-option label="已完成" value="已完成" />
<el-option label="作废" value="作废" />
</el-select>
</div> </div>
</div> </div>
@@ -375,27 +419,17 @@ const canDeleteRow = (row) => {
<div v-else> <div v-else>
<div class="list-header"> <div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条合同</span> <span class="total-count">共找到 {{ total }} 条合同</span>
</div> </div>
<el-table :data="paginatedData" border style="width: 100%"> <el-table :data="paginatedData" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="编号" width="70" /> <el-table-column prop="id" label="合同编号" width="90" />
<el-table-column prop="contract_name" label="合同名称" min-width="180" /> <el-table-column prop="contract_name" label="合同名称" min-width="200" />
<el-table-column prop="type" label="类型" width="90"> <el-table-column prop="type" label="类型" width="90">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.type === 'franchise' ? 'success' : 'warning'">{{ row.type === 'franchise' ? '加盟' : '采购' }}</el-tag> <el-tag :type="row.type === 'franchise' ? 'success' : 'warning'">{{ row.type === 'franchise' ? '加盟' : '采购' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="customer_name" label="客户" width="100">
<template #default="{ row }">
{{ row.customer_name || '-' }}
</template>
</el-table-column>
<el-table-column prop="supplier_name" label="供应商" width="100">
<template #default="{ row }">
{{ row.supplier_name || '-' }}
</template>
</el-table-column>
<el-table-column prop="employee_name" label="业务员" width="90"> <el-table-column prop="employee_name" label="业务员" width="90">
<template #default="{ row }"> <template #default="{ row }">
{{ row.employee_name || '-' }} {{ row.employee_name || '-' }}
@@ -411,16 +445,6 @@ const canDeleteRow = (row) => {
<el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag> <el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="effective_date" label="生效日期" width="110">
<template #default="{ row }">
{{ formatDate(row.effective_date) }}
</template>
</el-table-column>
<el-table-column prop="expiry_date" label="到期日期" width="110">
<template #default="{ row }">
{{ formatDate(row.expiry_date) }}
</template>
</el-table-column>
<el-table-column label="操作" width="160" fixed="right" v-if="canOperate"> <el-table-column label="操作" width="160" fixed="right" v-if="canOperate">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" @click="editContract(row)" v-if="canEditRow(row)">编辑</el-button> <el-button link type="primary" @click="editContract(row)" v-if="canEditRow(row)">编辑</el-button>
@@ -434,7 +458,7 @@ const canDeleteRow = (row) => {
<el-pagination <el-pagination
v-model:current-page="currentPage" v-model:current-page="currentPage"
:page-size="pageSize" :page-size="pageSize"
:total="filteredResults.length" :total="total"
layout="prev, pager, next" layout="prev, pager, next"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
@@ -444,6 +468,35 @@ const canDeleteRow = (row) => {
</div> </div>
</div> </div>
<!-- 合同详情弹窗 -->
<el-dialog v-model="showDetailDialog" title="合同详情" width="700px" @close="closeDetail">
<div v-if="currentDetail" class="detail-content">
<el-descriptions :column="2" border>
<el-descriptions-item label="合同编号">{{ currentDetail.id }}</el-descriptions-item>
<el-descriptions-item label="合同名称">{{ currentDetail.contract_name }}</el-descriptions-item>
<el-descriptions-item label="合同类型">
<el-tag :type="currentDetail.type === 'franchise' ? 'success' : 'warning'">{{ currentDetail.type === 'franchise' ? '加盟合同' : '采购合同' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="getStatusType(currentDetail.status)">{{ currentDetail.status }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="客户">{{ currentDetail.customer_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="供应商">{{ currentDetail.supplier_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="业务员">{{ currentDetail.employee_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ currentDetail.responsible_user_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="金额">¥{{ currentDetail.amount?.toLocaleString() }}</el-descriptions-item>
<el-descriptions-item label="生效日期">{{ formatDate(currentDetail.effective_date) }}</el-descriptions-item>
<el-descriptions-item label="到期日期">{{ formatDate(currentDetail.expiry_date) }}</el-descriptions-item>
<el-descriptions-item label="合同内容" :span="2">{{ currentDetail.contract_content || '无' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ currentDetail.remark || '无' }}</el-descriptions-item>
</el-descriptions>
</div>
<template #footer>
<el-button @click="closeDetail">关闭</el-button>
<el-button type="primary" @click="(() => { const d = currentDetail; closeDetail(); editContract(d) })()" v-if="canOperate">编辑</el-button>
</template>
</el-dialog>
<!-- 新增/编辑表单 --> <!-- 新增/编辑表单 -->
<div v-if="showAddForm" class="contract-form" style="margin-top: 20px;"> <div v-if="showAddForm" class="contract-form" style="margin-top: 20px;">
<el-divider content-position="left">{{ isEditMode ? '编辑合同' : '新增合同' }}</el-divider> <el-divider content-position="left">{{ isEditMode ? '编辑合同' : '新增合同' }}</el-divider>
@@ -514,7 +567,7 @@ const canDeleteRow = (row) => {
<el-form-item label="状态" required> <el-form-item label="状态" required>
<el-select v-model="form.status" style="width: 100%;"> <el-select v-model="form.status" style="width: 100%;">
<el-option label="草稿" value="草稿" /> <el-option label="草稿" value="草稿" />
<el-option label="生效" value="生效" /> <el-option label="生效" value="生效" />
<el-option label="生效" value="生效" /> <el-option label="生效" value="生效" />
<el-option label="完成" value="完成" /> <el-option label="完成" value="完成" />
<el-option label="作废" value="作废" /> <el-option label="作废" value="作废" />
@@ -603,4 +656,12 @@ const canDeleteRow = (row) => {
padding-top: 15px; padding-top: 15px;
border-top: 1px solid #eee; border-top: 1px solid #eee;
} }
.clickable-row {
cursor: pointer;
}
.detail-content {
padding: 10px 0;
}
</style> </style>

View File

@@ -38,6 +38,7 @@ const filterRegion = ref([])
// 分页相关 // 分页相关
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0)
// 只保留省市两级的地区数据 // 只保留省市两级的地区数据
const regionDataTwoLevel = computed(() => { const regionDataTwoLevel = computed(() => {
@@ -50,28 +51,29 @@ const regionDataTwoLevel = computed(() => {
})) }))
}) })
// 分页后的数据 // 分页后的数据服务端已分页searchResults 即为当前页数据)
const paginatedData = computed(() => { const paginatedData = computed(() => searchResults.value)
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return searchResults.value.slice(start, end)
})
onMounted(() => { onMounted(() => {
fetchData() fetchData()
}) })
// 监听搜索结果变化,重置页码 // 获取客户列表(服务端分页)
watch(searchResults, () => { const fetchData = async (page) => {
currentPage.value = 1
})
// 获取客户列表
const fetchData = async () => {
loading.value = true loading.value = true
const res = await getCustomerList() const params = {
page: page || currentPage.value,
pageSize: pageSize.value
}
const res = await getCustomerList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -88,6 +90,8 @@ const handleSearch = async () => {
loading.value = true loading.value = true
try { try {
const params = { const params = {
page: currentPage.value,
pageSize: pageSize.value,
name: select.value === '1' ? search.value : undefined, name: select.value === '1' ? search.value : undefined,
id: select.value === '2' ? Number(search.value) : undefined, id: select.value === '2' ? Number(search.value) : undefined,
province: filterRegion.value?.[0] ? CodeToText[filterRegion.value[0]] : undefined, province: filterRegion.value?.[0] ? CodeToText[filterRegion.value[0]] : undefined,
@@ -96,7 +100,13 @@ const handleSearch = async () => {
const res = await getCustomerList(params) const res = await getCustomerList(params)
if (seq !== searchSeq) return if (seq !== searchSeq) return
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
} finally { } finally {
@@ -215,9 +225,10 @@ const closeDetail = () => {
currentDetail.value = null currentDetail.value = null
} }
// 页码变化 // 页码变化(服务端分页:重新请求后端)
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
currentPage.value = val currentPage.value = val
fetchData(val)
} }
// 检查权限 // 检查权限
@@ -237,8 +248,8 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
class="customer-search-with-select" @keyup.enter="handleSearch"> class="customer-search-with-select" @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="姓名" value="1" /> <el-option label="客户姓名" value="1" />
<el-option label="编号" value="2" /> <el-option label="客户编号" value="2" />
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
@@ -278,11 +289,11 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<div v-else> <div v-else>
<div class="list-header"> <div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条记录</span> <span class="total-count">共找到 {{ total }} 条记录</span>
</div> </div>
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row"> <el-table :data="paginatedData" v-loading="loading" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="编号" width="80" /> <el-table-column prop="id" label="客户编号" width="90" />
<el-table-column prop="name" label="姓名" width="120" /> <el-table-column prop="name" label="姓名" width="120" />
<el-table-column prop="phone" label="电话" width="150" /> <el-table-column prop="phone" label="电话" width="150" />
<el-table-column label="地区" min-width="150"> <el-table-column label="地区" min-width="150">
@@ -306,7 +317,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<el-pagination <el-pagination
v-model:current-page="currentPage" v-model:current-page="currentPage"
:page-size="pageSize" :page-size="pageSize"
:total="searchResults.length" :total="total"
layout="prev, pager, next" layout="prev, pager, next"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
@@ -326,7 +337,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
</el-form-item> </el-form-item>
<el-form-item label="电话" required> <el-form-item label="电话" required>
<el-input v-model="form.phone" maxlength="11" <el-input v-model="form.phone" maxlength="11" oninput="this.value=this.value.replace(/\D/g,'')"
placeholder="请输入11位手机号" style="width: 100%" /> placeholder="请输入11位手机号" style="width: 100%" />
</el-form-item> </el-form-item>

View File

@@ -373,8 +373,8 @@ const showSalary = computed(() => ['总经理办公室', '财务部'].includes(g
class="employee-search-with-select" @keyup.enter="handleSearch"> class="employee-search-with-select" @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="ID" value="1" /> <el-option label="员工编号" value="1" />
<el-option label="姓名" value="2" /> <el-option label="员工姓名" value="2" />
<el-option label="部门" value="3" /> <el-option label="部门" value="3" />
</el-select> </el-select>
</template> </template>
@@ -413,7 +413,7 @@ const showSalary = computed(() => ['总经理办公室', '财务部'].includes(g
</div> </div>
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row"> <el-table :data="paginatedData" v-loading="loading" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="ID" width="60" /> <el-table-column prop="id" label="员工编号" width="90" />
<el-table-column prop="name" label="姓名" width="80" /> <el-table-column prop="name" label="姓名" width="80" />
<el-table-column prop="gender" label="性别" width="60"> <el-table-column prop="gender" label="性别" width="60">
<template #default="{ row }"> <template #default="{ row }">
@@ -531,7 +531,7 @@ const showSalary = computed(() => ['总经理办公室', '财务部'].includes(g
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系电话"> <el-form-item label="联系电话">
<el-input v-model="form.phone" placeholder="请输入手机号" /> <el-input v-model="form.phone" placeholder="请输入手机号" type="tel" maxlength="11" oninput="this.value=this.value.replace(/\D/g,'')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@@ -623,7 +623,7 @@ const showSalary = computed(() => ['总经理办公室', '财务部'].includes(g
<el-dialog v-model="showDetailDialog" title="员工详情" width="650px" @close="closeDetail"> <el-dialog v-model="showDetailDialog" title="员工详情" width="650px" @close="closeDetail">
<div v-if="currentDetail" class="detail-content"> <div v-if="currentDetail" class="detail-content">
<el-descriptions :column="2" border> <el-descriptions :column="2" border>
<el-descriptions-item label="员工ID">{{ currentDetail.id }}</el-descriptions-item> <el-descriptions-item label="员工编号">{{ currentDetail.id }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ currentDetail.name }}</el-descriptions-item> <el-descriptions-item label="姓名">{{ currentDetail.name }}</el-descriptions-item>
<el-descriptions-item label="性别"> <el-descriptions-item label="性别">
<span :style="{ color: currentDetail.gender === '女' ? '#e6a23c' : '#409eff' }">{{ currentDetail.gender }}</span> <span :style="{ color: currentDetail.gender === '女' ? '#e6a23c' : '#409eff' }">{{ currentDetail.gender }}</span>

View File

@@ -2,7 +2,7 @@
<div class="home-container"> <div class="home-container">
<!-- 顶部视频横幅 --> <!-- 顶部视频横幅 -->
<div class="video-banner"> <div class="video-banner">
<video src="../../public/首页顶图.mp4" autoplay muted loop class="bg-video"></video> <video src="/首页顶图.mp4" autoplay muted loop class="bg-video"></video>
<div class="video-overlay"> <div class="video-overlay">
<h2 class="banner-title">欢迎使用蜜雪冰城管理系统</h2> <h2 class="banner-title">欢迎使用蜜雪冰城管理系统</h2>
</div> </div>
@@ -18,7 +18,7 @@
<div class="intro-content"> <div class="intro-content">
<div class="pic-wrapper"> <div class="pic-wrapper">
<img src="../../public/mixue.png" alt="雪王" class="xuewang-img"> <img src="/mixue.png" alt="雪王" class="xuewang-img">
</div> </div>
<div class="txt-wrapper"> <div class="txt-wrapper">
<div class="quote"> <div class="quote">

View File

@@ -45,7 +45,7 @@ const checkPermission = (resource, action) => {
> >
<!-- 左侧 Logo --> <!-- 左侧 Logo -->
<el-menu-item index="" class="logo-item"> <el-menu-item index="" class="logo-item">
<img src="../../public/logo.png" alt="logo" class="logo-img"> <img src="/logo.png" alt="logo" class="logo-img">
<h1 class="logo-title">蜜雪冰城管理系统</h1> <h1 class="logo-title">蜜雪冰城管理系统</h1>
</el-menu-item> </el-menu-item>

View File

@@ -39,14 +39,13 @@ const supplierList = ref([])
// 分页相关 // 分页相关
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0)
// 产品类型映射 // 产品类型映射
const productTypeMap = { const productTypeMap = {
raw_material: '原料', '茶饮原料': '茶饮原料',
packaging: '包装料', '包装物料': '包装料',
equipment: '设备器具', '设备器具': '设备器具'
cleaning: '清洁用品',
promote: '宣传物料'
} }
onMounted(() => { onMounted(() => {
@@ -67,24 +66,25 @@ watch(filterType, () => {
handleSearch() handleSearch()
}) })
// 监听搜索结果变化,重置页码 // 分页后的数据服务端已分页searchResults 即为当前页数据)
watch(searchResults, () => { const paginatedData = computed(() => searchResults.value)
currentPage.value = 1
})
// 分页后的数据 // 获取产品列表(服务端分页)
const paginatedData = computed(() => { const fetchData = async (page) => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return searchResults.value.slice(start, end)
})
// 获取产品列表
const fetchData = async () => {
loading.value = true loading.value = true
const res = await getProductsList() const params = {
page: page || currentPage.value,
pageSize: pageSize.value
}
const res = await getProductsList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -99,6 +99,8 @@ const handleSearch = async () => {
loading.value = true loading.value = true
const params = { const params = {
page: currentPage.value,
pageSize: pageSize.value,
type: filterType.value || undefined type: filterType.value || undefined
} }
if (select.value === '1') { if (select.value === '1') {
@@ -110,7 +112,13 @@ const handleSearch = async () => {
} }
const res = await getProductsList(params) const res = await getProductsList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -236,18 +244,17 @@ const closeDetail = () => {
// 产品类型标签样式 // 产品类型标签样式
const getTypeTag = (type) => { const getTypeTag = (type) => {
const map = { const map = {
raw_material: '', '茶饮原料': '',
packaging: 'success', '包装物料': 'success',
equipment: 'warning', '设备器具': 'warning'
cleaning: 'info',
promote: 'danger'
} }
return map[type] || 'info' return map[type] || 'info'
} }
// 页码变化 // 页码变化(服务端分页:重新请求后端)
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
currentPage.value = val currentPage.value = val
fetchData(val)
} }
// 检查权限 // 检查权限
@@ -267,8 +274,8 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
class="products-search-with-select" @keyup.enter="handleSearch"> class="products-search-with-select" @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="ID" value="1" /> <el-option label="产品编号" value="1" />
<el-option label="名称" value="2" /> <el-option label="产品名称" value="2" />
<el-option label="供应商" value="3" /> <el-option label="供应商" value="3" />
</el-select> </el-select>
</template> </template>
@@ -286,11 +293,9 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<div class="filter-row"> <div class="filter-row">
<span class="filter-label">筛选条件</span> <span class="filter-label">筛选条件</span>
<el-select v-model="filterType" placeholder="产品类型" clearable style="width: 140px; margin-right: 12px;"> <el-select v-model="filterType" placeholder="产品类型" clearable style="width: 140px; margin-right: 12px;">
<el-option label="原料" value="raw_material" /> <el-option label="茶饮原料" value="茶饮原料" />
<el-option label="包装料" value="packaging" /> <el-option label="包装料" value="包装物料" />
<el-option label="设备器具" value="equipment" /> <el-option label="设备器具" value="设备器具" />
<el-option label="清洁用品" value="cleaning" />
<el-option label="宣传物料" value="promote" />
</el-select> </el-select>
</div> </div>
</div> </div>
@@ -306,12 +311,12 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<div v-else> <div v-else>
<div class="list-header"> <div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条记录</span> <span class="total-count">共找到 {{ total }} 条记录</span>
</div> </div>
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%" <el-table :data="paginatedData" v-loading="loading" border style="width: 100%"
@row-dblclick="handleRowDblClick" row-class-name="clickable-row"> @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="ID" width="70" /> <el-table-column prop="id" label="产品编号" width="90" />
<el-table-column prop="name" label="产品名称" min-width="120" /> <el-table-column prop="name" label="产品名称" min-width="120" />
<el-table-column prop="type" label="产品类型" width="110"> <el-table-column prop="type" label="产品类型" width="110">
<template #default="{ row }"> <template #default="{ row }">
@@ -342,7 +347,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<el-pagination <el-pagination
v-model:current-page="currentPage" v-model:current-page="currentPage"
:page-size="pageSize" :page-size="pageSize"
:total="searchResults.length" :total="total"
layout="prev, pager, next" layout="prev, pager, next"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
@@ -362,11 +367,9 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<el-form-item label="产品类型" required> <el-form-item label="产品类型" required>
<el-select v-model="form.type" placeholder="请选择产品类型" style="width: 100%;"> <el-select v-model="form.type" placeholder="请选择产品类型" style="width: 100%;">
<el-option label="原料" value="raw_material" /> <el-option label="茶饮原料" value="茶饮原料" />
<el-option label="包装料" value="packaging" /> <el-option label="包装料" value="包装物料" />
<el-option label="设备器具" value="equipment" /> <el-option label="设备器具" value="设备器具" />
<el-option label="清洁用品" value="cleaning" />
<el-option label="宣传物料" value="promote" />
</el-select> </el-select>
</el-form-item> </el-form-item>

View File

@@ -32,6 +32,8 @@ const showSearchResults = ref(false)
const showAddForm = ref(false) const showAddForm = ref(false)
const isEditMode = ref(false) const isEditMode = ref(false)
const currentServiceId = ref(null) const currentServiceId = ref(null)
const showDetailDialog = ref(false)
const currentDetail = ref(null)
const loading = ref(false) const loading = ref(false)
const customerList = ref([]) const customerList = ref([])
const employeeList = ref([]) const employeeList = ref([])
@@ -39,6 +41,7 @@ const employeeList = ref([])
// 分页相关 // 分页相关
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0)
// 状态映射 // 状态映射
const statusMap = { const statusMap = {
@@ -73,37 +76,31 @@ watch(() => form.handle_status, (val) => {
} }
}) })
// 监听筛选变化 // 监听筛选变化(与 user.vue 一致)
watch(filterStatus, () => { watch(filterStatus, () => {
currentPage.value = 1 currentPage.value = 1
handleSearch() handleSearch()
}) })
// 监听搜索结果变化,重置页码 // 分页后的数据服务端已分页searchResults 即为当前页数据)
watch(searchResults, () => { const paginatedData = computed(() => searchResults.value)
currentPage.value = 1
})
const filteredResults = computed(() => { // 获取售后列表(服务端分页)
if (!isOperationsManager.value) return searchResults.value const fetchData = async (page) => {
return searchResults.value.filter(row => {
return row.responsible_user_id != null && Number(row.responsible_user_id) === Number(currentUserId.value)
})
})
// 分页后的数据
const paginatedData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return filteredResults.value.slice(start, end)
})
// 获取售后列表
const fetchData = async () => {
loading.value = true loading.value = true
const res = await getServiceList() const params = {
page: page || currentPage.value,
pageSize: pageSize.value
}
const res = await getServiceList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -116,10 +113,15 @@ const handleSearch = async () => {
cancelAdd() cancelAdd()
} }
currentPage.value = 1
loading.value = true loading.value = true
const params = { const params = {
page: 1,
pageSize: pageSize.value,
handle_status: filterStatus.value || undefined handle_status: filterStatus.value || undefined
} }
// 只在有搜索内容时才添加搜索参数(与 user.vue 一致)
if (search.value) {
if (select.value === '1') { if (select.value === '1') {
params.id = Number(search.value) params.id = Number(search.value)
} else if (select.value === '2') { } else if (select.value === '2') {
@@ -129,9 +131,26 @@ const handleSearch = async () => {
} else if (select.value === '4') { } else if (select.value === '4') {
params.customer_name = search.value params.customer_name = search.value
} }
}
try {
const res = await getServiceList(params) const res = await getServiceList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} else {
console.warn('[service] handleSearch 响应异常:', res)
searchResults.value = []
total.value = 0
}
} catch (e) {
console.error('[service] handleSearch 请求失败:', e)
searchResults.value = []
total.value = 0
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -152,6 +171,18 @@ const clearSearch = () => {
resetSearch() resetSearch()
} }
// 双击行查看详情
const handleRowDblClick = (row) => {
currentDetail.value = { ...row }
showDetailDialog.value = true
}
// 关闭详情弹窗
const closeDetail = () => {
showDetailDialog.value = false
currentDetail.value = null
}
// 清空表单 // 清空表单
const resetForm = () => { const resetForm = () => {
form.customer_id = '' form.customer_id = ''
@@ -253,9 +284,10 @@ const cancelAdd = () => {
showSearchResults.value = true showSearchResults.value = true
} }
// 页码变化 // 页码变化(服务端分页:重新请求后端)
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
currentPage.value = val currentPage.value = val
fetchData(val)
} }
// 检查权限 // 检查权限
@@ -287,8 +319,8 @@ const canDeleteRow = (row) => {
class="service-search-with-select" @keyup.enter="handleSearch"> class="service-search-with-select" @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="编号" value="1" /> <el-option label="售后编号" value="1" />
<el-option label="客户ID" value="2" /> <el-option label="客户编号" value="2" />
<el-option label="客户姓名" value="4" /> <el-option label="客户姓名" value="4" />
<el-option label="反馈内容" value="3" /> <el-option label="反馈内容" value="3" />
</el-select> </el-select>
@@ -325,11 +357,11 @@ const canDeleteRow = (row) => {
<div v-else> <div v-else>
<div class="list-header"> <div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条记录</span> <span class="total-count">共找到 {{ total }} 条记录</span>
</div> </div>
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%"> <el-table :data="paginatedData" v-loading="loading" border style="width: 100%" @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="编号" width="70" /> <el-table-column prop="id" label="售后编号" width="90" />
<el-table-column prop="customer_name" label="客户" width="100"> <el-table-column prop="customer_name" label="客户" width="100">
<template #default="{ row }"> <template #default="{ row }">
{{ row.customer_name || row.customer_id }} {{ row.customer_name || row.customer_id }}
@@ -367,7 +399,7 @@ const canDeleteRow = (row) => {
<el-pagination <el-pagination
v-model:current-page="currentPage" v-model:current-page="currentPage"
:page-size="pageSize" :page-size="pageSize"
:total="filteredResults.length" :total="total"
layout="prev, pager, next" layout="prev, pager, next"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
@@ -377,6 +409,29 @@ const canDeleteRow = (row) => {
</div> </div>
</div> </div>
<!-- 售后详情弹窗 -->
<el-dialog v-model="showDetailDialog" title="售后详情" width="700px" @close="closeDetail">
<div v-if="currentDetail" class="detail-content">
<el-descriptions :column="2" border>
<el-descriptions-item label="售后编号">{{ currentDetail.id }}</el-descriptions-item>
<el-descriptions-item label="客户">{{ currentDetail.customer_name || currentDetail.customer_id }}</el-descriptions-item>
<el-descriptions-item label="业务员">{{ currentDetail.employee_name || currentDetail.employee_id || '—' }}</el-descriptions-item>
<el-descriptions-item label="处理状态">
<el-tag :type="statusMap[currentDetail.handle_status]">{{ currentDetail.handle_status }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="售后日期">{{ formatDate(currentDetail.service_date) }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ currentDetail.responsible_user_name || '—' }}</el-descriptions-item>
<el-descriptions-item label="反馈内容" :span="2">{{ currentDetail.feedback || '无' }}</el-descriptions-item>
<el-descriptions-item label="处理方式" :span="2">{{ currentDetail.handle_method || '无' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ currentDetail.remark || '无' }}</el-descriptions-item>
</el-descriptions>
</div>
<template #footer>
<el-button @click="closeDetail">关闭</el-button>
<el-button type="primary" @click="(() => { const d = currentDetail; closeDetail(); editService(d) })()" v-if="canOperate">编辑</el-button>
</template>
</el-dialog>
<!-- 新增/编辑售后表单 --> <!-- 新增/编辑售后表单 -->
<div v-if="showAddForm" class="service-info-label"> <div v-if="showAddForm" class="service-info-label">
<el-divider content-position="left">{{ isEditMode ? '编辑售后记录' : '新增售后' }}</el-divider> <el-divider content-position="left">{{ isEditMode ? '编辑售后记录' : '新增售后' }}</el-divider>
@@ -490,4 +545,12 @@ const canDeleteRow = (row) => {
padding-top: 15px; padding-top: 15px;
border-top: 1px solid #eee; border-top: 1px solid #eee;
} }
.clickable-row {
cursor: pointer;
}
.detail-content {
padding: 10px 0;
}
</style> </style>

View File

@@ -37,9 +37,10 @@ const currentDetail = ref(null)
// 分页相关 // 分页相关
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0)
// 供应商类型 // 供应商类型
const supplierTypes = ['原料', '包装', '设备'] const supplierTypes = ['原料', '包装', '设备']
onMounted(() => { onMounted(() => {
fetchData() fetchData()
@@ -51,24 +52,25 @@ watch([filterType, filterStatus], () => {
handleSearch() handleSearch()
}) })
// 监听搜索结果变化 // 分页后的数据服务端已分页searchResults 即为当前页数据)
watch(searchResults, () => { const paginatedData = computed(() => searchResults.value)
currentPage.value = 1
})
// 分页后的数据 // 获取供应商列表(服务端分页)
const paginatedData = computed(() => { const fetchData = async (page) => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return searchResults.value.slice(start, end)
})
// 获取供应商列表
const fetchData = async () => {
loading.value = true loading.value = true
const res = await getSupplierList() const params = {
page: page || currentPage.value,
pageSize: pageSize.value
}
const res = await getSupplierList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -83,6 +85,8 @@ const handleSearch = async () => {
loading.value = true loading.value = true
const params = { const params = {
page: currentPage.value,
pageSize: pageSize.value,
type: filterType.value || undefined, type: filterType.value || undefined,
status: filterStatus.value !== '' ? filterStatus.value : undefined status: filterStatus.value !== '' ? filterStatus.value : undefined
} }
@@ -96,7 +100,13 @@ const handleSearch = async () => {
} }
const res = await getSupplierList(params) const res = await getSupplierList(params)
if (res.code === 0 || res.code === 200) { if (res.code === 0 || res.code === 200) {
searchResults.value = res.data.list || res.data if (res.data && Array.isArray(res.data.list)) {
searchResults.value = res.data.list
total.value = res.data.total
} else if (Array.isArray(res.data)) {
searchResults.value = res.data
total.value = res.data.length
}
} }
showSearchResults.value = true showSearchResults.value = true
loading.value = false loading.value = false
@@ -217,9 +227,10 @@ const closeDetail = () => {
currentDetail.value = null currentDetail.value = null
} }
// 页码变化 // 页码变化(服务端分页:重新请求后端)
const handleCurrentChange = (val) => { const handleCurrentChange = (val) => {
currentPage.value = val currentPage.value = val
fetchData(val)
} }
// 检查权限 // 检查权限
@@ -239,8 +250,8 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
class="supplier-search-with-select" @keyup.enter="handleSearch"> class="supplier-search-with-select" @keyup.enter="handleSearch">
<template #prepend> <template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="ID" value="1" /> <el-option label="供应商编号" value="1" />
<el-option label="名称" value="2" /> <el-option label="供应商名称" value="2" />
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
@@ -277,12 +288,12 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<div v-else> <div v-else>
<div class="list-header"> <div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条记录</span> <span class="total-count">共找到 {{ total }} 条记录</span>
</div> </div>
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%" <el-table :data="paginatedData" v-loading="loading" border style="width: 100%"
@row-dblclick="handleRowDblClick" row-class-name="clickable-row"> @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="ID" width="70" /> <el-table-column prop="id" label="供应商编号" width="100" />
<el-table-column prop="name" label="供应商名称" min-width="150" /> <el-table-column prop="name" label="供应商名称" min-width="150" />
<el-table-column prop="contact" label="联系人" width="100" /> <el-table-column prop="contact" label="联系人" width="100" />
<el-table-column prop="phone" label="联系电话" width="130" /> <el-table-column prop="phone" label="联系电话" width="130" />
@@ -312,7 +323,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<el-pagination <el-pagination
v-model:current-page="currentPage" v-model:current-page="currentPage"
:page-size="pageSize" :page-size="pageSize"
:total="searchResults.length" :total="total"
layout="prev, pager, next" layout="prev, pager, next"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
@@ -335,7 +346,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
</el-form-item> </el-form-item>
<el-form-item label="联系电话"> <el-form-item label="联系电话">
<el-input v-model="form.phone" placeholder="请输入联系电话" /> <el-input v-model="form.phone" placeholder="请输入联系电话" type="tel" maxlength="11" oninput="this.value=this.value.replace(/\D/g,'')" />
</el-form-item> </el-form-item>
<el-form-item label="地址"> <el-form-item label="地址">
@@ -370,7 +381,7 @@ const canOperate = computed(() => canUpdate.value || canDelete.value)
<el-dialog v-model="showDetailDialog" title="供应商详情" width="650px" @close="closeDetail"> <el-dialog v-model="showDetailDialog" title="供应商详情" width="650px" @close="closeDetail">
<div v-if="currentDetail" class="detail-content"> <div v-if="currentDetail" class="detail-content">
<el-descriptions :column="2" border> <el-descriptions :column="2" border>
<el-descriptions-item label="供应商ID">{{ currentDetail.id }}</el-descriptions-item> <el-descriptions-item label="供应商编号">{{ currentDetail.id }}</el-descriptions-item>
<el-descriptions-item label="供应商名称">{{ currentDetail.name }}</el-descriptions-item> <el-descriptions-item label="供应商名称">{{ currentDetail.name }}</el-descriptions-item>
<el-descriptions-item label="联系人">{{ currentDetail.contact || '无' }}</el-descriptions-item> <el-descriptions-item label="联系人">{{ currentDetail.contact || '无' }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ currentDetail.phone || '无' }}</el-descriptions-item> <el-descriptions-item label="联系电话">{{ currentDetail.phone || '无' }}</el-descriptions-item>

View File

@@ -281,7 +281,7 @@ const canManage = computed(() => hasPermission('user', 'manage'))
<el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="用户名" value="1" /> <el-option label="用户名" value="1" />
<el-option label="真实姓名" value="2" /> <el-option label="真实姓名" value="2" />
<el-option label="ID" value="3" /> <el-option label="用户编号" value="3" />
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
@@ -323,7 +323,7 @@ const canManage = computed(() => hasPermission('user', 'manage'))
<el-table :data="paginatedData" v-loading="loading" border style="width: 100%" <el-table :data="paginatedData" v-loading="loading" border style="width: 100%"
@row-dblclick="handleRowDblClick" row-class-name="clickable-row"> @row-dblclick="handleRowDblClick" row-class-name="clickable-row">
<el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="id" label="用户编号" width="90" />
<el-table-column prop="username" label="用户名" width="120" /> <el-table-column prop="username" label="用户名" width="120" />
<el-table-column prop="real_name" label="真实姓名" min-width="120"> <el-table-column prop="real_name" label="真实姓名" min-width="120">
<template #default="{ row }"> <template #default="{ row }">
@@ -414,7 +414,7 @@ const canManage = computed(() => hasPermission('user', 'manage'))
<el-dialog v-model="showDetailDialog" title="用户详情" width="550px" @close="closeDetail"> <el-dialog v-model="showDetailDialog" title="用户详情" width="550px" @close="closeDetail">
<div v-if="currentDetail" class="detail-content"> <div v-if="currentDetail" class="detail-content">
<el-descriptions :column="2" border> <el-descriptions :column="2" border>
<el-descriptions-item label="用户ID">{{ currentDetail.id }}</el-descriptions-item> <el-descriptions-item label="用户编号">{{ currentDetail.id }}</el-descriptions-item>
<el-descriptions-item label="用户名">{{ currentDetail.username }}</el-descriptions-item> <el-descriptions-item label="用户名">{{ currentDetail.username }}</el-descriptions-item>
<el-descriptions-item label="真实姓名">{{ currentDetail.real_name || '-' }}</el-descriptions-item> <el-descriptions-item label="真实姓名">{{ currentDetail.real_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="部门">{{ currentDetail.dept_desc || '-' }}</el-descriptions-item> <el-descriptions-item label="部门">{{ currentDetail.dept_desc || '-' }}</el-descriptions-item>