Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-dml
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-dml
Commits
fb5296da
提交
fb5296da
authored
11月 13, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: 修改AI打分功能
上级
a215af9e
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
340 行增加
和
410 行删除
+340
-410
ScoreCardLive.vue
src/modules/live/score/components/ScoreCardLive.vue
+8
-173
Index.vue
src/modules/live/score/views/Index.vue
+1
-1
View.vue
src/modules/live/score/views/View.vue
+1
-1
api.ts
src/modules/live/test/api.ts
+5
-0
RecordDialog.vue
src/modules/live/test/components/RecordDialog.vue
+7
-7
RecordView.vue
src/modules/live/test/components/RecordView.vue
+315
-0
View.vue
src/modules/live/test/views/View.vue
+2
-227
menu.ts
src/stores/menu.ts
+1
-1
没有找到文件。
src/modules/live/score/components/ScoreCardLive.vue
浏览文件 @
fb5296da
<
script
setup
>
import
VueMarkdown
from
'vue-markdown-render'
import
Demo
from
'../../test/components/Demo.vue'
import
RecordView
from
'../../test/components/RecordView.vue'
const
props
=
defineProps
({
defineProps
({
data
:
{
type
:
Object
},
})
const
detail
=
computed
(()
=>
{
return
{
...
props
.
data
,
live_info
:
JSON
.
parse
(
props
.
data
.
live_info
)
}
})
function
formatDuration
(
seconds
)
{
const
minutes
=
Math
.
floor
(
seconds
/
60
)
const
remainingSeconds
=
(
seconds
%
60
).
toFixed
(
2
)
return
minutes
>
0
?
`
${
minutes
}
m
${
remainingSeconds
}
s`
:
`
${
remainingSeconds
}
s`
}
</
script
>
<
template
>
<div
class=
"live-view"
<RecordView
:recordId=
"data.id"
:isView=
"false"
style=
"border: 1px solid #eee; border-radius: 10px; margin-bottom: 20px; overflow: hidden"
v-if=
"detail"
>
<AppCard>
<div
class=
"live-info"
>
<div
class=
"live-info-header"
>
<h2>
练习表现
</h2>
<p>
评分等级
</p>
<h3>
{{
detail
.
ai_level
||
'--'
}}
</h3>
<p>
主播完成质量良好,需要关注细节勤加练习
</p>
</div>
<div
class=
"live-info-item"
>
<div>
<p>
主播姓名
</p>
<p>
{{
detail
.
created_operator
.
real_name
||
detail
.
created_operator
.
nickname
}}
</p>
</div>
<div>
<p>
直播时长
</p>
<p>
{{
formatDuration
(
detail
.
live_duration
)
}}
</p>
</div>
<div>
<p>
开始时间
</p>
<p>
{{
detail
.
live_start_time
}}
</p>
</div>
<div>
<p>
结束时间
</p>
<p>
{{
detail
.
live_end_time
}}
</p>
</div>
<div>
<p>
视频状态
</p>
<p>
已上传
</p>
</div>
<div>
<p>
观众总人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalViewers
}}
</p>
</div>
<div>
<p>
最高峰人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
peakViewers
}}
</p>
</div>
<div>
<p>
点赞数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalLikes
}}
</p>
</div>
<div>
<p>
刷礼物人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGiftViewers
}}
</p>
</div>
<div>
<p>
刷礼物总数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGifts
}}
</p>
</div>
<div>
<p>
下单量
</p>
<p>
{{
detail
.
orders_count
}}
</p>
</div>
</div>
</div>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
违规情况
</h2>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"detail.illegal_word"
v-if=
"detail.illegal_word"
/>
</div>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
卖点讲解
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
产生订单
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<
template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
</div>
<Demo
:id=
"detail.live_practice_id"
:recordId=
"detail.id"
:isView=
"true"
/>
</template>
<
style
lang=
"scss"
scoped
>
.live-view
{
.live-info
{
display
:
flex
;
gap
:
12px
;
p
{
font-size
:
14px
;
color
:
#525252
;
margin
:
10px
0
;
}
.live-info-header
{
display
:
flex
;
flex-direction
:
column
;
border-right
:
1px
solid
#e5e5e5
;
padding-right
:
12px
;
h2
{
font-size
:
24px
;
font-weight
:
bold
;
}
v-if=
"data"
/>
h3
{
font-size
:
40px
;
font-weight
:
bold
;
}
}
.live-info-item
{
flex
:
1
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
12px
;
div
{
width
:
180px
;
}
}
}
.live-title
{
font-size
:
20px
;
font-weight
:
bold
;
margin-bottom
:
20px
;
}
.live-tips
{
margin-top
:
10px
;
font-size
:
14px
;
color
:
#000
;
b
{
font-size
:
14px
;
font-weight
:
bold
;
margin-right
:
20px
;
}
}
.el-step__description
{
margin-bottom
:
20px
;
}
.live-markdown
{
line-height
:
1
.8
;
li
{
list-style
:
disc
;
margin-left
:
20px
;
}
p
{
margin
:
10px
0
;
}
strong
,
b
{
font-weight
:
bold
;
}
}
}
</
style
>
<Demo
:id=
"data.live_practice_id"
:recordId=
"data.id"
:isView=
"true"
/>
</
template
>
src/modules/live/score/views/Index.vue
浏览文件 @
fb5296da
...
...
@@ -53,7 +53,7 @@ const handleExport = () => {
</
script
>
<
template
>
<AppCard
title=
"
直播
成绩管理"
>
<AppCard
title=
"成绩管理"
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<template
#
header-buttons
>
<!--
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
提交成绩
</el-button>
-->
...
...
src/modules/live/score/views/View.vue
浏览文件 @
fb5296da
...
...
@@ -234,7 +234,7 @@ const handlePublishScore = () => {
}
</
script
>
<
template
>
<AppCard
title=
"
直播
成绩管理"
v-if=
"detail"
>
<AppCard
title=
"成绩管理"
v-if=
"detail"
>
<div
class=
"score-header"
>
<el-form
label-suffix=
":"
inline
class=
"info"
>
<el-form-item
label=
"姓名"
>
{{
detail
.
student_name
}}
</el-form-item>
...
...
src/modules/live/test/api.ts
浏览文件 @
fb5296da
...
...
@@ -71,3 +71,8 @@ export function pushSubtitle(params: { subtitle: string; selling_point: string;
export
function
updateImprovementPlan
(
data
:
{
id
:
string
;
improvement_plan
:
string
})
{
return
httpRequest
.
post
(
'/api/lab/v1/experiment/live-practice/submit-improvement-plan'
,
data
)
}
// AI 打分
export
function
aiScore
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/dev/v1/experiment/live-practice/score-live-practice-record'
,
data
)
}
src/modules/live/test/components/RecordDialog.vue
浏览文件 @
fb5296da
...
...
@@ -55,13 +55,13 @@ const listOptions = {
return
row
.
ai_status
||
'--'
},
},
{
label
:
'评级'
,
prop
:
'ai_level'
,
computed
({
row
})
{
return
row
.
ai_level
||
'--'
},
},
//
{
//
label: '评级',
//
prop: 'ai_level',
//
computed({ row }) {
//
return row.ai_level || '--'
//
},
//
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
140
},
],
}
...
...
src/modules/live/test/components/RecordView.vue
0 → 100644
浏览文件 @
fb5296da
<
script
setup
>
import
VueMarkdown
from
'vue-markdown-render'
import
Demo
from
'../components/Demo.vue'
import
ImprovementPlan
from
'../components/ImprovementPlan.vue'
import
{
getRecord
,
aiScore
}
from
'../api'
const
props
=
defineProps
({
isView
:
{
type
:
Boolean
,
default
:
true
},
recordId
:
{
type
:
String
},
})
const
detail
=
ref
(
null
)
const
fetchRecord
=
async
()
=>
{
const
res
=
await
getRecord
({
id
:
props
.
recordId
})
const
resDetail
=
res
.
data
.
detail
detail
.
value
=
{
...
resDetail
,
live_info
:
JSON
.
parse
(
resDetail
.
live_info
)
}
}
onMounted
(()
=>
{
fetchRecord
()
})
const
id
=
computed
(()
=>
{
return
detail
.
value
?.
live_practice_info
?.
id
})
const
dialogVisible
=
ref
(
false
)
const
result
=
computed
(()
=>
{
try
{
return
JSON
.
parse
(
detail
.
value
.
illegal_word
)
||
{}
}
catch
(
error
)
{
console
.
log
(
error
)
}
return
{}
})
const
tipsList
=
{
A
:
[
{
title
:
'卖点讲解'
,
content
:
'强化产品独特性与情感场景化表达。'
},
{
title
:
'违规情况'
,
content
:
'关注平台新规并规避敏感词。'
},
{
title
:
'讲解时长'
,
content
:
'精准分配时间,促销环节压缩冗余。'
},
{
title
:
'其他建议'
,
content
:
'模拟实战并复盘转化数据。'
},
],
B
:
[
{
title
:
'卖点讲解'
,
content
:
'场景化设计减少参数罗列。'
},
{
title
:
'违规情况'
,
content
:
'熟记合规词库并规避竞品对比。'
},
{
title
:
'讲解时长'
,
content
:
'控制节奏,促销环节提速。'
},
{
title
:
'其他建议'
,
content
:
'学习高感染力话术并准备互动模板。'
},
],
C
:
[
{
title
:
'卖点讲解'
,
content
:
'结构化表达并突出核心卖点。'
},
{
title
:
'违规情况'
,
content
:
'系统学习规则并使用AI审核。'
},
{
title
:
'讲解时长'
,
content
:
'分段练习并制定时间分配表。'
},
{
title
:
'其他建议'
,
content
:
'参加基础培训并拆解优秀案例。'
},
],
D
:
[
{
title
:
'卖点讲解'
,
content
:
'模板化练习并记忆关键词。'
},
{
title
:
'违规情况'
,
content
:
'精读合规手册并替换敏感词。'
},
{
title
:
'讲解时长'
,
content
:
'分段训练并使用计时器。'
},
{
title
:
'其他建议'
,
content
:
'录制回放并建立反馈机制。'
},
],
}
const
tips
=
computed
(()
=>
{
return
tipsList
[
detail
.
value
?.
ai_level
||
'A'
]
})
const
successWords
=
computed
(()
=>
{
return
detail
.
value
?.
words
?.
filter
((
item
)
=>
item
.
time
)
||
[]
})
const
failedWords
=
computed
(()
=>
{
return
detail
.
value
?.
words
?.
filter
((
item
)
=>
!
item
.
time
)
||
[]
})
const
handleAIScore
=
()
=>
{
aiScore
({
id
:
props
.
recordId
}).
then
((
res
)
=>
{
console
.
log
(
res
)
})
}
function
formatDuration
(
seconds
)
{
const
minutes
=
Math
.
floor
(
seconds
/
60
)
const
remainingSeconds
=
(
seconds
%
60
).
toFixed
(
2
)
return
minutes
>
0
?
`
${
minutes
}
m
${
remainingSeconds
}
s`
:
`
${
remainingSeconds
}
s`
}
</
script
>
<
template
>
<div
class=
"live-view"
v-if=
"detail"
>
<AppCard>
<div
class=
"live-info"
>
<div
class=
"live-info-header"
>
<h2
@
dblclick=
"handleAIScore"
>
我的练习表现
</h2>
<h6>
{{
detail
.
live_practice_info
?.
live_commodity
?.
title
}}
</h6>
<div
v-if=
"false"
>
<p>
评分等级
</p>
<h3>
{{
detail
.
ai_level
||
'--'
}}
</h3>
<p>
主播完成质量良好,需要关注细节勤加练习
</p>
</div>
</div>
<div
class=
"live-info-item"
>
<div>
<p>
主播姓名
</p>
<p>
{{
detail
.
created_operator
.
real_name
||
detail
.
created_operator
.
nickname
}}
</p>
</div>
<div>
<p>
直播时长
</p>
<p>
{{
formatDuration
(
detail
.
live_duration
)
}}
</p>
</div>
<div>
<p>
开始时间
</p>
<p>
{{
detail
.
live_start_time
}}
</p>
</div>
<div>
<p>
结束时间
</p>
<p>
{{
detail
.
live_end_time
}}
</p>
</div>
<div>
<p>
视频状态
</p>
<p>
已上传
</p>
</div>
<div>
<p>
观众总人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalViewers
}}
</p>
</div>
<div>
<p>
最高峰人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
peakViewers
}}
</p>
</div>
<div>
<p>
点赞数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalLikes
}}
</p>
</div>
<div>
<p>
刷礼物人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGiftViewers
}}
</p>
</div>
<div>
<p>
刷礼物总数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGifts
}}
</p>
</div>
<div>
<p>
下单量
</p>
<p>
{{
detail
.
orders_count
}}
</p>
</div>
<div
v-if=
"isView"
>
<p>
操作
</p>
<el-button
type=
"primary"
link
@
click=
"dialogVisible = true"
>
查看直播回放
</el-button>
<ImprovementPlan
:id=
"recordId"
:content=
"detail.improvement_plan"
v-if=
"recordId"
/>
</div>
</div>
</div>
</AppCard>
<AppCard
v-if=
"false"
>
<h2
class=
"live-title"
>
练习优化建议
</h2>
<div
v-for=
"(item, index) in tips"
:key=
"index"
>
<p
class=
"live-tips"
>
<b>
{{
item
.
title
}}
</b>
{{
item
.
content
}}
</p>
</div>
</AppCard>
<AppCard
title=
"卖点讲解覆盖情况"
>
<ul
class=
"live-ul"
>
<li>
已讲解:
{{
successWords
.
length
}}
个卖点
</li>
<li>
未讲解:
{{
failedWords
.
length
}}
个卖点
</li>
<li>
覆盖率:
{{
((
successWords
.
length
/
detail
.
words
?.
length
)
*
100
).
toFixed
(
2
)
}}
%
</li>
</ul>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"result.sellingPoints"
v-if=
"result.sellingPoints"
/>
</div>
<h2
class=
"live-title"
>
已讲解卖点:
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in successWords"
:key=
"index"
:title=
"item.name"
status=
"success"
>
<template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
<h2
class=
"live-title"
>
未讲解卖点:
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in failedWords"
:key=
"index"
:title=
"item.name"
status=
"error"
>
<
template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<AppCard
title=
"违禁词分析"
>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"result.forbiddenWords"
v-if=
"result.forbiddenWords"
/>
</div>
</AppCard>
<AppCard
title=
"语速分析"
>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"result.speechSpeed"
v-if=
"result.speechSpeed"
/>
</div>
</AppCard>
<AppCard
title=
"直播优化建议"
>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"result.optimizationTips"
v-if=
"result.optimizationTips"
/>
</div>
</AppCard>
<AppCard
v-if=
"false"
>
<h2
class=
"live-title"
>
违规情况
</h2>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"result.illegal_word"
v-if=
"result.illegal_word"
/>
</div>
</AppCard>
<AppCard
v-if=
"false"
>
<h2
class=
"live-title"
>
卖点讲解
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<
template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<AppCard
v-if=
"false"
>
<h2
class=
"live-title"
>
产生订单
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<
template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<el-dialog
v-model=
"dialogVisible"
title=
"直播回放"
width=
"1200px"
>
<div
style=
"height: 740px"
>
<Demo
:id=
"id"
:recordId=
"recordId"
:isView=
"true"
/>
</div>
</el-dialog>
</div>
</template>
<
style
lang=
"scss"
>
.live-view
{
.live-info
{
display
:
flex
;
gap
:
12px
;
p
{
font-size
:
14px
;
color
:
#525252
;
margin
:
10px
0
;
}
.live-info-header
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
border-right
:
1px
solid
#e5e5e5
;
padding-right
:
12px
;
h2
{
font-size
:
24px
;
font-weight
:
bold
;
}
h3
{
font-size
:
40px
;
font-weight
:
bold
;
}
h6
{
font-size
:
20px
;
font-weight
:
bold
;
}
}
.live-info-item
{
flex
:
1
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
12px
;
div
{
width
:
200px
;
}
}
}
.live-title
{
font-size
:
14px
;
font-weight
:
bold
;
margin
:
20px
0
;
}
.live-tips
{
margin-top
:
10px
;
font-size
:
14px
;
color
:
#000
;
b
{
font-size
:
14px
;
font-weight
:
bold
;
margin-right
:
20px
;
}
}
.el-step__description
{
margin-bottom
:
20px
;
}
.live-markdown
{
line-height
:
1
.8
;
li
{
list-style
:
disc
;
margin-left
:
20px
;
}
p
{
margin
:
10px
0
;
}
strong
,
b
{
font-weight
:
bold
;
}
}
.live-ul
{
display
:
flex
;
margin-bottom
:
20px
;
gap
:
30px
;
}
}
</
style
>
src/modules/live/test/views/View.vue
浏览文件 @
fb5296da
<
script
setup
>
import
VueMarkdown
from
'vue-markdown-render'
import
Demo
from
'../components/Demo.vue'
import
{
getRecord
}
from
'../api'
import
ImprovementPlan
from
'../components/ImprovementPlan.vue'
import
RecordView
from
'../components/RecordView.vue'
const
route
=
useRoute
()
const
id
=
route
.
query
.
id
const
recordId
=
route
.
query
.
record_id
const
dialogVisible
=
ref
(
false
)
const
detail
=
ref
(
null
)
const
fetchRecord
=
async
()
=>
{
const
res
=
await
getRecord
({
id
:
recordId
})
const
resDetail
=
res
.
data
.
detail
detail
.
value
=
{
...
resDetail
,
live_info
:
JSON
.
parse
(
resDetail
.
live_info
)
}
}
onMounted
(()
=>
{
fetchRecord
()
})
const
tipsList
=
{
A
:
[
{
title
:
'卖点讲解'
,
content
:
'强化产品独特性与情感场景化表达。'
},
{
title
:
'违规情况'
,
content
:
'关注平台新规并规避敏感词。'
},
{
title
:
'讲解时长'
,
content
:
'精准分配时间,促销环节压缩冗余。'
},
{
title
:
'其他建议'
,
content
:
'模拟实战并复盘转化数据。'
},
],
B
:
[
{
title
:
'卖点讲解'
,
content
:
'场景化设计减少参数罗列。'
},
{
title
:
'违规情况'
,
content
:
'熟记合规词库并规避竞品对比。'
},
{
title
:
'讲解时长'
,
content
:
'控制节奏,促销环节提速。'
},
{
title
:
'其他建议'
,
content
:
'学习高感染力话术并准备互动模板。'
},
],
C
:
[
{
title
:
'卖点讲解'
,
content
:
'结构化表达并突出核心卖点。'
},
{
title
:
'违规情况'
,
content
:
'系统学习规则并使用AI审核。'
},
{
title
:
'讲解时长'
,
content
:
'分段练习并制定时间分配表。'
},
{
title
:
'其他建议'
,
content
:
'参加基础培训并拆解优秀案例。'
},
],
D
:
[
{
title
:
'卖点讲解'
,
content
:
'模板化练习并记忆关键词。'
},
{
title
:
'违规情况'
,
content
:
'精读合规手册并替换敏感词。'
},
{
title
:
'讲解时长'
,
content
:
'分段训练并使用计时器。'
},
{
title
:
'其他建议'
,
content
:
'录制回放并建立反馈机制。'
},
],
}
const
tips
=
computed
(()
=>
{
return
tipsList
[
detail
.
value
?.
ai_level
||
'A'
]
})
function
formatDuration
(
seconds
)
{
const
minutes
=
Math
.
floor
(
seconds
/
60
)
const
remainingSeconds
=
(
seconds
%
60
).
toFixed
(
2
)
return
minutes
>
0
?
`
${
minutes
}
m
${
remainingSeconds
}
s`
:
`
${
remainingSeconds
}
s`
}
</
script
>
<
template
>
<div
class=
"live-view"
v-if=
"detail"
>
<AppCard>
<div
class=
"live-info"
>
<div
class=
"live-info-header"
>
<h2>
我的练习表现
</h2>
<p>
评分等级
</p>
<h3>
{{
detail
.
ai_level
||
'--'
}}
</h3>
<p>
主播完成质量良好,需要关注细节勤加练习
</p>
</div>
<div
class=
"live-info-item"
>
<div>
<p>
主播姓名
</p>
<p>
{{
detail
.
created_operator
.
real_name
||
detail
.
created_operator
.
nickname
}}
</p>
</div>
<div>
<p>
直播时长
</p>
<p>
{{
formatDuration
(
detail
.
live_duration
)
}}
</p>
</div>
<div>
<p>
开始时间
</p>
<p>
{{
detail
.
live_start_time
}}
</p>
</div>
<div>
<p>
结束时间
</p>
<p>
{{
detail
.
live_end_time
}}
</p>
</div>
<div>
<p>
视频状态
</p>
<p>
已上传
</p>
</div>
<div>
<p>
观众总人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalViewers
}}
</p>
</div>
<div>
<p>
最高峰人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
peakViewers
}}
</p>
</div>
<div>
<p>
点赞数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalLikes
}}
</p>
</div>
<div>
<p>
刷礼物人数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGiftViewers
}}
</p>
</div>
<div>
<p>
刷礼物总数
</p>
<p>
{{
detail
.
live_info
.
stats
.
totalGifts
}}
</p>
</div>
<div>
<p>
下单量
</p>
<p>
{{
detail
.
orders_count
}}
</p>
</div>
<div>
<p>
操作
</p>
<el-button
type=
"primary"
link
@
click=
"dialogVisible = true"
>
查看直播回放
</el-button>
<ImprovementPlan
:id=
"recordId"
:content=
"detail.improvement_plan"
v-if=
"recordId"
/>
</div>
</div>
</div>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
练习优化建议
</h2>
<div
v-for=
"(item, index) in tips"
:key=
"index"
>
<p
class=
"live-tips"
>
<b>
{{
item
.
title
}}
</b>
{{
item
.
content
}}
</p>
</div>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
违规情况
</h2>
<div
class=
"live-markdown"
>
<VueMarkdown
:source=
"detail.illegal_word"
v-if=
"detail.illegal_word"
/>
</div>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
卖点讲解
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<AppCard>
<h2
class=
"live-title"
>
产生订单
</h2>
<el-steps
direction=
"vertical"
:active=
"1"
>
<el-step
v-for=
"(item, index) in detail.words"
:key=
"index"
:title=
"item.name"
:status=
"item.time ? 'success' : 'error'"
>
<
template
#
description
>
{{
item
.
time
}}
{{
item
.
subtitle
}}
</
template
>
</el-step>
</el-steps>
</AppCard>
<el-dialog
v-model=
"dialogVisible"
title=
"直播回放"
width=
"1200px"
>
<div
style=
"height: 740px"
>
<Demo
:id=
"id"
:recordId=
"recordId"
:isView=
"true"
/>
</div>
</el-dialog>
</div>
<RecordView
:recordId=
"recordId"
/>
</
template
>
<
style
lang=
"scss"
>
.live-view
{
.live-info
{
display
:
flex
;
gap
:
12px
;
p
{
font-size
:
14px
;
color
:
#525252
;
margin
:
10px
0
;
}
.live-info-header
{
display
:
flex
;
flex-direction
:
column
;
border-right
:
1px
solid
#e5e5e5
;
padding-right
:
12px
;
h2
{
font-size
:
24px
;
font-weight
:
bold
;
}
h3
{
font-size
:
40px
;
font-weight
:
bold
;
}
}
.live-info-item
{
flex
:
1
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
12px
;
div
{
width
:
180px
;
}
}
}
.live-title
{
font-size
:
20px
;
font-weight
:
bold
;
margin-bottom
:
20px
;
}
.live-tips
{
margin-top
:
10px
;
font-size
:
14px
;
color
:
#000
;
b
{
font-size
:
14px
;
font-weight
:
bold
;
margin-right
:
20px
;
}
}
.el-step__description
{
margin-bottom
:
20px
;
}
.live-markdown
{
line-height
:
1
.8
;
li
{
list-style
:
disc
;
margin-left
:
20px
;
}
p
{
margin
:
10px
0
;
}
strong
,
b
{
font-weight
:
bold
;
}
}
}
</
style
>
src/stores/menu.ts
浏览文件 @
fb5296da
...
...
@@ -378,7 +378,7 @@ const adminMenus: IMenuItem[] = [
{
id
:
203
,
name
:
'
直播
成绩管理'
,
name
:
'成绩管理'
,
path
:
'/live/score'
,
icon
:
markRaw
(
DocumentChecked
),
role
:
[
5
,
6
],
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论