Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-dml
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-dml
Commits
b39a21bd
提交
b39a21bd
authored
8月 06, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 更新评分逻辑,支持AI评分选项和评分详情展示
上级
5e72e11b
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
81 行增加
和
103 行删除
+81
-103
useScore.ts
src/modules/score/composables/useScore.ts
+77
-63
Index.vue
src/modules/score/views/Index.vue
+1
-4
View.vue
src/modules/score/views/View.vue
+3
-36
没有找到文件。
src/modules/score/composables/useScore.ts
浏览文件 @
b39a21bd
import
{
getScoreList
,
getScoreDetail
,
updateScore
}
from
'../api'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useChat
}
from
'@ezijing/ai-vue'
// import { generatePrompt } from '../prompt'
// import { generatePrompt as generatePrompt2 } from '../prompt2'
import
{
ElMessage
}
from
'element-plus'
import
{
importType
,
...
...
@@ -28,9 +26,10 @@ interface ScoreItem {
comment
:
string
}
export
function
useScore
()
{
export
function
useScore
(
options
:
{
includeAIScore
?:
boolean
}
=
{}
)
{
const
userStore
=
useUserStore
()
const
isLoading
=
ref
(
false
)
const
includeAIScore
=
options
.
includeAIScore
??
true
const
{
generateText
}
=
useChat
({
provider
:
'volcano'
})
const
fetchScoreList
=
async
()
=>
{
...
...
@@ -92,74 +91,75 @@ export function useScore() {
const
liveData
=
detail
.
live_data
const
competitionRule
=
detail
.
competition_rule
let
prompt
=
''
// if (competitionRule?.competition == 1) {
// if (competitionRule?.questions == 1) {
// prompt = generatePrompt(detail.live_data)
// } else {
// prompt = generatePrompt2(detail.live_data)
// }
// } else {
const
rules
=
JSON
.
parse
(
competitionRule
?.
config
||
'{}'
)?.
rules
||
[]
rules
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
rule_mode
!=
2
)
return
if
(
item
.
type
==
1
)
{
prompt
+=
`请根据选手提交的商品品类信息进行评分(满分
${
item
.
percent
}
分):
选手提交内容:
${
JSON
.
stringify
(
liveData
.
commodity_types
)}
`
}
else
if
(
item
.
type
==
2
)
{
prompt
+=
`请根据选手提交的商品属性配置信息进行评分(满分
${
item
.
percent
}
分):
重要性字典:
${
JSON
.
stringify
(
importType
)}
必要性字典:
${
JSON
.
stringify
(
requiredType
)}
选手提交内容:
${
JSON
.
stringify
(
liveData
.
commodity_attrs
)}
`
}
else
if
(
item
.
type
==
3
)
{
prompt
+=
`请根据选手提交的商品信息维护内容进行评分(满分
${
item
.
percent
}
分):
发货模式字典:
${
JSON
.
stringify
(
deliveryMode
)}
const
ruleDataMap
:
Record
<
number
,
{
key
:
string
;
label
:
string
;
data
:
unknown
;
extra
?:
string
}
>
=
{
1
:
{
key
:
'commodity_type'
,
label
:
'商品品类信息'
,
data
:
liveData
.
commodity_types
,
},
2
:
{
key
:
'commodity_attr'
,
label
:
'商品属性配置信息'
,
data
:
liveData
.
commodity_attrs
,
extra
:
`重要性字典:
${
JSON
.
stringify
(
importType
)}
必要性字典:
${
JSON
.
stringify
(
requiredType
)}
`
,
},
3
:
{
key
:
'commodity'
,
label
:
'商品信息维护内容'
,
data
:
liveData
.
commodities
,
extra
:
`发货模式字典:
${
JSON
.
stringify
(
deliveryMode
)}
发货时效字典:
${
JSON
.
stringify
(
deliveryTime
)}
订单库存扣减规则字典:
${
JSON
.
stringify
(
orderStockCount
)}
运费模板字典:
${
JSON
.
stringify
(
shippingTemplate
)}
售后政策字典:
${
JSON
.
stringify
(
afterSalesPolicy
)}
选手提交内容:
${
JSON
.
stringify
(
liveData
.
commodities
)}
`
}
else
if
(
item
.
type
==
4
)
{
prompt
+=
`请根据选手提交的直播话术进行评分(满分
${
item
.
percent
}
分):
选手提交内容:
${
JSON
.
stringify
(
liveData
.
speeches
)}
`
}
prompt
+=
`评分标准:
${
item
.
content
}
`
})
prompt
+=
`EXAMPLE JSON OUTPUT:
{
"commodity_type": {
"score": 5,
"comment": "这是评语"
售后政策字典:
${
JSON
.
stringify
(
afterSalesPolicy
)}
`
,
},
"commodity_attr": {
"score": 5,
"comment": "这是评语"
4
:
{
key
:
'speech'
,
label
:
'直播话术'
,
data
:
liveData
.
speeches
,
},
"commodity": {
"score": 5,
"comment": "这是评语"
5
:
{
key
:
'practice_record1'
,
label
:
'直播演练'
,
data
:
liveData
.
practices
?.[
0
]?.
records
?.[
0
]?.
subtitle
,
},
"speech": {
"score": 5,
"comment": "这是评语"
6
:
{
key
:
'report'
,
label
:
'直播总结汇报'
,
data
:
liveData
.
reports
,
},
}`
// }
}
const
autoRules
=
rules
.
filter
((
item
:
any
)
=>
item
.
rule_mode
==
2
&&
ruleDataMap
[
Number
(
item
.
type
)])
const
prompt
=
autoRules
.
map
((
item
:
any
)
=>
{
const
ruleData
=
ruleDataMap
[
Number
(
item
.
type
)]
return
`【
${
item
.
name
||
ruleData
.
label
}
】
请根据选手提交的
${
ruleData
.
label
}
进行评分(满分
${
item
.
percent
}
分)
${
ruleData
.
extra
?
`
${
ruleData
.
extra
}
\n`
:
''
}
选手提交内容:
${
JSON
.
stringify
(
ruleData
.
data
)}
评分标准:
${
item
.
content
||
'请根据提交内容客观评分,并说明扣分原因。'
}
`
})
.
join
(
'
\
n
\
n'
)
const
outputExample
=
Object
.
fromEntries
(
autoRules
.
map
((
item
:
any
)
=>
[
ruleDataMap
[
Number
(
item
.
type
)].
key
,
{
score
:
0
,
comment
:
'请填写评分依据'
}]),
)
const
fullPrompt
=
`
${
prompt
}
只输出 JSON,不要输出其他内容。每个评分项都必须返回,score 不得低于 0 或高于该项满分。
JSON 输出格式:
${
JSON
.
stringify
(
outputExample
,
null
,
2
)}
`
const
messages
=
[
{
role
:
'system'
,
content
:
`你是一位专业的
电商运营评分专家,负责对选手的商品信息维护操作
进行客观、准确的评分。`
,
content
:
`你是一位专业的
大赛评分专家,负责根据评分规则对选手提交的内容
进行客观、准确的评分。`
,
},
{
role
:
'user'
,
content
:
p
rompt
},
{
role
:
'user'
,
content
:
fullP
rompt
},
]
const
result
=
await
generateText
({
model
:
'deepseek-v4-flash-260425'
,
...
...
@@ -169,7 +169,20 @@ ${JSON.stringify(liveData.speeches)}`
if
(
!
result
)
return
try
{
const
scoreDetails
:
Record
<
string
,
ScoreItem
>
=
JSON
.
parse
(
result
.
content
)
const
parsed
=
JSON
.
parse
(
result
.
content
)
const
scoreDetails
:
Record
<
string
,
ScoreItem
>
=
Object
.
fromEntries
(
autoRules
.
map
((
item
:
any
)
=>
{
const
key
=
ruleDataMap
[
Number
(
item
.
type
)].
key
const
score
=
Number
(
parsed
[
key
]?.
score
)
return
[
key
,
{
score
:
Number
.
isFinite
(
score
)
?
Math
.
max
(
0
,
Math
.
min
(
item
.
percent
,
score
))
:
0
,
comment
:
String
(
parsed
[
key
]?.
comment
||
''
),
},
]
}),
)
const
totalScore
=
Object
.
values
(
scoreDetails
).
reduce
((
acc
,
curr
)
=>
acc
+
(
curr
.
score
||
0
),
0
)
console
.
log
(
scoreDetails
)
const
myScore
:
ScoreDetail
=
{
...
...
@@ -181,9 +194,10 @@ ${JSON.stringify(liveData.speeches)}`
updated_at
:
new
Date
().
toLocaleString
(),
}
const
scores
=
[...
detail
.
scores
.
filter
((
item
:
any
)
=>
item
.
checker_id
!=
userStore
.
user
?.
id
),
myScore
]
// 总平均分,过滤掉AI评分
const
validScores
=
scores
.
filter
((
item
)
=>
!
item
.
is_ai
)
const
totalAverageScore
=
validScores
.
reduce
((
acc
,
curr
)
=>
acc
+
(
curr
.
total_score
||
0
),
0
)
/
validScores
.
length
const
scoresForTotal
=
includeAIScore
?
scores
:
scores
.
filter
((
item
)
=>
!
item
.
is_ai
)
const
totalAverageScore
=
scoresForTotal
.
length
?
scoresForTotal
.
reduce
((
acc
,
curr
)
=>
acc
+
(
curr
.
total_score
||
0
),
0
)
/
scoresForTotal
.
length
:
0
await
updateScore
({
id
:
detail
.
id
,
check_status
:
2
,
...
...
src/modules/score/views/Index.vue
浏览文件 @
b39a21bd
...
...
@@ -52,10 +52,7 @@ const listOptions = computed(() => {
try
{
const
scores
=
row
.
score_details
?
JSON
.
parse
(
row
.
score_details
)
:
[]
return
Array
.
isArray
(
scores
)
?
scores
.
filter
((
item
)
=>
!
item
.
is_ai
)
.
map
((
item
)
=>
`
${
item
.
checker_name
}
(
${
item
.
total_score
}
)`
)
.
join
(
'<br/>'
)
?
scores
.
map
((
item
)
=>
`
${
item
.
is_ai
?
'AI'
:
item
.
checker_name
}
(
${
item
.
total_score
}
)`
).
join
(
'<br/>'
)
:
''
}
catch
(
error
)
{
console
.
log
(
'评分人解析失败'
,
error
)
...
...
src/modules/score/views/View.vue
浏览文件 @
b39a21bd
<
script
setup
>
import
{
getScoreDetail
,
updateScore
}
from
'../api'
import
{
ElMessage
}
from
'element-plus'
import
{
useChat
}
from
'@ezijing/ai-vue'
import
{
generatePrompt
}
from
'../prompt'
import
{
generatePrompt
as
generatePrompt2
}
from
'../prompt2'
import
{
cloneDeep
}
from
'lodash-es'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useEventListener
}
from
'@vueuse/core'
...
...
@@ -16,8 +13,6 @@ const CompetitionOperations = defineAsyncComponent(() => import('../components/C
const
route
=
useRoute
()
const
id
=
route
.
query
.
id
const
{
isLoading
,
generateText
}
=
useChat
({
provider
:
'volcano'
})
const
detail
=
ref
(
null
)
const
scoreDetails
=
reactive
({})
...
...
@@ -61,26 +56,6 @@ onMounted(() => {
fetchDetail
()
})
const
handleAIScore
=
async
()
=>
{
console
.
log
(
'AI一键评分'
)
const
prompt
=
detail
.
value
.
competition_rule
?.
questions
==
1
?
generatePrompt
(
detail
.
value
.
live_data
)
:
generatePrompt2
(
detail
.
value
.
live_data
)
const
result
=
await
generateText
({
prompt
,
response_format
:
{
type
:
'json_object'
}
})
try
{
const
parsed
=
JSON
.
parse
(
result
.
content
)
Object
.
assign
(
scoreDetails
,
parsed
)
commitScore
(
1
,
true
).
then
(()
=>
{
ElMessage
.
success
(
'保存成功'
)
})
}
catch
(
error
)
{
console
.
log
(
error
)
ElMessage
.
error
(
'评分失败'
)
return
}
}
const
handleSave
=
()
=>
{
commitScore
().
then
(()
=>
{
ElMessage
.
success
(
'保存成功'
)
...
...
@@ -100,9 +75,9 @@ const commitScore = (status = 1, isAI = false) => {
// 去掉当前评分人的评分,并添加当前评分人的评分
scores
=
[...
scores
.
filter
((
item
)
=>
!
(
item
.
checker_id
==
userStore
.
user
.
id
&&
!
item
.
is_ai
)),
myScore
]
// 总平均分,过滤掉AI评分
const
validScores
=
scores
.
filter
((
item
)
=>
!
item
.
is_ai
)
const
totalAverageScore
=
validScores
.
reduce
((
acc
,
curr
)
=>
acc
+
(
curr
.
total_score
||
0
),
0
)
/
validScores
.
length
const
totalAverageScore
=
scores
.
length
?
scores
.
reduce
((
acc
,
curr
)
=>
acc
+
(
curr
.
total_score
||
0
),
0
)
/
scores
.
length
:
0
return
updateScore
({
id
,
...
...
@@ -144,14 +119,6 @@ useEventListener(window, 'pagehide', () => {
<el-form-item
label=
"状态"
>
{{
detail
.
check_status_name
}}
</el-form-item>
<el-form-item
label=
"提交时间"
>
{{
detail
.
commit_time
}}
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
:loading=
"isLoading"
@
click=
"handleAIScore"
v-if=
"detail.competition_rule?.competition == 1"
v-show=
"false"
>
AI一键评分
</el-button
>
<el-button
type=
"primary"
@
click=
"handlePublishScore"
>
提交成绩
</el-button>
</el-form-item>
</el-form>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论