主页V2
This commit is contained in:
parent
a60e56d4c8
commit
2895ee40c0
@ -390,7 +390,7 @@ const local: App.I18n.Schema = {
|
||||
home: {
|
||||
branchDesc:
|
||||
'为了方便大家开发和更新合并,我们对main分支的代码进行了精简,只保留了首页菜单,其余内容已移至example分支进行维护。预览地址显示的内容即为example分支的内容。',
|
||||
greeting: '早安,{userName}, 今天又是充满活力的一天!',
|
||||
greeting: '您好,{userName}, 今天又是充满活力的一天!',
|
||||
weatherDesc: '今日多云转晴,20℃ - 25℃!',
|
||||
projectCount: '项目数',
|
||||
todo: '待办',
|
||||
|
||||
@ -1,68 +1,272 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import HeaderBanner from './modules/header-banner.vue';
|
||||
import CardData from './modules/card-data.vue';
|
||||
import CardDataSummary from './modules/card-data-summary.vue';
|
||||
import CardDataMkt from './modules/card-data-mkt.vue';
|
||||
import LineChart from './modules/line-chart.vue';
|
||||
import LineChartSummary from './modules/line-chart-summary.vue';
|
||||
import LineChartMkt from './modules/line-chart-mkt.vue';
|
||||
import PieChart from './modules/pie-chart.vue';
|
||||
import PieChartSummary from './modules/pie-chart-summary.vue';
|
||||
import PieChartMkt from './modules/pie-chart-mkt.vue';
|
||||
import ProjectNews from './modules/project-news.vue';
|
||||
import CreativityBanner from './modules/creativity-banner.vue';
|
||||
import { useAuthStore } from "@/store/modules/auth";
|
||||
import dayjs from 'dayjs';
|
||||
import { computed, onMounted, ref, watch, h } from 'vue' // 添加 h 导入
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import HeaderBanner from './modules/header-banner.vue'
|
||||
//import CardData from './modules/card-data.vue'
|
||||
import CardDataSummary from './modules/card-data-summary.vue'
|
||||
import CardDataMkt from './modules/card-data-mkt.vue'
|
||||
//import ProjectNews from './modules/project-news.vue'
|
||||
//import CreativityBanner from './modules/creativity-banner.vue'
|
||||
import { useAuthStore } from "@/store/modules/auth"
|
||||
import {
|
||||
NButton,
|
||||
NCard,
|
||||
NStatistic,
|
||||
NDataTable,
|
||||
NTag,
|
||||
NDivider,
|
||||
NH1,
|
||||
NH2,
|
||||
NP,
|
||||
NNumberAnimation,
|
||||
NProgress,
|
||||
NGrid,
|
||||
NGi,
|
||||
NSpace,
|
||||
NIcon,
|
||||
NThing
|
||||
} from 'naive-ui'
|
||||
|
||||
const appStore = useAppStore();
|
||||
const { userInfo } = useAuthStore();
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const gap = computed(() => (appStore.isMobile ? 0 : 16));
|
||||
const appStore = useAppStore()
|
||||
const { userInfo } = useAuthStore()
|
||||
|
||||
const gap = computed(() => (appStore.isMobile ? 0 : 16))
|
||||
|
||||
//是否管理用户
|
||||
let isAdmin = ref(false);
|
||||
|
||||
// 初始设置为本月范围
|
||||
const dateRange = ref<[number, number]>([
|
||||
dayjs().startOf('month').valueOf(), // 本月第一天
|
||||
dayjs().endOf('month').valueOf() // 本月最后一天
|
||||
]);
|
||||
])
|
||||
|
||||
// 处理日期变化
|
||||
const handleDateChange = (range: [number, number]) => {
|
||||
dateRange.value = range;
|
||||
};
|
||||
dateRange.value = range
|
||||
}
|
||||
|
||||
// 设置快速日期范围
|
||||
const setDateRange = (type: 'today' | 'week' | 'month') => {
|
||||
let start, end;
|
||||
let start, end
|
||||
|
||||
switch (type) {
|
||||
case 'today':
|
||||
start = dayjs().startOf('day');
|
||||
end = dayjs().endOf('day');
|
||||
break;
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
break
|
||||
case 'week':
|
||||
start = dayjs().startOf('week');
|
||||
end = dayjs().endOf('week');
|
||||
break;
|
||||
start = dayjs().startOf('week')
|
||||
end = dayjs().endOf('week')
|
||||
break
|
||||
case 'month':
|
||||
start = dayjs().startOf('month');
|
||||
end = dayjs().endOf('month');
|
||||
break;
|
||||
start = dayjs().startOf('month')
|
||||
end = dayjs().endOf('month')
|
||||
break
|
||||
default:
|
||||
start = dayjs().startOf('day');
|
||||
end = dayjs().endOf('day');
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
}
|
||||
|
||||
dateRange.value = [start.valueOf(), end.valueOf()];
|
||||
};
|
||||
dateRange.value = [start.valueOf(), end.valueOf()]
|
||||
}
|
||||
|
||||
//测试登录用户信息
|
||||
/*onMounted(() => {
|
||||
console.log(JSON.stringify(userInfo));
|
||||
console.log("是否营销:" + userInfo.user.userCategory);
|
||||
console.log("营销编号:" + userInfo.user.mktNo);
|
||||
});*/
|
||||
// 营销用户数据
|
||||
/*const marketingData = ref({
|
||||
performance: {
|
||||
totalAmount: 128456.78,
|
||||
completedProjects: 24,
|
||||
pendingProjects: 5,
|
||||
successRate: 92.5,
|
||||
growthRate: 12.5
|
||||
},
|
||||
pricingResults: [
|
||||
{ id: 1, project: '品牌推广活动', amount: 24500.00, status: '已完成', date: '2023-10-15' },
|
||||
{ id: 2, project: '社交媒体营销', amount: 18700.50, status: '进行中', date: '2023-10-18' },
|
||||
{ id: 3, project: '季度促销活动', amount: 35600.00, status: '待审核', date: '2023-10-20' },
|
||||
{ id: 4, project: '新产品发布会', amount: 28900.00, status: '已完成', date: '2023-10-22' }
|
||||
],
|
||||
errorResults: [
|
||||
{ id: 1, project: '品牌推广活动', errorType: '数据不一致', status: '已处理', date: '2023-10-16' },
|
||||
{ id: 2, project: '社交媒体营销', errorType: '计算错误', status: '待处理', date: '2023-10-19' },
|
||||
{ id: 3, project: '季度促销活动', errorType: '规则冲突', status: '处理中', date: '2023-10-21' }
|
||||
]
|
||||
})*/
|
||||
|
||||
// 当用户是管理用户时,登陆后即异步查询所有用户信息
|
||||
// 当用户是营销用户时,登录后即异步查询自己的信息
|
||||
const adminData = ref({
|
||||
//查询 按照业务类型查询计价金额汇总,取最大4条+其他汇总成一条
|
||||
pricingSummary: [
|
||||
],
|
||||
//查询 营销表、业务规则表、其他必要表,按照创建时间和修改时间排序,取最新5条
|
||||
recentActivities: [
|
||||
]
|
||||
})
|
||||
|
||||
// 计价结果表格列
|
||||
/*const pricingColumns = [
|
||||
{
|
||||
title: '项目名称',
|
||||
key: 'project',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'project-cell' }, [
|
||||
h('div', { class: 'project-name' }, row.project),
|
||||
h('div', { class: 'project-date' }, row.date)
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-cell' }, row.amount.toLocaleString('zh-CN', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}))
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已完成' ? 'success' :
|
||||
row.status === '进行中' ? 'warning' : 'default'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]*/
|
||||
|
||||
// 差错结果表格列
|
||||
/*const errorColumns = [
|
||||
{ title: '项目名称', key: 'project' },
|
||||
{ title: '差错类型', key: 'errorType' },
|
||||
{
|
||||
title: '处理状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已处理' ? 'success' :
|
||||
row.status === '处理中' ? 'warning' : 'error'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]*/
|
||||
|
||||
// 汇总数据表格列
|
||||
const summaryColumns = [
|
||||
{ title: '业务类别', key: 'category' },
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-with-trend' }, [
|
||||
h('span', row.amount.toLocaleString('zh-CN')),
|
||||
h(NIcon, {
|
||||
size: '16',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050',
|
||||
style: { 'margin-left': '8px' }
|
||||
}, { default: () => '元' })
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '占比',
|
||||
key: 'percentage',
|
||||
render: (row: any) => {
|
||||
return h(NProgress, {
|
||||
type: 'line',
|
||||
percentage: row.percentage,
|
||||
'indicator-placement': 'inside',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 活动记录表格列
|
||||
const activityColumns = [
|
||||
{
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'user-cell' }, [
|
||||
/*h(NIcon, { size: '16', style: { 'margin-right': '8px' } }, { default: () => 'USER' }),*/
|
||||
/*h(NIcon, { size: '16', style: { 'margin-right': '8px' } }),*/
|
||||
h('span', row.user)
|
||||
])
|
||||
}
|
||||
},
|
||||
{ title: '操作', key: 'action' },
|
||||
{
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'time-cell' }, [
|
||||
/*h(NIcon, { size: '14', style: { 'margin-right': '6px' } }, { default: () => 'TIME' }),*/
|
||||
h('span', row.time)
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 测试登录用户信息
|
||||
onMounted(() => {
|
||||
//console.log(JSON.stringify(userInfo));
|
||||
//console.log("是否营销:" + userInfo.user.userCategory);
|
||||
//console.log("营销编号:" + userInfo.user.mktNo);
|
||||
//console.log("营销编号:" + userInfo.dept.deptCategory);
|
||||
|
||||
//根据用户部门判断是否管理用户
|
||||
isAdmin =
|
||||
(
|
||||
userInfo.dept.deptCategory === '251009999'
|
||||
|| userInfo.dept.deptCategory === '251000099'
|
||||
|| userInfo.dept.deptId === '100'
|
||||
);
|
||||
|
||||
// 当用户是管理用户时,登陆后即异步查询所有用户信息,暂时mock数据
|
||||
if(isAdmin.value){
|
||||
adminData.value.pricingSummary = [
|
||||
{ category: '智E通业务', amount: 245600.00, percentage: 42, trend: 'up', growth: 8.2 },
|
||||
{ category: '综合收单业务', amount: 187430.50, percentage: 32, trend: 'up', growth: 12.5 },
|
||||
{ category: '代收业务', amount: 151209.06, percentage: 26, trend: 'down', growth: -3.4 },
|
||||
{ category: '社保卡业务', amount: 151209.06, percentage: 26, trend: 'down', growth: -3.4 },
|
||||
{ category: '其他', amount: 151209.06, percentage: 26, trend: 'down', growth: -3.4 }
|
||||
];
|
||||
adminData.value.recentActivities = [
|
||||
{ user: '王凯', action: '录入营销数据', time: '5分钟前', type: 'update' },
|
||||
{ user: '李延玲', action: '录入营销数据', time: '30分钟前', type: 'import' },
|
||||
{ user: '柏学慧', action: '新增业务类型', time: '2小时前', type: 'submit' },
|
||||
{ user: '吴新宇', action: '修改分成比例', time: '昨天', type: 'review' },
|
||||
{ user: '赵清惠', action: '录入营销数据', time: '7天前', type: 'review' }
|
||||
]
|
||||
}else{// 当用户是营销用户时,登录后即异步查询自己的信息,暂时mock数据
|
||||
adminData.value.pricingSummary = [
|
||||
{ category: '智E通业务', amount: 24560.00, percentage: 42, trend: 'up', growth: 8.2 },
|
||||
{ category: '综合收单业务', amount: 18743.50, percentage: 32, trend: 'up', growth: 12.5 },
|
||||
{ category: '代收业务', amount: 15120.06, percentage: 26, trend: 'down', growth: -3.4 },
|
||||
{ category: '社保卡业务', amount: 15129.06, percentage: 26, trend: 'down', growth: -3.4 },
|
||||
{ category: '其他', amount: 15129.06, percentage: 26, trend: 'down', growth: -3.4 }
|
||||
];
|
||||
adminData.value.recentActivities = [
|
||||
{ user: userInfo.user.nickName, action: '录入营销数据', time: '5分钟前', type: 'update' },
|
||||
{ user: userInfo.user.nickName, action: '录入营销数据', time: '30分钟前', type: 'import' },
|
||||
{ user: userInfo.user.nickName, action: '新增业务类型', time: '2小时前', type: 'submit' },
|
||||
{ user: userInfo.user.nickName, action: '修改分成比例', time: '昨天', type: 'review' },
|
||||
{ user: userInfo.user.nickName, action: '录入营销数据', time: '7天前', type: 'review' }
|
||||
]
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -83,32 +287,138 @@ const setDateRange = (type: 'today' | 'week' | 'month') => {
|
||||
@date-change="handleDateChange"
|
||||
@quick-change="setDateRange"/>
|
||||
|
||||
<!-- 线图、bar图 -->
|
||||
<!-- 替换线图和饼图部分为数据卡片 -->
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi span="24 s:24 m:14">
|
||||
<NCard :bordered="false" class="card-wrapper">
|
||||
<LineChartMkt
|
||||
v-if="userInfo.user.userCategory === '0'"
|
||||
:date-range="dateRange"
|
||||
/>
|
||||
<LineChartSummary
|
||||
v-else
|
||||
:date-range="dateRange"/>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:10">
|
||||
<NCard :bordered="false" class="card-wrapper">
|
||||
<PieChartMkt
|
||||
v-if="userInfo.user.userCategory === '0'"
|
||||
:date-range="dateRange"
|
||||
/>
|
||||
<PieChartSummary
|
||||
v-else
|
||||
:date-range="dateRange"/>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<!-- 营销用户视图 -->
|
||||
<!-- <template v-if="userInfo.user.userCategory === '0'">
|
||||
<NGi span="24 s:24 m:14">
|
||||
<NCard title="计价结果" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="pricingColumns"
|
||||
:data="marketingData.pricingResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
查看全部
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:10">
|
||||
<NCard title="差错分析" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="errorColumns"
|
||||
:data="marketingData.errorResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
处理差错
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</template>-->
|
||||
|
||||
<!-- 管理用户视图 -->
|
||||
<!-- <template v-else>-->
|
||||
<!-- <template v-if="userInfo.user.userCategory === '9'">-->
|
||||
<template v-if="userInfo.user">
|
||||
<NGi span="24 s:24 m:14">
|
||||
<NCard title="计价汇总" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="summaryColumns"
|
||||
:data="adminData.pricingSummary"
|
||||
:bordered="false"
|
||||
/>
|
||||
<!-- <template #header-extra>
|
||||
<NButton text type="primary">
|
||||
导出数据
|
||||
</NButton>
|
||||
</template>-->
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:10">
|
||||
<NCard title="最近活动" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="activityColumns"
|
||||
:data="adminData.recentActivities"
|
||||
:bordered="false"
|
||||
/>
|
||||
<!-- <template #header-extra>
|
||||
<NButton text type="primary">
|
||||
查看全部
|
||||
</NButton>
|
||||
</template>-->
|
||||
</NCard>
|
||||
</NGi>
|
||||
</template>
|
||||
</NGrid>
|
||||
|
||||
<!-- 额外信息卡片 -->
|
||||
<!-- <NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi span="24 s:24 m:12">
|
||||
<NCard title="项目动态" :bordered="false" class="card-wrapper" size="small">
|
||||
<ProjectNews />
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:12">
|
||||
<NCard title="创意营销" :bordered="false" class="card-wrapper" size="small">
|
||||
<CreativityBanner />
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>-->
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
.card-wrapper {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:deep(.n-card__content) {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-th {
|
||||
background-color: #f9fafb;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-td {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.project-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.project-date {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.amount-cell {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.amount-with-trend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.user-cell, .time-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
571
cds-fontend-2025.V1/src/views/home/index.vue.bak20250903001
Normal file
571
cds-fontend-2025.V1/src/views/home/index.vue.bak20250903001
Normal file
@ -0,0 +1,571 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, h } from 'vue'
|
||||
import { useAuthStore } from '@/store/modules/auth'
|
||||
import { NButton, NCard, NStatistic, NDataTable, NTag, NDivider, NH1, NH2, NP, NNumberAnimation, NProgress, NGrid, NGi, NSpace, NIcon } from 'naive-ui'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const { userInfo } = authStore
|
||||
|
||||
// 用户角色判断
|
||||
const isMarketingUser = computed(() => userInfo?.user?.userCategory === '9')
|
||||
const isAdminUser = computed(() => userInfo?.user?.userCategory === '9')
|
||||
|
||||
// 营销用户数据
|
||||
const marketingData = ref({
|
||||
performance: {
|
||||
totalAmount: 128456.78,
|
||||
completedProjects: 24,
|
||||
pendingProjects: 5,
|
||||
successRate: 92.5
|
||||
},
|
||||
pricingResults: [
|
||||
{ id: 1, project: '品牌推广活动', amount: 24500.00, status: '已完成', date: '2023-10-15' },
|
||||
{ id: 2, project: '社交媒体营销', amount: 18700.50, status: '进行中', date: '2023-10-18' },
|
||||
{ id: 3, project: '季度促销活动', amount: 35600.00, status: '待审核', date: '2023-10-20' },
|
||||
{ id: 4, project: '新产品发布会', amount: 28900.00, status: '已完成', date: '2023-10-22' }
|
||||
],
|
||||
errorResults: [
|
||||
{ id: 1, project: '品牌推广活动', errorType: '数据不一致', status: '已处理', date: '2023-10-16' },
|
||||
{ id: 2, project: '社交媒体营销', errorType: '计算错误', status: '待处理', date: '2023-10-19' },
|
||||
{ id: 3, project: '季度促销活动', errorType: '规则冲突', status: '处理中', date: '2023-10-21' }
|
||||
]
|
||||
})
|
||||
|
||||
// 管理用户数据
|
||||
const adminData = ref({
|
||||
systemOverview: {
|
||||
totalUsers: 42,
|
||||
activeProjects: 18,
|
||||
totalRevenue: 584239.56,
|
||||
systemLoad: 78.2,
|
||||
errorRate: 5.3
|
||||
},
|
||||
pricingSummary: [
|
||||
{ category: '标准套餐', amount: 245600.00, percentage: 42, trend: 'up' },
|
||||
{ category: '高级套餐', amount: 187430.50, percentage: 32, trend: 'up' },
|
||||
{ category: '定制方案', amount: 151209.06, percentage: 26, trend: 'down' }
|
||||
],
|
||||
recentActivities: [
|
||||
{ user: '张经理', action: '更新了计价规则', time: '2小时前', type: 'update' },
|
||||
{ user: '李主管', action: '导入了新数据', time: '5小时前', type: 'import' },
|
||||
{ user: '王营销', action: '提交了营销数据', time: '昨天', type: 'submit' },
|
||||
{ user: '赵助理', action: '审核了定价方案', time: '昨天', type: 'review' }
|
||||
]
|
||||
})
|
||||
|
||||
// 计价结果表格列
|
||||
const pricingColumns = [
|
||||
{
|
||||
title: '项目名称',
|
||||
key: 'project',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'project-cell' }, [
|
||||
h('div', { class: 'project-name' }, row.project),
|
||||
h('div', { class: 'project-date' }, row.date)
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-cell' }, row.amount.toLocaleString('zh-CN', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}))
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已完成' ? 'success' :
|
||||
row.status === '进行中' ? 'warning' : 'default'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 差错结果表格列
|
||||
const errorColumns = [
|
||||
{ title: '项目名称', key: 'project' },
|
||||
{ title: '差错类型', key: 'errorType' },
|
||||
{
|
||||
title: '处理状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已处理' ? 'success' :
|
||||
row.status === '处理中' ? 'warning' : 'error'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 汇总数据表格列
|
||||
const summaryColumns = [
|
||||
{ title: '套餐类别', key: 'category' },
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-with-trend' }, [
|
||||
h('span', row.amount.toLocaleString('zh-CN')),
|
||||
h(NIcon, {
|
||||
size: '16',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050',
|
||||
style: { 'margin-left': '8px' }
|
||||
}, { default: () => h(row.trend === 'up' ? TrendingUp : TrendingUp) })
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '占比',
|
||||
key: 'percentage',
|
||||
render: (row: any) => {
|
||||
return h(NProgress, {
|
||||
type: 'line',
|
||||
percentage: row.percentage,
|
||||
'indicator-placement': 'inside',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 活动记录表格列
|
||||
const activityColumns = [
|
||||
{
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'user-cell' }, [
|
||||
h(NIcon, { size: '16', style: { 'margin-right': '8px' } }, { default: () => h(Users) }),
|
||||
h('span', row.user)
|
||||
])
|
||||
}
|
||||
},
|
||||
{ title: '操作', key: 'action' },
|
||||
{
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'time-cell' }, [
|
||||
h(NIcon, { size: '14', style: { 'margin-right': '6px' } }, { default: () => h(Time) }),
|
||||
h('span', row.time)
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 初始设置为本月范围
|
||||
const dateRange = ref<[number, number]>([
|
||||
dayjs().startOf('month').valueOf(),
|
||||
dayjs().endOf('month').valueOf()
|
||||
])
|
||||
|
||||
// 处理日期变化
|
||||
const handleDateChange = (range: [number, number]) => {
|
||||
dateRange.value = range
|
||||
}
|
||||
|
||||
// 设置快速日期范围
|
||||
const setDateRange = (type: 'today' | 'week' | 'month') => {
|
||||
let start, end
|
||||
|
||||
switch (type) {
|
||||
case 'today':
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
break
|
||||
case 'week':
|
||||
start = dayjs().startOf('week')
|
||||
end = dayjs().endOf('week')
|
||||
break
|
||||
case 'month':
|
||||
start = dayjs().startOf('month')
|
||||
end = dayjs().endOf('month')
|
||||
break
|
||||
default:
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
}
|
||||
|
||||
dateRange.value = [start.valueOf(), end.valueOf()]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<!-- 欢迎横幅 -->
|
||||
<n-card class="welcome-card" :bordered="false">
|
||||
<div class="header">
|
||||
<div>
|
||||
<n-h1 style="margin: 0; color: #1f2937;">营销计价系统</n-h1>
|
||||
<n-p style="margin: 8px 0 0; color: #6b7280; font-size: 16px;">
|
||||
{{ isMarketingUser ? '高效管理您的营销数据和计价结果' : '全面掌控系统数据和运营状况' }}
|
||||
</n-p>
|
||||
</div>
|
||||
<n-tag type="primary" round size="large">
|
||||
{{ isMarketingUser ? '营销用户' : '管理用户' }}
|
||||
</n-tag>
|
||||
</div>
|
||||
</n-card>
|
||||
|
||||
<!-- 营销用户视图 -->
|
||||
<template v-if="isMarketingUser">
|
||||
<div class="section-header">
|
||||
<n-h2 style="margin: 0;">营销工作台</n-h2>
|
||||
<n-p style="margin: 8px 0 0; color: #6b7280;">欢迎回来!以下是您的营销数据概览和计价结果。</n-p>
|
||||
</div>
|
||||
|
||||
<n-grid :cols="4" :x-gap="16" :y-gap="16" class="stats-grid">
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="总营销金额">
|
||||
<n-number-animation :from="0" :to="marketingData.performance.totalAmount" />
|
||||
<template #suffix>¥</template>
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="TrendingUp" color="#18a058" size="20" />
|
||||
<span style="color: #18a058; font-size: 14px;">+12.5%</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="完成项目数">
|
||||
<n-number-animation :from="0" :to="marketingData.performance.completedProjects" />
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="CheckmarkCircle" color="#18a058" size="20" />
|
||||
<span style="color: #18a058; font-size: 14px;">92.5% 成功率</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="待处理项目">
|
||||
<n-number-animation :from="0" :to="marketingData.performance.pendingProjects" />
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="Time" color="#f0a020" size="20" />
|
||||
<span style="color: #f0a020; font-size: 14px;">需要关注</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="差错项目">
|
||||
<n-number-animation :from="0" :to="marketingData.errorResults.length" />
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="AlertCircle" color="#d03050" size="20" />
|
||||
<span style="color: #d03050; font-size: 14px;">{{ marketingData.errorResults.filter(e => e.status === '待处理').length }} 个待处理</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
|
||||
<n-grid :cols="2" :x-gap="16" :y-gap="16" class="data-grid">
|
||||
<n-gi>
|
||||
<n-card title="计价结果" class="data-card" size="small">
|
||||
<n-data-table
|
||||
:columns="pricingColumns"
|
||||
:data="marketingData.pricingResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card title="差错分析" class="data-card" size="small">
|
||||
<n-data-table
|
||||
:columns="errorColumns"
|
||||
:data="marketingData.errorResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</template>
|
||||
|
||||
<!-- 管理用户视图 -->
|
||||
<template v-else-if="isAdminUser">
|
||||
<div class="section-header">
|
||||
<n-h2 style="margin: 0;">管理控制台</n-h2>
|
||||
<n-p style="margin: 8px 0 0; color: #6b7280;">系统概览和关键指标汇总。</n-p>
|
||||
</div>
|
||||
|
||||
<n-grid :cols="5" :x-gap="16" :y-gap="16" class="stats-grid">
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="系统用户数">
|
||||
<n-number-animation :from="0" :to="adminData.systemOverview.totalUsers" />
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="Users" color="#2080f0" size="20" />
|
||||
<span style="color: #2080f0; font-size: 14px;">+3 本月新增</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="活跃项目数">
|
||||
<n-number-animation :from="0" :to="adminData.systemOverview.activeProjects" />
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="Activity" color="#18a058" size="20" />
|
||||
<span style="color: #18a058; font-size: 14px;">78% 完成率</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="总收入">
|
||||
<n-number-animation :from="0" :to="adminData.systemOverview.totalRevenue" />
|
||||
<template #suffix>¥</template>
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="TrendingUp" color="#18a058" size="20" />
|
||||
<span style="color: #18a058; font-size: 14px;">+18.2%</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="系统负载">
|
||||
<n-number-animation :from="0" :to="adminData.systemOverview.systemLoad" />
|
||||
<template #suffix>%</template>
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="Activity" color="#f0a020" size="20" />
|
||||
<span style="color: #f0a020; font-size: 14px;">运行正常</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card class="stat-card" content-style="padding: 20px;">
|
||||
<n-space vertical>
|
||||
<n-statistic label="差错率">
|
||||
<n-number-animation :from="0" :to="adminData.systemOverview.errorRate" />
|
||||
<template #suffix>%</template>
|
||||
</n-statistic>
|
||||
<n-space align="center">
|
||||
<n-icon :component="AlertCircle" color="#d03050" size="20" />
|
||||
<span style="color: #d03050; font-size: 14px;">需关注</span>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
|
||||
<n-grid :cols="2" :x-gap="16" :y-gap="16" class="data-grid">
|
||||
<n-gi>
|
||||
<n-card title="计价汇总" class="data-card" size="small">
|
||||
<n-data-table
|
||||
:columns="summaryColumns"
|
||||
:data="adminData.pricingSummary"
|
||||
:bordered="false"
|
||||
/>
|
||||
|
||||
<div class="chart-container">
|
||||
<n-p>收入分布图表可视化</n-p>
|
||||
</div>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi>
|
||||
<n-card title="最近活动" class="data-card" size="small">
|
||||
<n-data-table
|
||||
:columns="activityColumns"
|
||||
:data="adminData.recentActivities"
|
||||
:bordered="false"
|
||||
/>
|
||||
|
||||
<div class="quick-actions">
|
||||
<n-space>
|
||||
<n-button type="primary" tertiary>
|
||||
导入数据
|
||||
</n-button>
|
||||
<n-button type="info" tertiary>
|
||||
规则管理
|
||||
</n-button>
|
||||
<n-button type="success" tertiary>
|
||||
生成报告
|
||||
</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-container {
|
||||
padding: 24px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
background-color: #f8fafc;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.welcome-card {
|
||||
margin-bottom: 24px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.welcome-card :deep(.n-card__content) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.data-grid {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.data-card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #e5e7eb;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.data-card :deep(.n-card-header) {
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.data-card :deep(.n-card__content) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 200px;
|
||||
background-color: #f9fafb;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
margin-top: 20px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.project-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.project-date {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.amount-cell {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.amount-with-trend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.user-cell, .time-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-th {
|
||||
background-color: #f9fafb;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-td {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
:deep(.n-statistic .n-statistic-value) {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
:deep(.n-statistic .n-statistic-label) {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
387
cds-fontend-2025.V1/src/views/home/index.vue.bak20250904001
Normal file
387
cds-fontend-2025.V1/src/views/home/index.vue.bak20250904001
Normal file
@ -0,0 +1,387 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch, h } from 'vue' // 添加 h 导入
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import HeaderBanner from './modules/header-banner.vue'
|
||||
import CardData from './modules/card-data.vue'
|
||||
import CardDataSummary from './modules/card-data-summary.vue'
|
||||
import CardDataMkt from './modules/card-data-mkt.vue'
|
||||
import ProjectNews from './modules/project-news.vue'
|
||||
import CreativityBanner from './modules/creativity-banner.vue'
|
||||
import { useAuthStore } from "@/store/modules/auth"
|
||||
import {
|
||||
NButton,
|
||||
NCard,
|
||||
NStatistic,
|
||||
NDataTable,
|
||||
NTag,
|
||||
NDivider,
|
||||
NH1,
|
||||
NH2,
|
||||
NP,
|
||||
NNumberAnimation,
|
||||
NProgress,
|
||||
NGrid,
|
||||
NGi,
|
||||
NSpace,
|
||||
NIcon,
|
||||
NThing
|
||||
} from 'naive-ui'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const { userInfo } = useAuthStore()
|
||||
|
||||
const gap = computed(() => (appStore.isMobile ? 0 : 16))
|
||||
|
||||
// 初始设置为本月范围
|
||||
const dateRange = ref<[number, number]>([
|
||||
dayjs().startOf('month').valueOf(), // 本月第一天
|
||||
dayjs().endOf('month').valueOf() // 本月最后一天
|
||||
])
|
||||
|
||||
// 处理日期变化
|
||||
const handleDateChange = (range: [number, number]) => {
|
||||
dateRange.value = range
|
||||
}
|
||||
|
||||
// 设置快速日期范围
|
||||
const setDateRange = (type: 'today' | 'week' | 'month') => {
|
||||
let start, end
|
||||
|
||||
switch (type) {
|
||||
case 'today':
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
break
|
||||
case 'week':
|
||||
start = dayjs().startOf('week')
|
||||
end = dayjs().endOf('week')
|
||||
break
|
||||
case 'month':
|
||||
start = dayjs().startOf('month')
|
||||
end = dayjs().endOf('month')
|
||||
break
|
||||
default:
|
||||
start = dayjs().startOf('day')
|
||||
end = dayjs().endOf('day')
|
||||
}
|
||||
|
||||
dateRange.value = [start.valueOf(), end.valueOf()]
|
||||
}
|
||||
|
||||
// 营销用户数据
|
||||
const marketingData = ref({
|
||||
performance: {
|
||||
totalAmount: 128456.78,
|
||||
completedProjects: 24,
|
||||
pendingProjects: 5,
|
||||
successRate: 92.5,
|
||||
growthRate: 12.5
|
||||
},
|
||||
pricingResults: [
|
||||
{ id: 1, project: '品牌推广活动', amount: 24500.00, status: '已完成', date: '2023-10-15' },
|
||||
{ id: 2, project: '社交媒体营销', amount: 18700.50, status: '进行中', date: '2023-10-18' },
|
||||
{ id: 3, project: '季度促销活动', amount: 35600.00, status: '待审核', date: '2023-10-20' },
|
||||
{ id: 4, project: '新产品发布会', amount: 28900.00, status: '已完成', date: '2023-10-22' }
|
||||
],
|
||||
errorResults: [
|
||||
{ id: 1, project: '品牌推广活动', errorType: '数据不一致', status: '已处理', date: '2023-10-16' },
|
||||
{ id: 2, project: '社交媒体营销', errorType: '计算错误', status: '待处理', date: '2023-10-19' },
|
||||
{ id: 3, project: '季度促销活动', errorType: '规则冲突', status: '处理中', date: '2023-10-21' }
|
||||
]
|
||||
})
|
||||
|
||||
// 管理用户数据
|
||||
const adminData = ref({
|
||||
systemOverview: {
|
||||
totalUsers: 42,
|
||||
activeProjects: 18,
|
||||
totalRevenue: 584239.56,
|
||||
systemLoad: 78.2,
|
||||
errorRate: 5.3
|
||||
},
|
||||
pricingSummary: [
|
||||
{ category: '标准套餐', amount: 245600.00, percentage: 42, trend: 'up', growth: 8.2 },
|
||||
{ category: '高级套餐', amount: 187430.50, percentage: 32, trend: 'up', growth: 12.5 },
|
||||
{ category: '定制方案', amount: 151209.06, percentage: 26, trend: 'down', growth: -3.4 }
|
||||
],
|
||||
recentActivities: [
|
||||
{ user: '张经理', action: '更新了计价规则', time: '2小时前', type: 'update' },
|
||||
{ user: '李主管', action: '导入了新数据', time: '5小时前', type: 'import' },
|
||||
{ user: '王营销', action: '提交了营销数据', time: '昨天', type: 'submit' },
|
||||
{ user: '赵助理', action: '审核了定价方案', time: '昨天', type: 'review' }
|
||||
]
|
||||
})
|
||||
|
||||
// 计价结果表格列
|
||||
const pricingColumns = [
|
||||
{
|
||||
title: '项目名称',
|
||||
key: 'project',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'project-cell' }, [
|
||||
h('div', { class: 'project-name' }, row.project),
|
||||
h('div', { class: 'project-date' }, row.date)
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-cell' }, row.amount.toLocaleString('zh-CN', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}))
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已完成' ? 'success' :
|
||||
row.status === '进行中' ? 'warning' : 'default'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 差错结果表格列
|
||||
const errorColumns = [
|
||||
{ title: '项目名称', key: 'project' },
|
||||
{ title: '差错类型', key: 'errorType' },
|
||||
{
|
||||
title: '处理状态',
|
||||
key: 'status',
|
||||
render: (row: any) => {
|
||||
const type = row.status === '已处理' ? 'success' :
|
||||
row.status === '处理中' ? 'warning' : 'error'
|
||||
return h(NTag, {
|
||||
type: type,
|
||||
size: 'small',
|
||||
round: true
|
||||
}, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 汇总数据表格列
|
||||
const summaryColumns = [
|
||||
{ title: '套餐类别', key: 'category' },
|
||||
{
|
||||
title: '金额 (¥)',
|
||||
key: 'amount',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'amount-with-trend' }, [
|
||||
h('span', row.amount.toLocaleString('zh-CN')),
|
||||
h(NIcon, {
|
||||
size: '16',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050',
|
||||
style: { 'margin-left': '8px' }
|
||||
}, { default: () => '123' })
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '占比',
|
||||
key: 'percentage',
|
||||
render: (row: any) => {
|
||||
return h(NProgress, {
|
||||
type: 'line',
|
||||
percentage: row.percentage,
|
||||
'indicator-placement': 'inside',
|
||||
color: row.trend === 'up' ? '#18a058' : '#d03050'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 活动记录表格列
|
||||
const activityColumns = [
|
||||
{
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'user-cell' }, [
|
||||
h(NIcon, { size: '16', style: { 'margin-right': '8px' } }, { default: () => 'USER' }),
|
||||
h('span', row.user)
|
||||
])
|
||||
}
|
||||
},
|
||||
{ title: '操作', key: 'action' },
|
||||
{
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'time-cell' }, [
|
||||
h(NIcon, { size: '14', style: { 'margin-right': '6px' } }, { default: () => 'TIME' }),
|
||||
h('span', row.time)
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 测试登录用户信息
|
||||
/*onMounted(() => {
|
||||
console.log(JSON.stringify(userInfo));
|
||||
console.log("是否营销:" + userInfo.user.userCategory);
|
||||
console.log("营销编号:" + userInfo.user.mktNo);
|
||||
});*/
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSpace vertical :size="16">
|
||||
<!-- 欢迎banner -->
|
||||
<HeaderBanner />
|
||||
|
||||
<!-- 数据卡 - 营销人员和其他人员看到的图表不同 -->
|
||||
<CardDataMkt
|
||||
v-if="userInfo.user.userCategory === '0'"
|
||||
:date-range="dateRange"
|
||||
@date-change="handleDateChange"
|
||||
@quick-change="setDateRange"
|
||||
/>
|
||||
<CardDataSummary
|
||||
v-else
|
||||
:date-range="dateRange"
|
||||
@date-change="handleDateChange"
|
||||
@quick-change="setDateRange"/>
|
||||
|
||||
<!-- 替换线图和饼图部分为数据卡片 -->
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<!-- 营销用户视图 -->
|
||||
<template v-if="userInfo.user.userCategory === '0'">
|
||||
<NGi span="24 s:24 m:14">
|
||||
<NCard title="计价结果" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="pricingColumns"
|
||||
:data="marketingData.pricingResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
查看全部
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:10">
|
||||
<NCard title="差错分析" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="errorColumns"
|
||||
:data="marketingData.errorResults"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
处理差错
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</template>
|
||||
|
||||
<!-- 管理用户视图 -->
|
||||
<template v-else>
|
||||
<NGi span="24 s:24 m:14">
|
||||
<NCard title="计价汇总" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="summaryColumns"
|
||||
:data="adminData.pricingSummary"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
导出数据
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:10">
|
||||
<NCard title="最近活动" :bordered="false" class="card-wrapper" size="small">
|
||||
<NDataTable
|
||||
:columns="activityColumns"
|
||||
:data="adminData.recentActivities"
|
||||
:bordered="false"
|
||||
/>
|
||||
<template #header-extra>
|
||||
<NButton text type="primary">
|
||||
查看全部
|
||||
</NButton>
|
||||
</template>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</template>
|
||||
</NGrid>
|
||||
|
||||
<!-- 额外信息卡片 -->
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi span="24 s:24 m:12">
|
||||
<NCard title="项目动态" :bordered="false" class="card-wrapper" size="small">
|
||||
<ProjectNews />
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi span="24 s:24 m:12">
|
||||
<NCard title="创意营销" :bordered="false" class="card-wrapper" size="small">
|
||||
<CreativityBanner />
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card-wrapper {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:deep(.n-card__content) {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-th {
|
||||
background-color: #f9fafb;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.n-data-table) .n-data-table-td {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.project-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.project-date {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.amount-cell {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.amount-with-trend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.user-cell, .time-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user