refactor(developer-config): 移除开发者配置页面相关代码和文档
- 删除应用配置页面及相关组件,重构路由为 /developer/config/[id].vue - 移除开发者文档页面及其导航与样式实现 - 清理开发者侧功能完善工作日志文件 - 删除全局.gitignore配置文件,清理无用忽略规则 - 优化应用配置页面的参数读取和路由结构,解决刷新404问题 - 解决数据库配置唯一键冲突,调整保存逻辑避免重复插入 - 移除对后端配置加密字段的 secret 标记,修正加密异常问题
This commit is contained in:
352
app/pages/admin/product/design.vue
Normal file
352
app/pages/admin/product/design.vue
Normal file
@@ -0,0 +1,352 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'admin' })
|
||||
|
||||
const { activeTab } = useNav()
|
||||
activeTab.value = 'product-design'
|
||||
|
||||
// 产品数据
|
||||
const products = ref([
|
||||
{ id: 'PD-001', name: '精密轴承组件 A型', code: 'BA-A-001', category: '轴承类', version: 'V2.1', status: '设计中', progress: 75, designer: '张工', updateTime: '2026-04-08' },
|
||||
{ id: 'PD-002', name: '液压缸体 B型', code: 'HA-B-002', category: '液压类', version: 'V1.5', status: '评审中', progress: 90, designer: '李工', updateTime: '2026-04-07' },
|
||||
{ id: 'PD-003', name: '传动齿轮组 C型', code: 'GA-C-003', category: '传动类', version: 'V3.0', status: '已发布', progress: 100, designer: '王工', updateTime: '2026-04-01' },
|
||||
{ id: 'PD-004', name: '密封圈组件 D型', code: 'SA-D-004', category: '密封类', version: 'V1.2', status: '设计中', progress: 45, designer: '赵工', updateTime: '2026-04-09' },
|
||||
{ id: 'PD-005', name: '弹簧组件 E型', code: 'SA-E-005', category: '弹簧类', version: 'V2.0', status: '已发布', progress: 100, designer: '张工', updateTime: '2026-03-28' },
|
||||
])
|
||||
|
||||
const statusMap: Record<string, string> = {
|
||||
'设计中': 'processing',
|
||||
'评审中': 'warning',
|
||||
'已发布': 'success',
|
||||
}
|
||||
|
||||
// 设计任务
|
||||
const designTasks = ref([
|
||||
{ id: 1, task: '优化轴承组件公差设计', assignee: '张工', deadline: '2026-04-15', priority: 'high' },
|
||||
{ id: 2, task: '完成缸体3D建模', assignee: '李工', deadline: '2026-04-12', priority: 'medium' },
|
||||
{ id: 3, task: '齿轮强度校核报告', assignee: '王工', deadline: '2026-04-10', priority: 'high' },
|
||||
{ id: 4, task: '密封圈材料选型', assignee: '赵工', deadline: '2026-04-18', priority: 'low' },
|
||||
])
|
||||
|
||||
const priorityMap: Record<string, string> = {
|
||||
high: 'error',
|
||||
medium: 'warning',
|
||||
low: 'default',
|
||||
}
|
||||
|
||||
// BOM 清单
|
||||
const bomItems = ref([
|
||||
{ no: 1, code: 'BA-A-001-01', name: '外圈', material: 'GCr15', qty: 2, unit: '件', supplier: '洛阳轴承' },
|
||||
{ no: 2, code: 'BA-A-001-02', name: '内圈', material: 'GCr15', qty: 2, unit: '件', supplier: '洛阳轴承' },
|
||||
{ no: 3, code: 'BA-A-001-03', name: '滚动体', material: 'Si3N4', qty: 12, unit: '件', supplier: '日本精工' },
|
||||
{ no: 4, code: 'BA-A-001-04', name: '保持架', material: 'PA66', qty: 1, unit: '件', supplier: '本地供应商' },
|
||||
])
|
||||
|
||||
const selectedProduct = ref<any>(null)
|
||||
const showBomModal = ref(false)
|
||||
|
||||
const viewBom = (product: any) => {
|
||||
selectedProduct.value = product
|
||||
showBomModal.value = true
|
||||
}
|
||||
|
||||
const modal = reactive({ visible: false, title: '', record: null as any })
|
||||
|
||||
const openModal = (title: string, record?: any) => {
|
||||
modal.title = title
|
||||
modal.record = record || {}
|
||||
modal.visible = true
|
||||
}
|
||||
|
||||
const statusFilter = ref<string[]>([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">产品设计</h2>
|
||||
<a-button type="primary" @click="openModal('新增产品')">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建产品
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<a-row :gutter="[20, 20]">
|
||||
<a-col :xs="24" :xl="16">
|
||||
<!-- 产品列表 -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">产品设计列表</span>
|
||||
<a-select
|
||||
v-model:value="statusFilter"
|
||||
mode="multiple"
|
||||
placeholder="筛选状态"
|
||||
style="width: 200px"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option value="设计中">设计中</a-select-option>
|
||||
<a-select-option value="评审中">评审中</a-select-option>
|
||||
<a-select-option value="已发布">已发布</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<a-table
|
||||
:dataSource="products"
|
||||
:pagination="{ pageSize: 10 }"
|
||||
size="small"
|
||||
rowKey="id"
|
||||
>
|
||||
<a-table-column title="产品编号" dataIndex="id" width="100" />
|
||||
<a-table-column title="产品名称" dataIndex="name">
|
||||
<template #default="{ record }">
|
||||
<a @click="viewBom(record)" class="link">{{ record.name }}</a>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="产品编码" dataIndex="code" width="120" />
|
||||
<a-table-column title="类别" dataIndex="category" width="100" />
|
||||
<a-table-column title="版本" dataIndex="version" width="80" />
|
||||
<a-table-column title="状态" dataIndex="status" width="100" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-tag :color="statusMap[text]">{{ text }}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="设计进度" dataIndex="progress" width="140" align="center">
|
||||
<template #default="{ record }">
|
||||
<a-progress :percent="record.progress" size="small" :showInfo="false" />
|
||||
<span class="text-xs text-gray-400 ml-2">{{ record.progress }}%</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="负责人" dataIndex="designer" width="80" align="center" />
|
||||
<a-table-column title="更新时间" dataIndex="updateTime" width="110" />
|
||||
<a-table-column title="操作" width="120" align="center" fixed="right">
|
||||
<template #default="{ record }">
|
||||
<a-space>
|
||||
<a @click="openModal('编辑产品', record)">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm title="确认删除?" ok-text="确认" cancel-text="取消">
|
||||
<a class="danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-col>
|
||||
|
||||
<a-col :xs="24" :xl="8">
|
||||
<!-- 设计任务 -->
|
||||
<div class="card mb-6">
|
||||
<div class="card-header">
|
||||
<span class="card-title">设计任务</span>
|
||||
<a-button type="link" size="small">全部</a-button>
|
||||
</div>
|
||||
<div class="task-list">
|
||||
<div v-for="task in designTasks" :key="task.id" class="task-item">
|
||||
<div class="task-header">
|
||||
<span class="task-name">{{ task.task }}</span>
|
||||
<a-tag :color="priorityMap[task.priority]" size="small">
|
||||
{{ task.priority === 'high' ? '高' : task.priority === 'medium' ? '中' : '低' }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div class="task-meta">
|
||||
<span><UserOutlined /> {{ task.assignee }}</span>
|
||||
<span><CalendarOutlined /> {{ task.deadline }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 设计统计 -->
|
||||
<div class="card">
|
||||
<div class="card-title">设计统计</div>
|
||||
<div class="stat-row">
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">12</span>
|
||||
<span class="stat-lbl">设计中</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">5</span>
|
||||
<span class="stat-lbl">评审中</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">28</span>
|
||||
<span class="stat-lbl">已发布</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- BOM 弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="showBomModal"
|
||||
:title="`BOM清单 - ${selectedProduct?.name || ''}`"
|
||||
width="700px"
|
||||
:footer="null"
|
||||
>
|
||||
<a-table
|
||||
:dataSource="bomItems"
|
||||
:pagination="false"
|
||||
size="small"
|
||||
rowKey="no"
|
||||
>
|
||||
<a-table-column title="序号" dataIndex="no" width="60" align="center" />
|
||||
<a-table-column title="物料编码" dataIndex="code" width="130" />
|
||||
<a-table-column title="物料名称" dataIndex="name" />
|
||||
<a-table-column title="材质" dataIndex="material" width="100" />
|
||||
<a-table-column title="用量" dataIndex="qty" width="60" align="center" />
|
||||
<a-table-column title="单位" dataIndex="unit" width="60" align="center" />
|
||||
<a-table-column title="供应商" dataIndex="supplier" />
|
||||
</a-table>
|
||||
</a-modal>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="modal.visible"
|
||||
:title="modal.title"
|
||||
width="500px"
|
||||
@ok="modal.visible = false"
|
||||
>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="产品名称">
|
||||
<a-input v-model:value="modal.record.name" placeholder="请输入产品名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="产品编码">
|
||||
<a-input v-model:value="modal.record.code" placeholder="请输入产品编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="产品类别">
|
||||
<a-select v-model:value="modal.record.category" placeholder="请选择类别">
|
||||
<a-select-option value="轴承类">轴承类</a-select-option>
|
||||
<a-select-option value="液压类">液压类</a-select-option>
|
||||
<a-select-option value="传动类">传动类</a-select-option>
|
||||
<a-select-option value="密封类">密封类</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="负责人">
|
||||
<a-select v-model:value="modal.record.designer" placeholder="请选择负责人">
|
||||
<a-select-option value="张工">张工</a-select-option>
|
||||
<a-select-option value="李工">李工</a-select-option>
|
||||
<a-select-option value="王工">王工</a-select-option>
|
||||
<a-select-option value="赵工">赵工</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
padding: 12px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.task-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.task-name {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.task-meta {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.task-meta span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-num {
|
||||
display: block;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
.stat-lbl {
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #4f46e5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.danger {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.mb-6 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
169
app/pages/admin/product/marketing.vue
Normal file
169
app/pages/admin/product/marketing.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'admin' })
|
||||
const { activeTab } = useNav()
|
||||
activeTab.value = 'product-marketing'
|
||||
|
||||
// 销售数据
|
||||
const salesData = ref([
|
||||
{ month: '1月', orders: 245, revenue: 128.5, target: 120 },
|
||||
{ month: '2月', orders: 312, revenue: 156.8, target: 130 },
|
||||
{ month: '3月', orders: 278, revenue: 142.3, target: 135 },
|
||||
])
|
||||
|
||||
const stats = ref([
|
||||
{ label: '本月订单', value: 156, unit: '单', change: '+12%', icon: '📋', color: '#6366f1' },
|
||||
{ label: '本月营收', value: 86.5, unit: '万', change: '+8%', icon: '💰', color: '#10b981' },
|
||||
{ label: '新增客户', value: 23, unit: '家', change: '+15%', icon: '🏢', color: '#f59e0b' },
|
||||
{ label: '平均单价', value: 5546, unit: '元', change: '-2%', icon: '💎', color: '#3b82f6' },
|
||||
])
|
||||
|
||||
// 客户列表
|
||||
const customers = ref([
|
||||
{ id: 'C001', name: '比亚迪股份有限公司', industry: '汽车制造', contact: '李经理', phone: '0755-89888888', orderCount: 45, amount: 280.5, status: 'VIP' },
|
||||
{ id: 'C002', name: '宁德时代新能源', industry: '新能源', contact: '王经理', phone: '0591-87654321', orderCount: 32, amount: 198.2, status: 'VIP' },
|
||||
{ id: 'C003', name: '华为技术有限公司', industry: '电子通信', contact: '张经理', phone: '0755-28780808', orderCount: 28, amount: 156.8, status: '重点' },
|
||||
{ id: 'C004', name: '富士康科技集团', industry: '电子制造', contact: '刘经理', phone: '0755-28129999', orderCount: 21, amount: 125.3, status: '普通' },
|
||||
{ id: 'C005', name: '美的集团', industry: '家电制造', contact: '陈经理', phone: '0757-26608888', orderCount: 18, amount: 98.6, status: '重点' },
|
||||
])
|
||||
|
||||
// 跟进记录
|
||||
const followRecords = ref([
|
||||
{ id: 1, customer: '比亚迪股份有限公司', content: '拜访客户,沟通轴承采购需求,预计月订单量增加30%', contact: '李经理', nextDate: '2026-04-15', status: '跟进中' },
|
||||
{ id: 2, customer: '宁德时代新能源', content: '技术方案对接完成,等待客户内部评审', contact: '王经理', nextDate: '2026-04-12', status: '待联系' },
|
||||
{ id: 3, customer: '华为技术有限公司', content: '完成样品交付,客户反馈良好', contact: '张经理', nextDate: '-', status: '已完成' },
|
||||
])
|
||||
|
||||
const statusColor: Record<string, string> = {
|
||||
'VIP': 'purple',
|
||||
'重点': 'blue',
|
||||
'普通': 'default',
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">营销管理</h2>
|
||||
<a-space>
|
||||
<a-button @click="() => {}">导出数据</a-button>
|
||||
<a-button type="primary" @click="() => {}">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建客户
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<a-row :gutter="[16, 16]" class="mb-6">
|
||||
<a-col :xs="12" :sm="6" v-for="stat in stats" :key="stat.label">
|
||||
<div class="stat-card" :style="{ '--accent': stat.color }">
|
||||
<div class="stat-icon">{{ stat.icon }}</div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-value">{{ stat.value }}<span class="stat-unit">{{ stat.unit }}</span></div>
|
||||
<div class="stat-label">{{ stat.label }}</div>
|
||||
<div :class="['stat-change', stat.change.startsWith('+') ? 'up' : 'down']">{{ stat.change }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="[20, 20]">
|
||||
<a-col :xs="24" :xl="16">
|
||||
<!-- 客户列表 -->
|
||||
<div class="card">
|
||||
<div class="card-title">客户列表</div>
|
||||
<a-table :dataSource="customers" :pagination="{ pageSize: 8 }" size="small" rowKey="id">
|
||||
<a-table-column title="客户编码" dataIndex="id" width="90" />
|
||||
<a-table-column title="客户名称" dataIndex="name" />
|
||||
<a-table-column title="行业" dataIndex="industry" width="100" />
|
||||
<a-table-column title="联系人" dataIndex="contact" width="80" />
|
||||
<a-table-column title="订单数" dataIndex="orderCount" width="80" align="center" />
|
||||
<a-table-column title="累计金额(万)" dataIndex="amount" width="110" align="right" />
|
||||
<a-table-column title="等级" dataIndex="status" width="80" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-tag :color="statusColor[text]">{{ text }}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="操作" width="100" align="center">
|
||||
<template #default>
|
||||
<a-space>
|
||||
<a>详情</a>
|
||||
<a-divider type="vertical" />
|
||||
<a>跟进</a>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-col>
|
||||
|
||||
<a-col :xs="24" :xl="8">
|
||||
<!-- 跟进记录 -->
|
||||
<div class="card">
|
||||
<div class="card-title">跟进记录</div>
|
||||
<div class="follow-list">
|
||||
<div v-for="record in followRecords" :key="record.id" class="follow-item">
|
||||
<div class="follow-header">
|
||||
<span class="follow-customer">{{ record.customer }}</span>
|
||||
<a-tag size="small" :color="record.status === '已完成' ? 'success' : record.status === '跟进中' ? 'processing' : 'warning'">
|
||||
{{ record.status }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div class="follow-content">{{ record.content }}</div>
|
||||
<div class="follow-meta">
|
||||
<span><UserOutlined /> {{ record.contact }}</span>
|
||||
<span v-if="record.nextDate !== '-'"><CalendarOutlined /> 下次: {{ record.nextDate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page-container { padding: 24px; }
|
||||
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
||||
.page-title { font-size: 20px; font-weight: 600; color: #1f2937; margin: 0; }
|
||||
|
||||
.stat-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
||||
border: 1px solid #f0f0f0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.stat-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 4px; height: 100%;
|
||||
background: var(--accent);
|
||||
}
|
||||
.stat-icon { font-size: 28px; }
|
||||
.stat-value { font-size: 22px; font-weight: 700; color: #1f2937; }
|
||||
.stat-unit { font-size: 12px; color: #9ca3af; margin-left: 2px; }
|
||||
.stat-label { font-size: 12px; color: #9ca3af; margin: 2px 0; }
|
||||
.stat-change { font-size: 12px; }
|
||||
.stat-change.up { color: #10b981; }
|
||||
.stat-change.down { color: #ef4444; }
|
||||
|
||||
.card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); border: 1px solid #f0f0f0; }
|
||||
.card-title { font-size: 16px; font-weight: 600; color: #1f2937; margin-bottom: 16px; }
|
||||
|
||||
.follow-list { display: flex; flex-direction: column; gap: 12px; }
|
||||
.follow-item { padding: 12px; background: #fafafa; border-radius: 8px; }
|
||||
.follow-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
|
||||
.follow-customer { font-size: 13px; font-weight: 600; color: #374151; }
|
||||
.follow-content { font-size: 12px; color: #6b7280; margin-bottom: 8px; line-height: 1.5; }
|
||||
.follow-meta { display: flex; gap: 16px; font-size: 11px; color: #9ca3af; }
|
||||
.follow-meta span { display: flex; align-items: center; gap: 4px; }
|
||||
|
||||
.mb-6 { margin-bottom: 20px; }
|
||||
</style>
|
||||
127
app/pages/admin/product/service.vue
Normal file
127
app/pages/admin/product/service.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'admin' })
|
||||
const { activeTab } = useNav()
|
||||
activeTab.value = 'product-service'
|
||||
|
||||
const activeTabKey = ref('tickets')
|
||||
|
||||
const tabs = [
|
||||
{ key: 'tickets', label: '服务工单' },
|
||||
{ key: 'feedback', label: '客户反馈' },
|
||||
{ key: 'warranty', label: '质保管理' },
|
||||
]
|
||||
|
||||
// 服务工单
|
||||
const tickets = ref([
|
||||
{ id: 'ST-2026040901', customer: '比亚迪股份有限公司', product: '精密轴承组件 A型', type: '技术支持', status: '处理中', assignee: '张工', createTime: '2026-04-09 10:30', urgent: 'high' },
|
||||
{ id: 'ST-2026040802', customer: '宁德时代新能源', product: '液压缸体 B型', type: '故障报修', status: '待派单', assignee: '-', createTime: '2026-04-08 15:20', urgent: 'medium' },
|
||||
{ id: 'ST-2026040801', customer: '华为技术有限公司', product: '传动齿轮组 C型', type: '咨询', status: '已完成', assignee: '李工', createTime: '2026-04-08 09:15', urgent: 'low' },
|
||||
{ id: 'ST-2026040703', customer: '美的集团', product: '密封圈组件 D型', type: '技术支持', status: '已完成', assignee: '王工', createTime: '2026-04-07 14:00', urgent: 'medium' },
|
||||
])
|
||||
|
||||
const statusColor: Record<string, string> = { '处理中': 'processing', '待派单': 'warning', '已完成': 'success' }
|
||||
const urgentColor: Record<string, string> = { 'high': 'error', 'medium': 'warning', 'low': 'default' }
|
||||
const urgentLabel: Record<string, string> = { 'high': '紧急', 'medium': '普通', 'low': '低' }
|
||||
|
||||
// 客户反馈
|
||||
const feedback = ref([
|
||||
{ id: 'FB-001', customer: '比亚迪股份有限公司', content: '产品性能稳定,交付及时,服务态度好', rating: 5, createTime: '2026-04-08' },
|
||||
{ id: 'FB-002', customer: '宁德时代新能源', content: '希望增加技术培训频次', rating: 4, createTime: '2026-04-07' },
|
||||
{ id: 'FB-003', customer: '华为技术有限公司', content: '产品质量可靠,但包装可以改进', rating: 4, createTime: '2026-04-06' },
|
||||
{ id: 'FB-004', customer: '富士康科技集团', content: '技术响应速度需要提升', rating: 3, createTime: '2026-04-05' },
|
||||
])
|
||||
|
||||
// 质保列表
|
||||
const warranty = ref([
|
||||
{ id: 'WA-001', product: '精密轴承组件 A型', batch: 'B-20260301-01', quantity: 500, warrantyPeriod: '2年', expireDate: '2028-03-01', status: '有效' },
|
||||
{ id: 'WA-002', product: '液压缸体 B型', batch: 'B-20260215-02', quantity: 200, warrantyPeriod: '1年', expireDate: '2027-02-15', status: '有效' },
|
||||
{ id: 'WA-003', product: '传动齿轮组 C型', batch: 'B-20251201-03', quantity: 1000, warrantyPeriod: '2年', expireDate: '2027-12-01', status: '即将到期' },
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">售后服务</h2>
|
||||
<a-button type="primary">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建工单
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<a-tabs v-model:activeKey="activeTabKey">
|
||||
<a-tab-pane key="tickets" tab="服务工单">
|
||||
<div class="card">
|
||||
<a-table :dataSource="tickets" :pagination="{ pageSize: 10 }" size="small" rowKey="id">
|
||||
<a-table-column title="工单编号" dataIndex="id" width="150" />
|
||||
<a-table-column title="客户" dataIndex="customer" />
|
||||
<a-table-column title="产品" dataIndex="product" />
|
||||
<a-table-column title="类型" dataIndex="type" width="100" align="center" />
|
||||
<a-table-column title="紧急度" dataIndex="urgent" width="90" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-tag :color="urgentColor[text]">{{ urgentLabel[text] }}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="状态" dataIndex="status" width="100" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-badge :status="statusColor[text] === 'processing' ? 'processing' : statusColor[text] === 'success' ? 'success' : 'warning'" :text="text" />
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="处理人" dataIndex="assignee" width="80" align="center" />
|
||||
<a-table-column title="创建时间" dataIndex="createTime" width="150" />
|
||||
<a-table-column title="操作" width="100" align="center">
|
||||
<template #default>
|
||||
<a>详情</a>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane key="feedback" tab="客户反馈">
|
||||
<div class="card">
|
||||
<a-table :dataSource="feedback" :pagination="{ pageSize: 10 }" size="small" rowKey="id">
|
||||
<a-table-column title="反馈编号" dataIndex="id" width="100" />
|
||||
<a-table-column title="客户" dataIndex="customer" />
|
||||
<a-table-column title="反馈内容" dataIndex="content" />
|
||||
<a-table-column title="评分" dataIndex="rating" width="120" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-rate :value="text" disabled :tooltips="['很差', '较差', '一般', '满意', '非常满意']" />
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="时间" dataIndex="createTime" width="120" />
|
||||
</a-table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane key="warranty" tab="质保管理">
|
||||
<div class="card">
|
||||
<a-table :dataSource="warranty" :pagination="false" size="small" rowKey="id">
|
||||
<a-table-column title="产品名称" dataIndex="product" />
|
||||
<a-table-column title="批次号" dataIndex="batch" width="160" />
|
||||
<a-table-column title="数量" dataIndex="quantity" width="80" align="center" />
|
||||
<a-table-column title="质保期" dataIndex="warrantyPeriod" width="90" align="center" />
|
||||
<a-table-column title="到期日期" dataIndex="expireDate" width="120" />
|
||||
<a-table-column title="状态" dataIndex="status" width="100" align="center">
|
||||
<template #default="{ text }">
|
||||
<a-tag :color="text === '有效' ? 'success' : 'warning'">{{ text }}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="操作" width="100" align="center">
|
||||
<template #default>
|
||||
<a>详情</a>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page-container { padding: 24px; }
|
||||
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
||||
.page-title { font-size: 20px; font-weight: 600; color: #1f2937; margin: 0; }
|
||||
.card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); border: 1px solid #f0f0f0; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user