Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mengchangaigc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姚珂
mengchangaigc
Commits
034d0c1b
Commit
034d0c1b
authored
Aug 24, 2026
by
黄同智
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
广告账户分析、团队分析、直播管理等页面的交互和布局
parent
0983a8bd
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1420 additions
and
102 deletions
+1420
-102
index.db
apps/web-vue/.pnpm-store/v11/index.db
+0
-0
package.json
apps/web-vue/package.json
+1
-0
index.vue
apps/web-vue/src/layout/index.vue
+5
-0
index.ts
apps/web-vue/src/router/index.ts
+13
-0
ad.vue
apps/web-vue/src/views/analysis/ad.vue
+35
-5
Tab1.vue
apps/web-vue/src/views/analysis/components/AD/Tab1.vue
+0
-0
Tab2.vue
apps/web-vue/src/views/analysis/components/AD/Tab2.vue
+0
-0
Tab3.vue
apps/web-vue/src/views/analysis/components/AD/Tab3.vue
+200
-0
Tab4.vue
apps/web-vue/src/views/analysis/components/AD/Tab4.vue
+224
-0
Tab1.vue
apps/web-vue/src/views/analysis/components/Team/Tab1.vue
+180
-0
Tab2.vue
apps/web-vue/src/views/analysis/components/Team/Tab2.vue
+190
-0
Tab3.vue
apps/web-vue/src/views/analysis/components/Team/Tab3.vue
+220
-0
TaskDetailDialog.vue
...e/src/views/analysis/components/Team/TaskDetailDialog.vue
+92
-0
TaskStatsDialog.vue
...ue/src/views/analysis/components/Team/TaskStatsDialog.vue
+103
-0
AdPlatformTags.vue
...ue/src/views/analysis/components/video/AdPlatformTags.vue
+24
-17
DeliveryReport.vue
...ue/src/views/analysis/components/video/DeliveryReport.vue
+41
-39
TagAnalysis.vue
...b-vue/src/views/analysis/components/video/TagAnalysis.vue
+3
-3
TencentDeliveryReport.vue
...views/analysis/components/video/TencentDeliveryReport.vue
+52
-29
department.vue
apps/web-vue/src/views/analysis/department.vue
+33
-5
video.vue
apps/web-vue/src/views/analysis/video.vue
+4
-4
index.vue
apps/web-vue/src/views/zhibo/index.vue
+0
-0
No files found.
apps/web-vue/.pnpm-store/v11/index.db
0 → 100644
View file @
034d0c1b
File added
apps/web-vue/package.json
View file @
034d0c1b
...
...
@@ -9,6 +9,7 @@
"preview"
:
"vite preview"
},
"dependencies"
:
{
"@element-plus/icons-vue"
:
"^2.3.2"
,
"@ffmpeg/ffmpeg"
:
"^0.12.15"
,
"@ffmpeg/util"
:
"^0.12.2"
,
"@vue-flow/additional-components"
:
"^1.3.3"
,
...
...
apps/web-vue/src/layout/index.vue
View file @
034d0c1b
...
...
@@ -110,6 +110,11 @@ const menus = [
icon
:
'redraw'
,
},
{
name
:
'直播管理'
,
path
:
'/zhibo'
,
icon
:
'map'
,
},
{
name
:
'任务协作'
,
path
:
'/task'
,
icon
:
'map'
,
...
...
apps/web-vue/src/router/index.ts
View file @
034d0c1b
...
...
@@ -30,6 +30,19 @@ const routes = [
]
},
{
path
:
'/zhibo'
,
component
:
Layout
,
children
:
[
{
path
:
'zhibo'
,
alias
:
''
,
name
:
'Zhibo'
,
component
:
import
(
'@/views/zhibo/index.vue'
),
meta
:
{
title
:
'直播管理'
,
icon
:
'House'
,
affix
:
true
}
}
]
},
{
path
:
'/task'
,
component
:
Layout
,
children
:
[
...
...
apps/web-vue/src/views/analysis/ad.vue
View file @
034d0c1b
<
template
>
<div>
<div
class=
"bgmr vh100 over-y-auto"
>
<section
class=
"bg-fff px-20 py-10 analysis-tabs"
>
<div
class=
"flex-items-center gap-16"
>
<div
v-for=
"item in tabs"
:key=
"item.value"
class=
"px-12 py-8 round-6 font-bold pointer"
:class=
"activeTab === item.value ? 'bg-main color-fff' : 'color-000'"
@
click=
"activeTab = item.value"
>
{{
item
.
label
}}
</div>
</div>
</section>
<div
class=
"p-16"
>
<component
:is=
"currentComponent"
/>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
Tab1
from
'./components/AD/Tab1.vue'
;
import
Tab2
from
'./components/AD/Tab2.vue'
;
import
Tab3
from
'./components/AD/Tab3.vue'
;
import
Tab4
from
'./components/AD/Tab4.vue'
;
const
activeTab
=
ref
(
'tab1'
);
const
tabs
=
[
{
label
:
'广告账户数据'
,
value
:
'tab1'
,
component
:
Tab1
},
{
label
:
'广告账户财务报表'
,
value
:
'tab2'
,
component
:
Tab2
},
{
label
:
'投放状态报表'
,
value
:
'tab3'
,
component
:
Tab3
},
{
label
:
'TikTok店铺'
,
value
:
'tab4'
,
component
:
Tab4
},
];
const
currentComponent
=
computed
(()
=>
tabs
.
find
((
item
)
=>
item
.
value
===
activeTab
.
value
)?.
component
);
</
script
>
<
style
scoped
lang=
"scss"
>
</
style
>
\ No newline at end of file
.analysis-tabs
{
border-bottom
:
1px
solid
#dfe7f2
;
}
</
style
>
apps/web-vue/src/views/analysis/components/AD/Tab1.vue
0 → 100644
View file @
034d0c1b
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/analysis/components/AD/Tab2.vue
0 → 100644
View file @
034d0c1b
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/analysis/components/AD/Tab3.vue
0 → 100644
View file @
034d0c1b
<
template
>
<div
class=
"status-report flex-col gap-12"
>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"top-line flex-between gap-16"
>
<div
class=
"flex-items-center gap-26 flex-wrap"
>
<button
v-for=
"item in dataTabs"
:key=
"item"
class=
"text-tab pointer border-none bg-none font-bold"
:class=
"
{ active: dataTab === item }" @click="dataTab = item">
{{
item
}}
</button>
</div>
<div
class=
"date-filter flex-items-center gap-8"
>
<span>
计划搭建时间
</span>
<el-date-picker
v-model=
"range"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"2025/03/31"
end-placeholder=
"2025/04/14"
/>
</div>
</div>
<div
class=
"flex-items-center justify-start gap-16 pt-14"
>
<div
class=
"flex-items-center gap-26 flex-wrap"
>
<button
v-for=
"item in platforms"
:key=
"item.value"
class=
"platform-item flex-items-center gap-6 pointer border-none bg-none"
:class=
"
{ active: platform === item.value }" @click="platform = item.value">
<span
class=
"w-10 h-10 round-2"
:style=
"
{ backgroundColor: item.color }">
</span>
{{
item
.
label
}}
</button>
</div>
<el-select
v-model=
"department"
class=
"w-180"
placeholder=
"请选择部门"
>
<el-option
label=
"抖音投放"
value=
"抖音投放"
/>
<el-option
label=
"测试指定员工可见-部门"
value=
"测试指定员工可见-部门"
/>
<el-option
label=
"未绑定"
value=
"未绑定"
/>
</el-select>
</div>
</el-card>
<el-card
class=
"report-card chart-card round-8"
shadow=
"never"
>
<div
class=
"flex-between gap-16"
>
<el-segmented
v-model=
"statusType"
:options=
"statusTabs"
/>
<div
class=
"flex-items-center gap-26 flex-wrap"
>
<span
v-for=
"item in legendItems"
:key=
"item.name"
class=
"flex-items-center gap-6"
>
<span
class=
"legend-dot w-10 h-10 round"
:style=
"
{ borderColor: item.color }">
</span>
{{
item
.
name
}}
</span>
</div>
</div>
<div
class=
"h-250 mt-10"
>
<v-chart
class=
"w-full h-full"
:option=
"lineOption"
autoresize
/>
</div>
</el-card>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between gap-16 pb-12"
>
<span
class=
"font-bold"
>
详细数据
</span>
<el-button
class=
"w-34 p-0"
@
click=
"settingVisible = !settingVisible"
>
☷
</el-button>
</div>
<el-alert
v-if=
"settingVisible"
class=
"mb-10"
title=
"已打开字段配置面板"
type=
"info"
show-icon
:closable=
"false"
/>
<el-table
:data=
"tableRows"
class=
"analysis-table"
row-key=
"department"
>
<el-table-column
prop=
"department"
label=
"部门"
min-width=
"260"
>
<template
#
default=
"
{ row }">
<span
:class=
"row.link ? 'link-text font-bold' : 'font-bold'"
>
{{
row
.
department
}}
</span></
template
>
</el-table-column>
<el-table-column
prop=
"built"
label=
"搭建计划总数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"running"
label=
"投放中 ↑↓"
align=
"center"
>
<
template
#
default=
"{ row }"
><span
class=
"color-green font-bold"
>
{{
row
.
running
}}
</span></
template
>
</el-table-column>
<el-table-column
prop=
"notStarted"
label=
"未投放 ⓘ ↑↓"
align=
"center"
/>
<el-table-column
prop=
"ended"
label=
"已终止 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"finished"
label=
"已完成 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"deleted"
label=
"已删除 ↑↓"
align=
"center"
>
<
template
#
default=
"{ row }"
><span
class=
"color-8aa"
>
{{
row
.
deleted
}}
</span></
template
>
</el-table-column>
</el-table>
<div
class=
"scroll-bar mt-14"
></div>
</el-card>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
VChart
from
'vue-echarts'
;
import
{
use
}
from
'echarts/core'
;
import
{
CanvasRenderer
}
from
'echarts/renderers'
;
import
{
LineChart
}
from
'echarts/charts'
;
import
{
GridComponent
,
LegendComponent
,
TooltipComponent
}
from
'echarts/components'
;
use
([
CanvasRenderer
,
LineChart
,
GridComponent
,
LegendComponent
,
TooltipComponent
]);
const
dataTab
=
ref
(
'部门数据'
);
const
platform
=
ref
(
'ad'
);
const
department
=
ref
(
''
);
const
range
=
ref
<
[
Date
,
Date
]
|
''
>
(
''
);
const
statusType
=
ref
(
'搭建计划总数'
);
const
settingVisible
=
ref
(
false
);
const
dataTabs
=
[
'部门数据'
,
'分组数据'
,
'个人数据'
,
'直播间数据'
,
'广告主明细数据'
];
const
statusTabs
=
[
'搭建计划总数'
,
'投放中'
,
'未投放'
];
const
platforms
=
[
{
label
:
'巨量广告'
,
value
:
'ad'
,
color
:
'#7c3aed'
},
{
label
:
'巨量千川'
,
value
:
'qianchuan'
,
color
:
'#2d8cff'
},
];
const
legendItems
=
[
{
name
:
'未绑定'
,
color
:
'#2d8cff'
},
{
name
:
'测试指定员工可见-部门'
,
color
:
'#00b578'
},
{
name
:
'抖音投放'
,
color
:
'#ff9800'
},
];
const
dates
=
[
'2025-03-31'
,
'2025-04-02'
,
'2025-04-04'
,
'2025-04-06'
,
'2025-04-08'
,
'2025-04-10'
,
'2025-04-12'
,
'2025-04-14'
];
const
tableRows
=
[
{
department
:
'总计'
,
built
:
18
,
running
:
5
,
notStarted
:
8
,
ended
:
3
,
finished
:
2
,
deleted
:
0
},
{
department
:
'抖音投放'
,
built
:
8
,
running
:
3
,
notStarted
:
3
,
ended
:
1
,
finished
:
1
,
deleted
:
0
,
link
:
true
},
{
department
:
'测试指定员工可见-部门'
,
built
:
6
,
running
:
2
,
notStarted
:
3
,
ended
:
1
,
finished
:
0
,
deleted
:
0
,
link
:
true
},
{
department
:
'未绑定'
,
built
:
4
,
running
:
0
,
notStarted
:
2
,
ended
:
1
,
finished
:
1
,
deleted
:
0
,
link
:
true
},
];
const
lineOption
=
computed
(()
=>
({
color
:
legendItems
.
map
((
item
)
=>
item
.
color
),
tooltip
:
{
trigger
:
'axis'
},
legend
:
{
show
:
false
},
grid
:
{
left
:
38
,
right
:
24
,
top
:
26
,
bottom
:
34
},
xAxis
:
{
type
:
'category'
,
boundaryGap
:
false
,
data
:
dates
,
axisLine
:
{
lineStyle
:
{
color
:
'#e8eef6'
}
},
axisLabel
:
{
color
:
'#8aa0bf'
},
},
yAxis
:
{
type
:
'value'
,
min
:
0
,
max
:
statusType
.
value
===
'搭建计划总数'
?
1
:
5
,
splitLine
:
{
lineStyle
:
{
color
:
'#edf3fb'
,
type
:
'dashed'
}
},
axisLabel
:
{
color
:
'#8aa0bf'
},
},
series
:
[
{
name
:
'未绑定'
,
type
:
'line'
,
smooth
:
true
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
],
symbolSize
:
8
},
{
name
:
'测试指定员工可见-部门'
,
type
:
'line'
,
smooth
:
true
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
],
symbolSize
:
8
},
{
name
:
'抖音投放'
,
type
:
'line'
,
smooth
:
true
,
data
:
[
0.05
,
0.05
,
0.05
,
0.05
,
0.05
,
0.05
,
0.05
,
0.05
],
symbolSize
:
8
},
],
}));
</
script
>
<
style
scoped
lang=
"scss"
>
.report-card
{
border
:
1px
solid
#dfe7f2
;
}
.top-line
{
border-bottom
:
1px
solid
#edf0f5
;
}
.text-tab
{
height
:
38px
;
padding
:
0
;
border-bottom
:
2px
solid
transparent
;
color
:
#3f5574
;
&
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom-color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.date-filter
{
color
:
#607086
;
}
.platform-item
{
color
:
#3f5574
;
&
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.chart-card
{
min-height
:
310px
;
}
.legend-dot
{
border
:
2px
solid
;
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f5f5f5
;
color
:
#888
;
padding
:
12px
0
;
}
}
.link-text
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.color-green
{
color
:
#00a86b
;
}
.color-8aa
{
color
:
#8aa0bf
;
}
.scroll-bar
{
height
:
5px
;
border-radius
:
999px
;
background
:
#dfe7f2
;
}
</
style
>
apps/web-vue/src/views/analysis/components/AD/Tab4.vue
0 → 100644
View file @
034d0c1b
<
template
>
<div
class=
"shop-report flex-col gap-14"
>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between flex-wrap gap-12 pb-14"
>
<div
class=
"flex-items-center gap-12"
>
<span
class=
"font-bold"
>
授权店铺
</span>
<el-button
type=
"primary"
@
click=
"authorizeShop"
>
授权店铺
</el-button>
</div>
<el-button
link
@
click=
"expanded = !expanded"
>
{{
expanded
?
'收起'
:
'展开'
}}
</el-button>
</div>
<div
v-show=
"expanded"
class=
"shop-grid flex flex-wrap gap-16"
>
<div
v-for=
"shop in shops"
:key=
"shop.code"
class=
"shop-card p-16 round-8 pointer"
:class=
"
{ selected: selectedShop === shop.code }" @click="selectedShop = shop.code">
<div
class=
"flex-items-center gap-12"
>
<div
class=
"tiktok-logo flex-center w-40 h-40 round-8 bg-000 color-fff fs-26 font-bold"
>
♪
</div>
<div
class=
"minw-0"
>
<div
class=
"flex-items-center gap-8 font-bold"
>
{{
shop
.
name
}}
<span
class=
"shop-tag px-6 py-2 round-4 fs-12"
>
{{
shop
.
type
}}
</span>
</div>
<div
class=
"shop-code mt-8 fs-12"
>
{{
shop
.
code
}}
</div>
</div>
</div>
<div
class=
"flex-between gap-8 mt-16"
>
<el-button
type=
"primary"
@
click
.
stop=
"analyzeShop(shop.code)"
size=
"small"
>
数据分析
</el-button>
<el-button
@
click
.
stop=
"moreShopActions(shop.code)"
size=
"small"
>
更多操作
</el-button>
</div>
</div>
</div>
</el-card>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between flex-wrap gap-12 pb-14"
>
<span
class=
"font-bold"
>
数据概览
</span>
<div
class=
"flex-items-center gap-12 flex-wrap"
>
<el-select
v-model=
"selectedShop"
class=
"w-180"
>
<el-option
v-for=
"shop in shops"
:key=
"shop.code"
:label=
"shop.name"
:value=
"shop.code"
/>
</el-select>
<el-segmented
v-model=
"granularity"
:options=
"granularityTabs"
/>
<el-select
v-model=
"timezone"
class=
"w-90"
>
<el-option
label=
"GMT-8"
value=
"GMT-8"
/>
<el-option
label=
"GMT+8"
value=
"GMT+8"
/>
</el-select>
<el-date-picker
v-model=
"range"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"2025/04/15"
end-placeholder=
"2025/04/15"
/>
</div>
</div>
<div
class=
"metric-grid"
>
<div
v-for=
"item in metrics"
:key=
"item.label"
class=
"metric-card minh-88 p-14 round-8"
>
<div
class=
"metric-label fs-12"
>
{{
item
.
label
}}
</div>
<div
class=
"metric-value mt-8 fs-20 fw-800"
>
{{
item
.
value
}}
</div>
<div
class=
"metric-compare mt-8 fs-12"
>
较上一周期
<span>
--
</span></div>
</div>
</div>
</el-card>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between flex-wrap gap-12 pb-14"
>
<div
class=
"flex-items-center gap-12"
>
<button
v-for=
"item in tableTabs"
:key=
"item"
class=
"text-tab border-none bg-none font-bold pointer"
:class=
"
{ active: tableTab === item }" @click="tableTab = item">
{{
item
}}
</button>
</div>
<el-button
type=
"primary"
@
click=
"exportData"
>
导出
</el-button>
</div>
<el-table
:data=
"tableRows"
class=
"analysis-table"
row-key=
"name"
>
<el-table-column
label=
"店铺"
align=
"center"
>
<el-table-column
prop=
"name"
label=
"名称"
min-width=
"260"
/>
<el-table-column
prop=
"code"
label=
"code"
min-width=
"180"
/>
</el-table-column>
<el-table-column
label=
"Statements"
align=
"center"
>
<el-table-column
prop=
"statementProcessing"
label=
"Processing 累计处理中"
min-width=
"160"
align=
"right"
/>
<el-table-column
prop=
"statementPaid"
label=
"Paid 总支付"
min-width=
"150"
align=
"right"
/>
<el-table-column
prop=
"statementFailed"
label=
"Failed 支付失败"
min-width=
"150"
align=
"right"
/>
</el-table-column>
<el-table-column
label=
"Payouts"
align=
"center"
>
<el-table-column
prop=
"payoutPaid"
label=
"Paid 总支付"
min-width=
"150"
align=
"right"
/>
<el-table-column
prop=
"payoutProcessing"
label=
"Processing 待入账"
min-width=
"160"
align=
"right"
/>
<el-table-column
prop=
"payoutFailed"
label=
"Failed 入账失败"
min-width=
"150"
align=
"right"
/>
</el-table-column>
</el-table>
</el-card>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
const
expanded
=
ref
(
true
);
const
selectedShop
=
ref
(
'USLCHNEAYD'
);
const
granularity
=
ref
(
'按日'
);
const
timezone
=
ref
(
'GMT-8'
);
const
range
=
ref
<
[
Date
,
Date
]
|
''
>
(
''
);
const
tableTab
=
ref
(
'店铺数据'
);
const
granularityTabs
=
[
'按日'
,
'按周'
,
'按月'
];
const
tableTabs
=
[
'店铺数据'
,
'订单数据'
];
const
shops
=
[
{
name
:
'SANDBOX7397710...'
,
code
:
'USLCHNEAYD'
,
type
:
'本地'
},
{
name
:
'GLOBAL_STORE_UK_01'
,
code
:
'UK88291045'
,
type
:
'跨境'
},
];
const
metrics
=
[
{
label
:
'Statements-Processing'
,
value
:
'$0'
},
{
label
:
'Statements-Paid'
,
value
:
'$0'
},
{
label
:
'Statements-Failed'
,
value
:
'$0'
},
{
label
:
'Payouts-Paid'
,
value
:
'$0'
},
{
label
:
'Payouts-Processing'
,
value
:
'$0'
},
{
label
:
'Payouts-Failed'
,
value
:
'$0'
},
{
label
:
'总订单数'
,
value
:
'0'
},
{
label
:
'总订单金额'
,
value
:
'$0'
},
{
label
:
'未支付订单数'
,
value
:
'0'
},
{
label
:
'未支付订单金额'
,
value
:
'$0'
},
{
label
:
'取消订单数'
,
value
:
'0'
},
{
label
:
'取消订单金额'
,
value
:
'$0'
},
{
label
:
'退货退款订单数'
,
value
:
'0'
},
{
label
:
'退货退款订单金额'
,
value
:
'$0'
},
];
const
tableRows
=
[
{
name
:
'SANDBOX7397710...'
,
code
:
'USLCHNEAYD'
,
statementProcessing
:
'$0.00'
,
statementPaid
:
'$0.00'
,
statementFailed
:
'$0.00'
,
payoutPaid
:
'$0.00'
,
payoutProcessing
:
'$0.00'
,
payoutFailed
:
'$0.00'
},
{
name
:
'GLOBAL_STORE_UK_01'
,
code
:
'UK88291045'
,
statementProcessing
:
'$0.00'
,
statementPaid
:
'$0.00'
,
statementFailed
:
'$0.00'
,
payoutPaid
:
'$0.00'
,
payoutProcessing
:
'$0.00'
,
payoutFailed
:
'$0.00'
},
];
const
authorizeShop
=
()
=>
ElMessage
.
success
(
'已打开店铺授权流程'
);
const
analyzeShop
=
(
code
:
string
)
=>
ElMessage
.
success
(
`正在分析店铺
${
code
}
`
);
const
moreShopActions
=
(
code
:
string
)
=>
ElMessage
.
info
(
`已打开
${
code
}
的更多操作`
);
const
exportData
=
()
=>
ElMessage
.
success
(
'已生成导出任务'
);
</
script
>
<
style
scoped
lang=
"scss"
>
.report-card
{
border
:
1px
solid
#dfe7f2
;
}
.shop-card
{
flex
:
0
0
calc
((
100%
-
64px
)
/
5
);
border
:
1px
solid
#eadffd
;
background
:
#faf7ff
;
&
.selected
{
box-shadow
:
0
0
0
1px
rgba
(
var
(
--
main-color
)
,
.45
)
inset
;
}
}
.tiktok-logo
{
flex-shrink
:
0
;
}
.minw-0
{
min-width
:
0
;
}
.shop-tag
{
background
:
#d9fbe8
;
color
:
#00875a
;
}
.shop-code
{
color
:
#607086
;
}
.metric-grid
{
display
:
grid
;
grid-template-columns
:
repeat
(
5
,
minmax
(
180px
,
1fr
));
gap
:
12px
;
}
.metric-card
{
border
:
1px
solid
#dfe7f2
;
background
:
#fbfdff
;
}
.metric-label
{
color
:
#48607f
;
}
.metric-value
{
color
:
#001a3d
;
}
.metric-compare
{
color
:
#8aa0bf
;
}
.text-tab
{
height
:
34px
;
padding
:
0
;
border-bottom
:
2px
solid
transparent
;
color
:
#3f5574
;
&
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom-color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f5f5f5
;
color
:
#888
;
padding
:
12px
0
;
}
}
@media
(
max-width
:
1600px
)
{
.shop-card
{
flex-basis
:
calc
((
100%
-
48px
)
/
4
);
}
}
@media
(
max-width
:
1000px
)
{
.shop-card
{
flex-basis
:
calc
((
100%
-
32px
)
/
3
);
}
}
@media
(
max-width
:
1200px
)
{
.metric-grid
{
grid-template-columns
:
repeat
(
2
,
minmax
(
240px
,
1fr
));
}
}
</
style
>
apps/web-vue/src/views/analysis/components/Team/Tab1.vue
0 → 100644
View file @
034d0c1b
<
template
>
<div
class=
"flex-col gap-16"
>
<section
class=
"insight-hero flex-between gap-16 p-20 round-12 color-fff"
>
<div
class=
"flex-items-center gap-16"
>
<button
v-for=
"item in insightTabs"
:key=
"item.value"
class=
"hero-tab flex-items-center gap-8 px-18 py-10 round-10 border-none color-fff font-bold pointer"
:class=
"
{ active: insightType === item.value }" @click="insightType = item.value">
<span>
{{
item
.
icon
}}
</span>
{{
item
.
label
}}
</button>
</div>
<div
class=
"flex-col items-center gap-10"
>
<div
class=
"flex-items-center gap-8"
>
<el-select
v-model=
"sourceRole"
class=
"hero-select w-160"
>
<el-option
label=
"致上运营"
value=
"致上运营"
/>
<el-option
label=
"默认部门"
value=
"默认部门"
/>
</el-select>
<span
class=
"px-12 py-6 round-10"
>
VS
</span>
<el-select
v-model=
"targetRole"
class=
"hero-select w-160"
>
<el-option
label=
"抖音1"
value=
"抖音1"
/>
<el-option
label=
"B部门"
value=
"B部门"
/>
</el-select>
</div>
<el-button
class=
"hero-action px-22"
round
@
click=
"showLeaderInsight"
>
领导力洞察
</el-button>
</div>
<div
class=
"w-300"
>
<el-date-picker
v-model=
"range"
class=
"hero-date"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
style=
"width: 100%;"
/>
</div>
</section>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between pb-12"
>
<div
class=
"flex-items-center gap-8"
>
<span
class=
"font-bold fs-16"
>
雷达图分析
</span>
<span
class=
"fs-12 color-8aa"
>
(
{{
sourceRole
}}
对比
{{
targetRole
}}
)
</span>
</div>
<el-button
type=
"primary"
@
click=
"exportData"
>
导出
</el-button>
</div>
<div
class=
"radar-wrap flex-center"
>
<v-chart
class=
"radar-chart"
:option=
"radarOption"
autoresize
/>
</div>
</el-card>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
VChart
from
'vue-echarts'
;
import
{
use
}
from
'echarts/core'
;
import
{
CanvasRenderer
}
from
'echarts/renderers'
;
import
{
RadarChart
}
from
'echarts/charts'
;
import
{
LegendComponent
,
TooltipComponent
}
from
'echarts/components'
;
import
{
ElMessage
}
from
'element-plus'
;
use
([
CanvasRenderer
,
RadarChart
,
TooltipComponent
,
LegendComponent
]);
const
insightType
=
ref
(
'personal'
);
const
sourceRole
=
ref
(
'致上运营'
);
const
targetRole
=
ref
(
'抖音1'
);
const
range
=
ref
<
[
Date
,
Date
]
|
''
>
(
''
);
const
insightTabs
=
[
{
label
:
'个人数据洞察'
,
value
:
'personal'
,
icon
:
'♙'
},
{
label
:
'小组数据洞察'
,
value
:
'team'
,
icon
:
'♧'
},
];
const
radarOption
=
computed
(()
=>
({
color
:
[
'#3f82ff'
,
'#8b5cf6'
],
tooltip
:
{},
legend
:
{
bottom
:
8
,
itemWidth
:
12
,
itemHeight
:
12
,
data
:
[
sourceRole
.
value
,
targetRole
.
value
],
textStyle
:
{
color
:
'#24405f'
,
fontWeight
:
700
},
},
radar
:
{
center
:
[
'50%'
,
'47%'
],
radius
:
150
,
splitNumber
:
5
,
axisName
:
{
color
:
'#48607f'
,
fontWeight
:
700
},
splitLine
:
{
lineStyle
:
{
color
:
'#e2ebf7'
,
type
:
'dashed'
}
},
splitArea
:
{
areaStyle
:
{
color
:
[
'rgba(63,130,255,.02)'
,
'rgba(63,130,255,.04)'
]
}
},
axisLine
:
{
lineStyle
:
{
color
:
'#d9e4f2'
}
},
indicator
:
[
{
name
:
'消耗力'
,
max
:
100
},
{
name
:
'贡献度'
,
max
:
100
},
{
name
:
'多样性'
,
max
:
100
},
{
name
:
'爆片率'
,
max
:
100
},
{
name
:
'勤奋度'
,
max
:
100
},
{
name
:
'创造力'
,
max
:
100
},
],
},
series
:
[
{
type
:
'radar'
,
symbolSize
:
8
,
areaStyle
:
{
opacity
:
0.18
},
data
:
[
{
name
:
sourceRole
.
value
,
value
:
[
35
,
78
,
38
,
45
,
86
,
78
]
},
{
name
:
targetRole
.
value
,
value
:
[
48
,
36
,
46
,
38
,
42
,
28
]
},
],
},
],
}));
const
showLeaderInsight
=
()
=>
ElMessage
.
success
(
'已生成领导力洞察'
);
const
exportData
=
()
=>
ElMessage
.
success
(
'已生成导出任务'
);
</
script
>
<
style
scoped
lang=
"scss"
>
.insight-hero
{
min-height
:
110px
;
background
:
linear-gradient
(
110deg
,
#3f82f6
0%
,
#8a4ce6
100%
);
box-shadow
:
0
12px
28px
rgba
(
63
,
130
,
246
,
.18
);
}
.hero-tab
{
background
:
transparent
;
&
.active
{
background
:
rgba
(
255
,
255
,
255
,
.16
);
box-shadow
:
0
0
0
1px
rgba
(
255
,
255
,
255
,
.35
)
inset
;
}
}
.hero-select
{
:deep
(
.el-select__wrapper
)
{
background
:
rgba
(
255
,
255
,
255
,
.18
);
border
:
1px
solid
rgba
(
255
,
255
,
255
,
.35
);
box-shadow
:
none
;
}
:deep
(
.el-select__selected-item
),
:deep
(
.el-select__placeholder
),
:deep
(
.el-select__caret
)
{
color
:
#fff
;
}
}
.vs-pill
,
.hero-action
{
background
:
rgba
(
255
,
255
,
255
,
.18
);
color
:
#fff
;
border
:
1px
solid
rgba
(
255
,
255
,
255
,
.35
);
}
.hero-date
{
:deep
(
.el-range-input
),
:deep
(
.el-range-separator
),
:deep
(
.el-icon
)
{
color
:
#fff
;
}
:deep
(
.el-input__wrapper
)
{
background
:
rgba
(
255
,
255
,
255
,
.18
);
box-shadow
:
0
0
0
1px
rgba
(
255
,
255
,
255
,
.35
)
inset
;
}
}
.report-card
{
border
:
1px
solid
#dfe7f2
;
}
.radar-wrap
{
min-height
:
470px
;
}
.radar-chart
{
width
:
560px
;
height
:
430px
;
}
.color-8aa
{
color
:
#8aa0bf
;
}
</
style
>
apps/web-vue/src/views/analysis/components/Team/Tab2.vue
0 → 100644
View file @
034d0c1b
<
template
>
<div
class=
"analysis-panel bg-fff round-8 p-24"
>
<div
class=
"flex-items-center gap-34 page-tabs pb-14"
>
<button
v-for=
"item in dataTabs"
:key=
"item"
class=
"text-tab border-none bg-none font-bold pointer"
:class=
"
{ active: dataTab === item }" @click="dataTab = item">
{{
item
}}
</button>
</div>
<div
class=
"flex-between flex-wrap gap-14 py-24"
>
<div
class=
"flex-items-center gap-12 flex-wrap"
>
<el-segmented
v-model=
"contentType"
:options=
"contentTabs"
/>
<el-select
v-model=
"department"
class=
"w-160"
placeholder=
"请选择部门"
>
<el-option
v-for=
"item in departments"
:key=
"item"
:label=
"item"
:value=
"item"
/>
</el-select>
</div>
<div
class=
"flex-items-center gap-12"
>
<el-select
v-model=
"summaryType"
class=
"w-90"
>
<el-option
label=
"汇总"
value=
"汇总"
/>
<el-option
label=
"明细"
value=
"明细"
/>
</el-select>
<el-date-picker
v-model=
"range"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
/>
</div>
</div>
<el-card
class=
"report-card round-8"
shadow=
"never"
>
<div
class=
"flex-between chart-tabs pb-10"
>
<div
class=
"flex-items-center gap-26"
>
<button
v-for=
"item in chartTabs"
:key=
"item"
class=
"text-tab small border-none bg-none font-bold pointer"
:class=
"
{ active: chartTab === item }" @click="chartTab = item">
{{
item
}}
</button>
</div>
<el-button
link
type=
"primary"
@
click=
"collapsed = !collapsed"
>
{{
collapsed
?
'展开'
:
'收起'
}}
</el-button>
</div>
<div
v-show=
"!collapsed"
class=
"pt-16"
>
<div
class=
"flex-between gap-12 mb-16"
>
<div
class=
"flex-items-center gap-10"
>
<el-segmented
v-model=
"metric"
:options=
"metricTabs"
/>
<el-select
v-model=
"rankLimit"
class=
"w-200"
>
<el-option
label=
"显示top5"
value=
"top5"
/>
<el-option
label=
"显示top10"
value=
"top10"
/>
</el-select>
</div>
<div
class=
"flex-items-center gap-18 flex-wrap"
>
<span
v-for=
"item in legendItems"
:key=
"item.name"
class=
"flex-items-center gap-6 fs-12"
>
<span
class=
"w-8 h-8 round"
:style=
"
{ backgroundColor: item.color }">
</span>
{{
item
.
name
}}
</span>
</div>
</div>
<div
class=
"chart-box round-8"
>
<v-chart
class=
"w-full h-full"
:option=
"lineOption"
autoresize
/>
</div>
</div>
</el-card>
<div
class=
"flex-between mt-30 mb-14"
>
<span
class=
"font-bold fs-16"
>
详细数据
</span>
<div
class=
"flex-items-center gap-8"
>
<el-button
@
click=
"exportData"
>
导出数据
</el-button>
<el-button
class=
"w-34 p-0"
@
click=
"fieldVisible = !fieldVisible"
>
☷
</el-button>
</div>
</div>
<el-alert
v-if=
"fieldVisible"
class=
"mb-10"
title=
"已打开字段配置面板"
type=
"info"
show-icon
:closable=
"false"
/>
<el-table
:data=
"tableRows"
class=
"analysis-table"
row-key=
"department"
>
<el-table-column
prop=
"date"
label=
"数据时间"
min-width=
"190"
/>
<el-table-column
prop=
"department"
label=
"部门名称"
min-width=
"160"
>
<template
#
default=
"
{ row }">
<span
class=
"color-main font-bold"
>
{{
row
.
department
}}
</span></
template
>
</el-table-column>
<el-table-column
prop=
"uploadPeople"
label=
"上传人数 ⓘ ↑↓"
align=
"center"
/>
<el-table-column
prop=
"uploadCount"
label=
"上传次数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"downloadCount"
label=
"下载次数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"downloadPeople"
label=
"被下载人数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"pushPeople"
label=
"被推送人数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"copyPeople"
label=
"被复制剪映人数 ↑↓"
align=
"center"
/>
<el-table-column
prop=
"usage"
label=
"作品被使用率 ⓘ ↑↓"
align=
"center"
/>
<el-table-column
prop=
"viral"
label=
"爆款视频数 ↑↓"
align=
"center"
>
<
template
#
default=
"{ row }"
><span
class=
"color-8aa"
>
{{
row
.
viral
}}
</span></
template
>
</el-table-column>
</el-table>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
VChart
from
'vue-echarts'
;
import
{
use
}
from
'echarts/core'
;
import
{
LineChart
}
from
'echarts/charts'
;
import
{
GridComponent
,
LegendComponent
,
TooltipComponent
}
from
'echarts/components'
;
import
{
CanvasRenderer
}
from
'echarts/renderers'
;
import
{
ElMessage
}
from
'element-plus'
;
use
([
CanvasRenderer
,
LineChart
,
GridComponent
,
TooltipComponent
,
LegendComponent
]);
const
dataTab
=
ref
(
'部门数据'
);
const
contentType
=
ref
(
'全部'
);
const
department
=
ref
(
''
);
const
summaryType
=
ref
(
'汇总'
);
const
range
=
ref
<
[
Date
,
Date
]
|
''
>
(
''
);
const
chartTab
=
ref
(
'时间趋势'
);
const
metric
=
ref
(
'上传'
);
const
rankLimit
=
ref
(
'top5'
);
const
collapsed
=
ref
(
false
);
const
fieldVisible
=
ref
(
false
);
const
dataTabs
=
[
'部门数据'
,
'分组数据'
,
'个人数据'
];
const
contentTabs
=
[
'全部'
,
'成片'
,
'素材'
,
'第三方'
,
'图片'
,
'音频'
];
const
chartTabs
=
[
'时间趋势'
,
'占比分析'
];
const
metricTabs
=
[
'上传'
,
'下载'
,
'复制到剪映'
];
const
departments
=
[
'默认部门'
,
'B部门'
,
'Ian部门1'
,
'7-20部门2'
,
'A部门'
];
const
legendItems
=
[
{
name
:
'默认部门'
,
color
:
'#6366f1'
},
{
name
:
'B部门'
,
color
:
'#10b981'
},
{
name
:
'Ian部门1'
,
color
:
'#f59e0b'
},
{
name
:
'7-20部门2'
,
color
:
'#ef4444'
},
{
name
:
'A部门'
,
color
:
'#06b6d4'
},
];
const
dates
=
[
'2025-04-06'
,
'2025-04-08'
,
'2025-04-10'
,
'2025-04-12'
,
'2025-04-14'
,
'2025-04-16'
,
'2025-04-18'
,
'2025-04-20'
];
const
tableRows
=
[
{
date
:
'2025-04-06-2025-04-21'
,
department
:
'默认部门'
,
uploadPeople
:
1
,
uploadCount
:
47
,
downloadCount
:
120
,
downloadPeople
:
22
,
pushPeople
:
8
,
copyPeople
:
12
,
usage
:
'59.57'
,
viral
:
0
},
{
date
:
'2025-04-06-2025-04-21'
,
department
:
'B部门'
,
uploadPeople
:
1
,
uploadCount
:
6
,
downloadCount
:
1
,
downloadPeople
:
0
,
pushPeople
:
1
,
copyPeople
:
1
,
usage
:
'33.33'
,
viral
:
0
},
{
date
:
'2025-04-06-2025-04-21'
,
department
:
'Ian部门1'
,
uploadPeople
:
1
,
uploadCount
:
3
,
downloadCount
:
0
,
downloadPeople
:
0
,
pushPeople
:
0
,
copyPeople
:
0
,
usage
:
'0.00'
,
viral
:
0
},
{
date
:
'2025-04-06-2025-04-21'
,
department
:
'7-20部门2'
,
uploadPeople
:
1
,
uploadCount
:
3
,
downloadCount
:
0
,
downloadPeople
:
0
,
pushPeople
:
0
,
copyPeople
:
0
,
usage
:
'0.00'
,
viral
:
0
},
{
date
:
'2025-04-06-2025-04-21'
,
department
:
'A部门'
,
uploadPeople
:
0
,
uploadCount
:
0
,
downloadCount
:
0
,
downloadPeople
:
0
,
pushPeople
:
0
,
copyPeople
:
0
,
usage
:
'0.00'
,
viral
:
0
},
];
const
lineOption
=
computed
(()
=>
({
color
:
legendItems
.
map
((
item
)
=>
item
.
color
),
tooltip
:
{
trigger
:
'axis'
},
legend
:
{
show
:
false
},
grid
:
{
left
:
54
,
right
:
40
,
top
:
35
,
bottom
:
42
},
xAxis
:
{
type
:
'category'
,
boundaryGap
:
false
,
data
:
dates
,
axisLabel
:
{
color
:
'#8aa0bf'
},
axisLine
:
{
lineStyle
:
{
color
:
'#edf3fb'
}
}
},
yAxis
:
{
type
:
'value'
,
splitLine
:
{
lineStyle
:
{
color
:
'#edf3fb'
,
type
:
'dashed'
}
},
axisLabel
:
{
color
:
'#8aa0bf'
}
},
series
:
[
{
name
:
'默认部门'
,
type
:
'line'
,
smooth
:
true
,
symbolSize
:
7
,
areaStyle
:
{
opacity
:
.
18
},
data
:
[
0
,
4
,
2
,
1
,
0
,
6
,
35
,
1
]
},
{
name
:
'B部门'
,
type
:
'line'
,
smooth
:
true
,
symbolSize
:
7
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
]
},
{
name
:
'Ian部门1'
,
type
:
'line'
,
smooth
:
true
,
symbolSize
:
7
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
]
},
{
name
:
'7-20部门2'
,
type
:
'line'
,
smooth
:
true
,
symbolSize
:
7
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
]
},
{
name
:
'A部门'
,
type
:
'line'
,
smooth
:
true
,
symbolSize
:
7
,
data
:
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
]
},
],
}));
const
exportData
=
()
=>
ElMessage
.
success
(
'已生成导出任务'
);
</
script
>
<
style
scoped
lang=
"scss"
>
.analysis-panel
{
border
:
1px
solid
#dfe7f2
;
}
.page-tabs
,
.chart-tabs
{
border-bottom
:
1px
solid
#edf0f5
;
}
.text-tab
{
height
:
36px
;
padding
:
0
;
border-bottom
:
2px
solid
transparent
;
color
:
#10233f
;
&
.small
{
height
:
34px
;
}
&
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom-color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.report-card
,
.chart-box
{
border
:
1px
solid
#dfe7f2
;
}
.chart-box
{
height
:
240px
;
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f8fbff
;
color
:
#48607f
;
font-weight
:
700
;
}
}
.color-8aa
{
color
:
#8aa0bf
;
}
</
style
>
apps/web-vue/src/views/analysis/components/Team/Tab3.vue
0 → 100644
View file @
034d0c1b
This diff is collapsed.
Click to expand it.
apps/web-vue/src/views/analysis/components/Team/TaskDetailDialog.vue
0 → 100644
View file @
034d0c1b
<
template
>
<Dialog
v-model=
"visible"
bg-color=
"#fff"
width=
"900"
>
<div
class=
"bg-fff round-12 hidden"
>
<div
class=
"dialog-header h-64 px-26 flex-items-center"
>
<span
class=
"color-main fs-18 mr-10"
>
⊙
</span>
<span
class=
"fs-16 font-bold color-000"
>
任务详情列表 -
{{
departmentName
}}
</span>
</div>
<div
class=
"px-26 pt-16 pb-26"
>
<el-table
:data=
"detailRows"
class=
"detail-table"
row-key=
"id"
>
<el-table-column
prop=
"id"
label=
"任务编号"
min-width=
"130"
/>
<el-table-column
prop=
"name"
label=
"任务名称"
min-width=
"170"
>
<template
#
default=
"
{ row }">
<span
class=
"color-main"
>
{{
row
.
name
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"target"
label=
"目标出片"
width=
"80"
align=
"center"
/>
<el-table-column
prop=
"finished"
label=
"实际完成"
width=
"80"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"color-green"
>
{{
row
.
finished
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"状态"
width=
"90"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"status-tag px-8 py-4 round-4"
:class=
"row.status === '已达标' ? 'success' : 'pending'"
>
{{
row
.
status
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"time"
label=
"时间"
width=
"200"
align=
"center"
/>
</el-table>
<div
class=
"flex justify-end mt-26"
>
<el-button
type=
"primary"
class=
"w-64"
@
click=
"visible = false"
>
关闭
</el-button>
</div>
</div>
</div>
</Dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
}
from
'vue'
;
import
Dialog
from
'@/components/Dialog/index.vue'
;
const
visible
=
defineModel
<
boolean
>
(
'visible'
,
{
required
:
true
});
const
props
=
defineProps
<
{
department
?:
string
;
}
>
();
const
departmentName
=
computed
(()
=>
props
.
department
||
'部门'
);
const
detailRows
=
computed
(()
=>
[
{
id
:
'TSK_20250410_01'
,
name
:
'美妆搜索对比视频批量制作'
,
target
:
20
,
finished
:
20
,
status
:
'已达标'
,
time
:
'2025-04-07 10:15'
},
{
id
:
'TSK_20250415_02'
,
name
:
'痛点拆解口播卡点视频'
,
target
:
15
,
finished
:
8
,
status
:
'待完成'
,
time
:
'2025-04-12 16:30'
},
]);
</
script
>
<
style
scoped
lang=
"scss"
>
.dialog-header
{
border-bottom
:
1px
solid
#edf0f5
;
}
.detail-table
{
border
:
1px
solid
#dfe7f2
;
border-radius
:
8px
;
overflow
:
hidden
;
:deep
(
.el-table__header
th
)
{
background
:
#f8fbff
;
color
:
#48607f
;
font-weight
:
700
;
}
}
.color-green
{
color
:
#00a86b
;
}
.status-tag
{
display
:
inline-block
;
line-height
:
18px
;
&
.success
{
color
:
#00a86b
;
background
:
#e9fbf3
;
}
&
.pending
{
color
:
#246bfe
;
background
:
#eef4ff
;
}
}
</
style
>
apps/web-vue/src/views/analysis/components/Team/TaskStatsDialog.vue
0 → 100644
View file @
034d0c1b
<
template
>
<Dialog
v-model=
"visible"
bg-color=
"#fff"
width=
"520"
>
<div
class=
"bg-fff round-12 hidden"
>
<div
class=
"dialog-header h-64 px-26 flex-items-center"
>
<span
class=
"w-4 h-18 round-10 bg-main mr-10"
></span>
<span
class=
"fs-16 font-bold color-000"
>
数据汇总
</span>
</div>
<div
class=
"px-26 pt-18 pb-24"
>
<div
class=
"summary-table round-8 hidden"
>
<div
class=
"summary-row"
>
<div
class=
"summary-label px-18 py-12 font-bold"
>
下单数量
</div>
<div
class=
"px-18 py-12 font-bold"
>
{{
stats
.
orders
}}
</div>
</div>
<div
class=
"summary-row"
>
<div
class=
"summary-label px-18 py-12 font-bold"
>
出片数量
</div>
<div
class=
"px-18 py-12 font-bold"
>
{{
stats
.
published
}}
</div>
</div>
</div>
<div
class=
"mt-18 mb-8 font-bold color-000"
>
状态汇总
</div>
<div
class=
"summary-table round-8 hidden"
>
<div
v-for=
"item in statusRows"
:key=
"item.label"
class=
"status-row"
>
<div
class=
"summary-label px-18 py-10 font-bold"
>
{{
item
.
label
}}
</div>
<div
class=
"px-18 py-10 text-center"
>
{{
item
.
rate
}}
</div>
<div
class=
"summary-label px-18 py-10 text-center font-bold"
>
数量
</div>
<div
class=
"px-18 py-10 text-center font-bold"
>
{{
item
.
count
}}
</div>
</div>
</div>
<div
class=
"flex justify-end mt-28"
>
<el-button
type=
"primary"
class=
"w-64"
@
click=
"visible = false"
>
确定
</el-button>
</div>
</div>
</div>
</Dialog>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
}
from
'vue'
;
import
Dialog
from
'@/components/Dialog/index.vue'
;
const
visible
=
defineModel
<
boolean
>
(
'visible'
,
{
required
:
true
});
const
props
=
defineProps
<
{
row
?:
{
orders
?:
number
;
published
?:
number
;
reached
?:
number
;
pending
?:
number
;
};
}
>
();
const
stats
=
computed
(()
=>
({
orders
:
props
.
row
?.
orders
??
0
,
published
:
props
.
row
?.
published
??
0
,
reached
:
props
.
row
?.
reached
??
0
,
pending
:
props
.
row
?.
pending
??
0
,
}));
const
statusRows
=
computed
(()
=>
{
const
total
=
stats
.
value
.
reached
+
stats
.
value
.
pending
;
const
rate
=
(
value
:
number
)
=>
(
total
?
`
${
Math
.
round
((
value
/
total
)
*
100
)}
%`
:
'0%'
);
return
[
{
label
:
'已上机'
,
rate
:
rate
(
stats
.
value
.
reached
),
count
:
stats
.
value
.
reached
},
{
label
:
'待审核'
,
rate
:
rate
(
stats
.
value
.
pending
),
count
:
stats
.
value
.
pending
},
];
});
</
script
>
<
style
scoped
lang=
"scss"
>
.dialog-header
{
border-bottom
:
1px
solid
#edf0f5
;
}
.summary-table
{
border
:
1px
solid
#dfe7f2
;
}
.summary-row
{
display
:
grid
;
grid-template-columns
:
1fr
1
.6fr
;
border-bottom
:
1px
solid
#edf0f5
;
&
:last-child
{
border-bottom
:
none
;
}
}
.status-row
{
display
:
grid
;
grid-template-columns
:
1fr
1fr
.5fr
.5fr
;
border-bottom
:
1px
solid
#edf0f5
;
&
:last-child
{
border-bottom
:
none
;
}
}
.summary-label
{
background
:
#f8fbff
;
color
:
#48607f
;
}
</
style
>
apps/web-vue/src/views/analysis/components/AdPlatformTags.vue
→
apps/web-vue/src/views/analysis/components/
video/
AdPlatformTags.vue
View file @
034d0c1b
...
...
@@ -21,7 +21,8 @@
<el-option
label=
"全部分类"
value=
"all"
/>
<el-option
label=
"服饰鞋包"
value=
"clothes"
/>
</el-select>
<div
class=
"w-240 mx-10"
>
<div
class=
"w-400 mx-10 flex-items-center"
>
<div
class=
"minw-70 color-888"
>
消耗时间:
</div>
<el-date-picker
v-model=
"dateRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
style=
"width: 100% !important;"
/>
</div>
...
...
@@ -35,28 +36,34 @@
<div
class=
"pb-16 flex-between ratio-title"
>
<span
class=
"fs-16 font-bold color-000"
>
占比分析
</span>
<el-button
type=
"primary"
link
@
click=
"collapsed = !collapsed"
>
{{
collapsed
?
'展开'
:
'收起'
}}
</el-button>
}}
</el-button>
</div>
<div
v-show=
"!collapsed"
class=
"p-20 flex gap-26"
>
<div
class=
"flex-1 gap-14 card-grid"
>
<div
v-for=
"item in ratioList"
:key=
"item.name"
class=
"p-18 round-6 flex-between metric-card"
>
<div
class=
"flex-items-center"
>
<div
class=
"flex-items-center
w-full
"
>
<span
class=
"w-42 h-42 round-8 flex-center fs-20"
:style=
"
{ color: item.color, backgroundColor: item.bg }">
{{
item
.
icon
}}
</span>
<div
class=
"ml-16"
>
<div
class=
"ml-16
flex-1
"
>
<div
class=
"font-bold color-000"
>
{{
item
.
name
}}
</div>
<div
class=
"mt-8"
>
数量:
<span
class=
"font-bold"
>
{{
item
.
count
.
toLocaleString
()
}}
</span>
</div>
<div
class=
"mt-6"
>
消耗:
<span
class=
"font-bold"
>
¥
{{
item
.
cost
.
toLocaleString
()
}}
</span>
<div
class=
"flex flex-between mt-10"
>
<div>
<div>
数量:
<span
class=
"font-bold"
>
{{
item
.
count
.
toLocaleString
()
}}
</span>
</div>
<div>
消耗:
<span
class=
"font-bold"
>
¥
{{
item
.
cost
.
toLocaleString
()
}}
</span>
</div>
</div>
<div
class=
"lh-24"
>
<div>
数量占比:
<span
class=
"font-bold"
>
{{
item
.
countRate
}}
%
</span></div>
<div>
消耗占比:
<span
class=
"font-bold"
>
{{
item
.
costRate
}}
%
</span></div>
</div>
</div>
</div>
</div>
<div
class=
"lh-24"
>
<div>
数量占比:
<span
class=
"font-bold"
>
{{
item
.
countRate
}}
%
</span></div>
<div>
消耗占比:
<span
class=
"font-bold"
>
{{
item
.
costRate
}}
%
</span></div>
</div>
</div>
</div>
<div
class=
"flex-1 minw-400 flex-items-center justify-center chart-panel"
>
...
...
@@ -87,7 +94,7 @@
<el-table
:data=
"pagedTableData"
class=
"analysis-table"
>
<el-table-column
prop=
"account"
label=
"广告账户"
min-width=
"210"
show-overflow-tooltip
/>
<el-table-column
prop=
"subject"
label=
"主体"
min-width=
"180"
show-overflow-tooltip
/>
<el-table-column
prop=
"department"
label=
"
部门
"
width=
"130"
/>
<el-table-column
prop=
"department"
label=
"
团队
"
width=
"130"
/>
<el-table-column
prop=
"group"
label=
"分组"
width=
"120"
/>
<el-table-column
prop=
"user"
label=
"用户"
width=
"100"
/>
<el-table-column
prop=
"category1"
label=
"一级分类"
width=
"110"
/>
...
...
@@ -104,7 +111,7 @@
</el-table-column>
<el-table-column
prop=
"goodCost"
label=
"优质素材消耗"
width=
"140"
align=
"center"
>
<
template
#
default=
"{ row }"
><span
class=
"font-bold color-green"
>
{{
row
.
goodCost
}}
</span></
template
>
}}
</span></
template
>
</el-table-column>
<el-table-column
prop=
"low"
label=
"低效素材"
width=
"110"
align=
"center"
>
<
template
#
default=
"{ row }"
><span
class=
"font-bold color-main"
>
{{
row
.
low
}}
</span></
template
>
...
...
@@ -160,7 +167,7 @@ const platformTabs = [
{
label
:
'巨量千川'
,
value
:
'qianchuan'
,
icon
:
'Ⅲ'
},
{
label
:
'巨量广告'
,
value
:
'ad'
,
icon
:
'⊘'
},
];
const
scopes
=
[
'汇总'
,
'
部门
'
,
'分组'
,
'个人'
,
'广告账户'
];
const
scopes
=
[
'汇总'
,
'
团队
'
,
'分组'
,
'个人'
,
'广告账户'
];
const
ratioList
=
[
{
name
:
'首发素材'
,
count
:
1280
,
cost
:
342800
,
countRate
:
28.5
,
costRate
:
32.4
,
color
:
'#5046e5'
,
bg
:
'#f0efff'
,
icon
:
'⌘'
},
{
name
:
'优质素材'
,
count
:
860
,
cost
:
415200
,
countRate
:
19.1
,
costRate
:
39.2
,
color
:
'#ef3d3d'
,
bg
:
'#fff0f0'
,
icon
:
'♙'
},
...
...
@@ -239,9 +246,9 @@ const handleSizeChange = () => {
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f
8fbff
;
color
:
#
48607f
;
font-weight
:
bold
;
background
:
#f
5f5f5
;
color
:
#
888
;
padding
:
12px
0
;
}
}
...
...
apps/web-vue/src/views/analysis/components/DeliveryReport.vue
→
apps/web-vue/src/views/analysis/components/
video/
DeliveryReport.vue
View file @
034d0c1b
<
template
>
<div
class=
"p-6"
>
<
el-card
class=
"round-12 mt-10 filter-card"
shadow=
"hover
"
>
<
div
class=
"bg-fff pt-16 px-16 round-8
"
>
<div
class=
"flex-items-center gap-34 header-tabs"
>
<div
v-for=
"item in platforms"
:key=
"item"
class=
"pb-16 font-bold pointer"
:class=
"
{ active: platform === item }" @click="platform = item">
{{
item
}}
</div>
</div>
<div
class=
"py-14 sub-tabs"
>
<div
class=
"flex-items-center gap-24"
>
<span
v-for=
"item in scopes"
:key=
"item"
class=
"font-bold pointer"
:class=
"
{ 'color-main': scope === item }" @click="scope = item">
{{
item
}}
</span>
</div>
<div
class=
"flex-items-center gap-10"
>
<div
class=
"w-300 flex-items-center mr-10"
>
<div
class=
"w-90"
>
上传时间:
</div>
<el-date-picker
v-model=
"uploadRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
style=
"width: 100% !important;"
/>
</div>
<div
class=
"w-300 flex-items-center mr-10"
>
<div
class=
"w-90"
>
投放时间:
</div>
<el-date-picker
v-model=
"deliveryRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
style=
"width: 100% !important;"
/>
</div>
</div>
<el-card
class=
"round-12 mt-16 filter-card"
shadow=
"hover"
>
<div
class=
"flex-between pb-16 sub-tabs"
>
<div
class=
"flex-items-center gap-30"
>
<span
v-for=
"item in scopes"
:key=
"item"
class=
"pointer"
:class=
"
{ 'color-main': scope === item }"
@click="scope = item">
{{
item
}}
</span>
</div>
<div
class=
"flex-between mt-16"
>
<div
class=
""
>
<el-button
type=
"primary"
>
视频作者
</el-button>
<el-button
class=
"mr-10"
>
下单运营
</el-button>
<el-select
v-model=
"department"
class=
"w-180 mr-10"
placeholder=
"请选择部门"
/>
<el-select
v-model=
"category"
class=
"w-180 mr-10"
placeholder=
"请选择分类"
/>
<el-button
type=
"primary"
class=
"w-66"
plain
>
查询
</el-button>
<el-button>
重置
</el-button>
<div
class=
"flex-items-center gap-10"
>
<div
class=
"w-300 flex-items-center mr-10"
>
<div
class=
"w-90"
>
上传时间:
</div>
<el-date-picker
v-model=
"uploadRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
style=
"width: 100% !important;"
/>
</div>
<div>
<el-button>
导出数据
</el-button>
<el-button
class=
"w-34 h-34"
>
☷
</el-button>
<div
class=
"w-300 flex-items-center mr-10"
>
<div
class=
"w-90"
>
投放时间:
</div>
<el-date-picker
v-model=
"deliveryRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
style=
"width: 100% !important;"
/>
</div>
</div>
</div>
</el-card>
<div
class=
"flex-between my-16"
>
<el-radio-group
v-model=
"radioVal"
class=
"mr-10"
>
<el-radio-button
label=
"视频作者"
:value=
"1"
/>
<el-radio-button
label=
"下单运营"
:value=
"2"
/>
</el-radio-group>
<div
class=
"flex"
>
<el-select
v-model=
"department"
class=
"w-180 mr-10"
placeholder=
"请选择团队"
/>
<el-select
v-model=
"category"
class=
"w-180 mr-10"
placeholder=
"请选择分类"
/>
<el-button
type=
"primary"
class=
"w-66"
plain
>
查询
</el-button>
<el-button>
重置
</el-button>
<el-button>
导出数据
</el-button>
<el-button
class=
"w-34"
>
☷
</el-button>
</div>
</div>
<el-card
class=
"round-12 mt-16"
shadow=
"hover"
>
<el-table
:data=
"pagedTableData"
class=
"analysis-table"
>
<el-table-column
prop=
"department"
label=
"
部门
"
min-width=
"160"
/>
<el-table-column
prop=
"department"
label=
"
团队
"
min-width=
"160"
/>
<el-table-column
prop=
"cost"
label=
"消耗"
width=
"120"
align=
"center"
/>
<el-table-column
prop=
"roi"
label=
"roi"
width=
"90"
align=
"center"
/>
<el-table-column
prop=
"totalAmount"
label=
"总成交金额"
width=
"130"
align=
"center"
/>
...
...
@@ -70,24 +71,25 @@
<
script
setup
lang=
"ts"
>
import
{
computed
,
reactive
,
ref
}
from
'vue'
;
const
platform
=
ref
(
'巨量广告'
);
const
scope
=
ref
(
'
部门
'
);
const
scope
=
ref
(
'
团队
'
);
const
department
=
ref
(
''
);
const
category
=
ref
(
''
);
const
uploadRange
=
ref
(
''
);
const
deliveryRange
=
ref
(
''
);
const
radioVal
=
ref
(
1
)
const
pageData
=
reactive
({
currentPage
:
1
,
pageSize
:
10
,
pageSizes
:
[
10
,
20
,
50
,
100
],
});
const
platforms
=
[
'巨量广告'
,
'巨量千川'
,
'磁力智投'
,
'磁力金牛'
,
'百度营销'
,
'小红书'
];
const
scopes
=
[
'
部门
'
,
'分组'
,
'个人'
,
'明细'
,
'分日'
,
'分月'
];
const
scopes
=
[
'
团队
'
,
'分组'
,
'个人'
,
'明细'
,
'分日'
,
'分月'
];
const
tableData
=
[
{
department
:
'总计'
,
cost
:
'1375201.50'
,
roi
:
'3.69'
,
totalAmount
:
'¥5,074,860'
,
amount
:
'¥4,740,000'
,
coupon
:
'¥334,860'
,
conversions
:
'44,240'
,
rate
:
'4.54%'
,
costRate
:
'¥31.09'
,
show
:
'26,040,000'
,
avgCost
:
'¥52.81'
,
click
:
'974,510'
,
clickRate
:
'3.74%'
,
avgPrice
:
'¥1.41'
,
play
:
'22,300,000'
},
{
department
:
'项目1-爆款电商'
,
cost
:
'342100.80'
,
roi
:
'4.12'
,
totalAmount
:
'¥1,409,450'
,
amount
:
'¥1,320,000'
,
coupon
:
'¥89,450'
,
conversions
:
'11,400'
,
rate
:
'5.10%'
,
costRate
:
'¥30.01'
,
show
:
'6,450,000'
,
avgCost
:
'¥53.03'
,
click
:
'223,500'
,
clickRate
:
'3.46%'
,
avgPrice
:
'¥1.53'
,
play
:
'5,600,000'
},
{
department
:
'达人测试
部门
'
,
cost
:
'285400.00'
,
roi
:
'3.85'
,
totalAmount
:
'¥1,098,790'
,
amount
:
'¥1,020,000'
,
coupon
:
'¥78,790'
,
conversions
:
'9,240'
,
rate
:
'4.82%'
,
costRate
:
'¥30.88'
,
show
:
'5,120,000'
,
avgCost
:
'¥55.74'
,
click
:
'191,980'
,
clickRate
:
'3.75%'
,
avgPrice
:
'¥1.48'
,
play
:
'4,320,000'
},
{
department
:
'达人测试
团队
'
,
cost
:
'285400.00'
,
roi
:
'3.85'
,
totalAmount
:
'¥1,098,790'
,
amount
:
'¥1,020,000'
,
coupon
:
'¥78,790'
,
conversions
:
'9,240'
,
rate
:
'4.82%'
,
costRate
:
'¥30.88'
,
show
:
'5,120,000'
,
avgCost
:
'¥55.74'
,
click
:
'191,980'
,
clickRate
:
'3.75%'
,
avgPrice
:
'¥1.48'
,
play
:
'4,320,000'
},
{
department
:
'xx素颜霜项目'
,
cost
:
'220500.00'
,
roi
:
'3.68'
,
totalAmount
:
'¥811,440'
,
amount
:
'¥760,000'
,
coupon
:
'¥51,440'
,
conversions
:
'7,350'
,
rate
:
'4.50%'
,
costRate
:
'¥30.00'
,
show
:
'4,100,000'
,
avgCost
:
'¥53.78'
,
click
:
'163,330'
,
clickRate
:
'3.98%'
,
avgPrice
:
'¥1.35'
,
play
:
'3,680,000'
},
{
department
:
'小真测试
部门
'
,
cost
:
'196200.50'
,
roi
:
'3.42'
,
totalAmount
:
'¥671,000'
,
amount
:
'¥630,000'
,
coupon
:
'¥41,000'
,
conversions
:
'6,150'
,
rate
:
'4.25%'
,
costRate
:
'¥31.90'
,
show
:
'3,820,000'
,
avgCost
:
'¥51.36'
,
click
:
'144,700'
,
clickRate
:
'3.78%'
,
avgPrice
:
'¥1.35'
,
play
:
'3,100,000'
},
{
department
:
'小真测试
团队
'
,
cost
:
'196200.50'
,
roi
:
'3.42'
,
totalAmount
:
'¥671,000'
,
amount
:
'¥630,000'
,
coupon
:
'¥41,000'
,
conversions
:
'6,150'
,
rate
:
'4.25%'
,
costRate
:
'¥31.90'
,
show
:
'3,820,000'
,
avgCost
:
'¥51.36'
,
click
:
'144,700'
,
clickRate
:
'3.78%'
,
avgPrice
:
'¥1.35'
,
play
:
'3,100,000'
},
{
department
:
'抖音投放一组'
,
cost
:
'189000.20'
,
roi
:
'3.52'
,
totalAmount
:
'¥665,280'
,
amount
:
'¥620,000'
,
coupon
:
'¥45,280'
,
conversions
:
'5,980'
,
rate
:
'4.15%'
,
costRate
:
'¥31.60'
,
show
:
'3,600,000'
,
avgCost
:
'¥52.50'
,
click
:
'144,000'
,
clickRate
:
'4.00%'
,
avgPrice
:
'¥1.31'
,
play
:
'3,150,000'
},
];
const
pagedTableData
=
computed
(()
=>
{
...
...
@@ -105,7 +107,6 @@ const handleSizeChange = () => {
border
:
1px
solid
#dfe7f2
;
}
.header-tabs
,
.sub-tabs
,
.table-footer
{
border-bottom
:
1px
solid
#edf0f5
;
...
...
@@ -119,13 +120,14 @@ const handleSizeChange = () => {
.header-tabs
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom
:
2px
solid
rgba
(
var
(
--
main-color
)
,
1
);
box-sizing
:
content-box
;
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f
8fbff
;
color
:
#
48607f
;
font-weight
:
bold
;
background
:
#f
5f5f5
;
color
:
#
888
;
padding
:
12px
0
;
}
}
</
style
>
apps/web-vue/src/views/analysis/components/TagAnalysis.vue
→
apps/web-vue/src/views/analysis/components/
video/
TagAnalysis.vue
View file @
034d0c1b
...
...
@@ -208,9 +208,9 @@ const handleSizeChange = () => {
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f
8fbff
;
color
:
#
48607f
;
font-weight
:
bold
;
background
:
#f
5f5f5
;
color
:
#
888
;
padding
:
12px
0
;
}
}
</
style
>
apps/web-vue/src/views/analysis/components/TencentDeliveryReport.vue
→
apps/web-vue/src/views/analysis/components/
video/
TencentDeliveryReport.vue
View file @
034d0c1b
...
...
@@ -2,21 +2,30 @@
<div
class=
"p-6"
>
<el-card
class=
"bg-fff round-12 mt-10"
shadow=
"hover"
>
<div
class=
"flex-items-center gap-30 header-tabs"
>
<div
v-for=
"item in dataTabs"
:key=
"item"
class=
"pb-16 font-bold pointer"
:class=
"
{ active: dataTab === item }" @click="dataTab = item">
{{
item
}}
</div>
<div
v-for=
"item in dataTabs"
:key=
"item"
class=
"pb-16 font-bold pointer"
:class=
"
{ active: dataTab === item }" @click="dataTab = item">
{{
item
}}
</div>
</div>
<div
class=
"pt-16 flex-between"
>
<div
class=
"flex-items-center"
>
<el-button
type=
"primary"
>
汇总
</el-button>
<el-button
class=
"mr-10"
>
明细
</el-button>
<el-select
v-model=
"department"
class=
"w-180 mr-10"
placeholder=
"请选择部门"
><el-option
label=
"默认部门"
value=
"默认部门"
/></el-select>
<el-select
v-model=
"group"
class=
"w-180 mr-10"
placeholder=
"请选择"
><el-option
label=
"华南电商一队"
value=
"华南电商一队"
/></el-select>
<div
class=
"w-240 mr-10"
>
<el-date-picker
v-model=
"range"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"2022/04/27"
end-placeholder=
"2025/05/12"
style=
"width: 100% !important;"
/>
<div
class=
"pt-16"
>
<div
class=
"flex-between"
>
<div
class=
"flex"
>
<el-radio-group
v-model=
"radioVal"
class=
"mr-10"
>
<el-radio-button
label=
"汇总"
:value=
"1"
/>
<el-radio-button
label=
"明细"
:value=
"2"
/>
</el-radio-group>
<el-select
v-model=
"department"
class=
"w-180 mr-10"
placeholder=
"请选择团队"
><el-option
label=
"默认团队"
value=
"默认团队"
/></el-select>
<el-select
v-model=
"group"
class=
"w-180 mr-10"
placeholder=
"请选择"
><el-option
label=
"华南电商一队"
value=
"华南电商一队"
/></el-select>
<el-button
type=
"primary"
plain
>
查询
</el-button>
<el-button>
重置
</el-button>
</div>
<div
class=
"w-240"
>
<el-date-picker
v-model=
"range"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
style=
"width: 100% !important;"
/>
</div>
<el-button
type=
"primary"
plain
>
查询
</el-button>
<el-button>
重置
</el-button>
</div>
</div>
</el-card>
...
...
@@ -26,7 +35,7 @@
<el-button
type=
"default"
plain
>
导出数据
</el-button>
</div>
<el-table
:data=
"pagedTableData"
class=
"analysis-table"
>
<el-table-column
prop=
"department"
label=
"
部门
"
min-width=
"180"
/>
<el-table-column
prop=
"department"
label=
"
团队
"
min-width=
"180"
/>
<el-table-column
prop=
"cost"
label=
"消耗"
align=
"center"
/>
<el-table-column
prop=
"conversions"
label=
"转化数"
align=
"center"
/>
<el-table-column
prop=
"rate"
label=
"转化率"
align=
"center"
/>
...
...
@@ -39,15 +48,9 @@
<el-table-column
prop=
"complete"
label=
"3S完播率"
align=
"center"
/>
</el-table>
<div
class=
"px-20 py-12 flex justify-end table-footer"
>
<el-pagination
v-model:current-page=
"pageData.currentPage"
v-model:page-size=
"pageData.pageSize"
background
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"tableData.length"
:page-sizes=
"pageData.pageSizes"
@
size-change=
"handleSizeChange"
/>
<el-pagination
v-model:current-page=
"pageData.currentPage"
v-model:page-size=
"pageData.pageSize"
background
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"tableData.length"
:page-sizes=
"pageData.pageSizes"
@
size-change=
"handleSizeChange"
/>
</div>
</el-card>
</div>
...
...
@@ -55,19 +58,20 @@
<
script
setup
lang=
"ts"
>
import
{
computed
,
reactive
,
ref
}
from
'vue'
;
const
dataTab
=
ref
(
'
部门
数据'
);
const
dataTab
=
ref
(
'
团队
数据'
);
const
department
=
ref
(
''
);
const
group
=
ref
(
''
);
const
range
=
ref
(
''
);
const
radioVal
=
ref
(
1
)
const
pageData
=
reactive
({
currentPage
:
1
,
pageSize
:
10
,
pageSizes
:
[
10
,
20
,
50
,
100
],
});
const
dataTabs
=
[
'
部门
数据'
,
'分组数据'
,
'个人数据'
];
const
dataTabs
=
[
'
团队
数据'
,
'分组数据'
,
'个人数据'
];
const
tableData
=
[
{
department
:
'总计'
,
cost
:
'361051.50'
,
conversions
:
'11,550'
,
rate
:
'4.27%'
,
costRate
:
'¥31.26'
,
show
:
'6,880,000'
,
click
:
'270,530'
,
clickRate
:
'3.93%'
,
avgPrice
:
'1.33'
,
play
:
'5,860,000'
,
complete
:
'20.6%'
},
{
department
:
'默认
部门
'
,
cost
:
'128450.50'
,
conversions
:
'4,210'
,
rate
:
'4.12%'
,
costRate
:
'¥30.50'
,
show
:
'2,450,000'
,
click
:
'98,200'
,
clickRate
:
'4.01%'
,
avgPrice
:
'1.31'
,
play
:
'2,100,000'
,
complete
:
'22.5%'
},
{
department
:
'默认
团队
'
,
cost
:
'128450.50'
,
conversions
:
'4,210'
,
rate
:
'4.12%'
,
costRate
:
'¥30.50'
,
show
:
'2,450,000'
,
click
:
'98,200'
,
clickRate
:
'4.01%'
,
avgPrice
:
'1.31'
,
play
:
'2,100,000'
,
complete
:
'22.5%'
},
{
department
:
'华南电商一队'
,
cost
:
'96200.80'
,
conversions
:
'3,120'
,
rate
:
'3.95%'
,
costRate
:
'¥30.83'
,
show
:
'1,820,000'
,
click
:
'74,620'
,
clickRate
:
'4.10%'
,
avgPrice
:
'1.29'
,
play
:
'1,560,000'
,
complete
:
'21.2%'
},
{
department
:
'华东投放二队'
,
cost
:
'84300.00'
,
conversions
:
'2,680'
,
rate
:
'3.78%'
,
costRate
:
'¥31.45'
,
show
:
'1,590,000'
,
click
:
'62,010'
,
clickRate
:
'3.90%'
,
avgPrice
:
'1.36'
,
play
:
'1,320,000'
,
complete
:
'20.4%'
},
{
department
:
'海外品牌推广组'
,
cost
:
'52100.20'
,
conversions
:
'1,540'
,
rate
:
'3.45%'
,
costRate
:
'¥33.83'
,
show
:
'1,020,000'
,
click
:
'35,700'
,
clickRate
:
'3.50%'
,
avgPrice
:
'1.46'
,
play
:
'880,000'
,
complete
:
'18.5%'
},
...
...
@@ -82,8 +86,27 @@ const handleSizeChange = () => {
</
script
>
<
style
scoped
lang=
"scss"
>
.header-tabs
,
.table-title
,
.table-footer
{
border-bottom
:
1px
solid
#edf0f5
;
}
.table-footer
{
border-top
:
1px
solid
#edf0f5
;
border-bottom
:
none
;
}
.header-tabs
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom
:
2px
solid
rgba
(
var
(
--
main-color
)
,
1
);
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f8fbff
;
color
:
#48607f
;
font-weight
:
bold
;
}
}
.header-tabs
,
.table-title
,
.table-footer
{
border-bottom
:
1px
solid
#edf0f5
;
}
.table-footer
{
border-top
:
1px
solid
#edf0f5
;
border-bottom
:
none
;
}
.header-tabs
.active
{
color
:
rgba
(
var
(
--
main-color
)
,
1
);
border-bottom
:
2px
solid
rgba
(
var
(
--
main-color
)
,
1
);
}
.analysis-table
{
:deep
(
.el-table__header
th
)
{
background
:
#f5f5f5
;
color
:
#888
;
padding
:
12px
0
;
}
}
</
style
>
apps/web-vue/src/views/analysis/department.vue
View file @
034d0c1b
<
template
>
<div>
<div
class=
"bgmr vh100 over-y-auto"
>
<section
class=
"bg-fff px-20 py-10 analysis-tabs"
>
<div
class=
"flex-items-center gap-16"
>
<div
v-for=
"item in tabs"
:key=
"item.value"
class=
"px-12 py-8 round-6 font-bold pointer"
:class=
"activeTab === item.value ? 'bg-main color-fff' : 'color-000'"
@
click=
"activeTab = item.value"
>
{{
item
.
label
}}
</div>
</div>
</section>
<div
class=
"p-16"
>
<component
:is=
"currentComponent"
/>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
Tab1
from
'./components/Team/Tab1.vue'
;
import
Tab2
from
'./components/Team/Tab2.vue'
;
import
Tab3
from
'./components/Team/Tab3.vue'
;
const
activeTab
=
ref
(
'tab1'
);
const
tabs
=
[
{
label
:
'数据洞察'
,
value
:
'tab1'
,
component
:
Tab1
},
{
label
:
'创作分析'
,
value
:
'tab2'
,
component
:
Tab2
},
{
label
:
'任务分析'
,
value
:
'tab3'
,
component
:
Tab3
},
];
const
currentComponent
=
computed
(()
=>
tabs
.
find
((
item
)
=>
item
.
value
===
activeTab
.
value
)?.
component
);
</
script
>
<
style
scoped
lang=
"scss"
>
</
style
>
\ No newline at end of file
.analysis-tabs
{
border-bottom
:
1px
solid
#dfe7f2
;
}
</
style
>
apps/web-vue/src/views/analysis/video.vue
View file @
034d0c1b
...
...
@@ -21,10 +21,10 @@
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
AdPlatformTags
from
'./components/AdPlatformTags.vue'
;
import
TagAnalysis
from
'./components/TagAnalysis.vue'
;
import
TencentDeliveryReport
from
'./components/TencentDeliveryReport.vue'
;
import
DeliveryReport
from
'./components/DeliveryReport.vue'
;
import
AdPlatformTags
from
'./components/
video/
AdPlatformTags.vue'
;
import
TagAnalysis
from
'./components/
video/
TagAnalysis.vue'
;
import
TencentDeliveryReport
from
'./components/
video/
TencentDeliveryReport.vue'
;
import
DeliveryReport
from
'./components/
video/
DeliveryReport.vue'
;
const
activeTab
=
ref
(
'platform'
);
const
tabs
=
[
...
...
apps/web-vue/src/views/zhibo/index.vue
0 → 100644
View file @
034d0c1b
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment