Files
tiantian-system/app/pages/admin/product/marketing.vue
赵忠林 f9e1286ab1 refactor(developer-config): 移除开发者配置页面相关代码和文档
- 删除应用配置页面及相关组件,重构路由为 /developer/config/[id].vue
- 移除开发者文档页面及其导航与样式实现
- 清理开发者侧功能完善工作日志文件
- 删除全局.gitignore配置文件,清理无用忽略规则
- 优化应用配置页面的参数读取和路由结构,解决刷新404问题
- 解决数据库配置唯一键冲突,调整保存逻辑避免重复插入
- 移除对后端配置加密字段的 secret 标记,修正加密异常问题
2026-04-09 07:35:34 +08:00

170 lines
7.4 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>