提交 54a2d56a authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 1cc0254a
......@@ -130,7 +130,7 @@ useIntervalFn(() => {
</el-button>
</template>
<br />
<ImprovementPlan :id="row.id" :content="row.improvement_plan" v-if="row.id" />
<ImprovementPlan :id="row.id" :content="row.improvement_plan" v-if="false" />
<template v-if="row.upload_way == '2'">
<br />
<el-button
......
......@@ -949,7 +949,7 @@ function formatDuration(seconds) {
<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" />
<ImprovementPlan :id="recordId" :content="detail.improvement_plan" v-if="false" />
</div>
</div>
</div>
......
<script setup>
import { useMapStore } from '@/stores/map'
import {
getNameByValue,
importType,
requiredType,
deliveryMode,
deliveryTime,
shippingTemplate,
afterSalesPolicy,
} from '@/utils/dictionary'
import ScoreCard from './ScoreCard.vue'
import ScoreCardLive from './ScoreCardLive.vue'
import Preview from '@/components/Preview.vue'
const statusList = useMapStore().getMapValuesByKey('system_status')
const props = defineProps({
detail: { type: Object, default: () => ({}) },
})
const scoreDetails = defineModel('scoreDetails', {
required: true,
default: () => ({}),
})
// 定义需要的所有 key 及其默认值
const requiredKeys = {
commodity_type: { score: null, comment: '' },
commodity_attr: { score: null, comment: '' },
commodity: { score: null, comment: '' },
speech: { score: null, comment: '' },
practice_record1: { score: null, comment: '' },
report: { score: null, comment: '' },
}
// 确保所有必需的 key 都存在,如果不存在则初始化
watchEffect(() => {
Object.keys(requiredKeys).forEach((key) => {
if (!scoreDetails.value[key]) {
scoreDetails.value[key] = { ...requiredKeys[key] }
} else if (!scoreDetails.value[key].hasOwnProperty('score') || !scoreDetails.value[key].hasOwnProperty('comment')) {
// 如果存在但结构不完整(缺少 score 或 comment),则合并默认值
scoreDetails.value[key] = { ...requiredKeys[key], ...scoreDetails.value[key] }
}
})
})
defineEmits(['save'])
// 比赛规则
const competitionRule = computed(() => {
const competition_rule = props.detail?.competition_rule || {}
if (competition_rule.config) {
const config = JSON.parse(competition_rule.config)
return { ...competition_rule, ...config }
} else {
return competition_rule
}
})
const scoreRules = computed(() => {
return competitionRule.value?.rules || []
})
const firstLivePractice = computed(() => {
return props.detail.live_data.practices[0]
})
const firstLivePracticeRecord = computed(() => {
return firstLivePractice.value?.records[0]
})
// 商品类别
const categoryTableOptions = {
columns: [
{ label: '商品品类名称', prop: 'name', align: 'left' },
{
label: '层级',
prop: 'level',
computed({ row }) {
return parseInt(row.level) + 1
},
},
{
label: '状态',
prop: 'status',
computed({ row }) {
const color = row.status === '1' ? 'var(--main-success-color)' : 'var(--main-color)'
return `<span style="color: ${color}">${getNameByValue(row.status, statusList)}</span>`
},
},
],
}
// 商品属性
const attrsTableOptions = {
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '商品属性名称', prop: 'name' },
{ label: '所属商品品类', prop: 'live_commodity_type_full_name' },
{
label: '重要性',
prop: 'is_importance',
computed({ row }) {
return getNameByValue(row.is_importance, importType)
},
},
{
label: '必要性',
prop: 'is_essential',
computed({ row }) {
return getNameByValue(row.is_essential, requiredType)
},
},
{
label: '状态',
prop: 'status',
computed({ row }) {
const color = row.status === '1' ? 'var(--main-success-color)' : 'var(--main-color)'
return `<span style="color: ${color}">${getNameByValue(row.status, statusList)}</span>`
},
},
{ label: '更新时间', prop: 'updated_time' },
],
}
// 商品管理
const productList = computed(() => {
return props.detail.live_data?.commodities?.map((item) => {
try {
item.info = JSON.parse(item.info)
item.info.delivery_mode_name = getNameByValue(item.info.delivery_mode, deliveryMode)
item.info.delivery_time_name = getNameByValue(item.info.delivery_time, deliveryTime)
item.info.shipping_template_name = getNameByValue(item.info.shipping_template, shippingTemplate)
item.info.after_sales_policy_name = getNameByValue(item.info.after_sales_policy, afterSalesPolicy)
item.live_commodity_attrs = JSON.parse(item.live_commodity_attrs)
item.picture_34_addreses = JSON.parse(item.picture_34_addreses)
item.picture_addreses = JSON.parse(item.picture_addreses)
} catch (error) {
console.log(error)
}
console.log(item)
return item
})
})
const productTableOptions = {
columns: [
{
type: 'expand',
slots: 'table-expand',
},
{ label: '序号', type: 'index', width: 60 },
{ label: '商品标题', prop: 'title' },
{ label: '所属商品品类', prop: 'live_commodity_type_full_name' },
{ label: '参考价(¥)', prop: 'info.reference_price' },
{ label: '发货模式', prop: 'info.delivery_mode_name' },
{ label: '发货时效', prop: 'info.delivery_time_name' },
{ label: '运费模板', prop: 'info.shipping_template_name' },
{ label: '售后政策', prop: 'info.after_sales_policy_name' },
],
}
// 商品规格
const productSpecsTableOptions = {
columns: [
{ label: '规格名称', prop: 'name' },
{
label: '规格值',
prop: 'value',
computed({ row }) {
return row.values.join(' / ')
},
},
],
}
// 商品sku
const productSkuTableOptions = {
columns: [
{
label: '规格',
prop: 'name',
computed({ row }) {
return row.specs?.join(' / ')
},
},
{ label: '价格(¥)', prop: 'price' },
{ label: '库存', prop: 'stock' },
],
}
// 直播话术
const talkTableOptions = {
columns: [
{ type: 'expand', slots: 'table-expand' },
{ label: '序号', type: 'index', width: 60 },
{ label: '直播话术名称', prop: 'name' },
{ label: '直播主题标题', prop: 'live_commodity_title' },
{
label: '话术时长',
prop: 'duration',
computed({ row }) {
return `${row.duration}分钟`
},
},
{ label: '所属直播主题品类', prop: 'live_commodity_type_full_name' },
],
}
const activeTab = ref(1)
const handleNext = () => {
activeTab.value++
}
</script>
<template>
<el-tabs stretch v-model="activeTab" class="score-tabs">
<el-tab-pane v-for="(item, index) in scoreRules" :key="index" :label="item.name" :name="index + 1" lazy>
<!-- 商品品类管理 -->
<template v-if="item.type == 1">
<ScoreCard
:maxScore="item.percent"
v-model:score="scoreDetails.commodity_type.score"
v-model:comment="scoreDetails.commodity_type.comment"
@save="$emit('save')"
@next="handleNext">
<AppList
v-bind="categoryTableOptions"
row-key="id"
:data="detail.live_data.commodity_types"
default-expand-all />
</ScoreCard>
</template>
<!-- 商品属性管理 -->
<template v-if="item.type == 2">
<ScoreCard
:maxScore="item.percent"
v-model:score="scoreDetails.commodity_attr.score"
v-model:comment="scoreDetails.commodity_attr.comment"
@save="$emit('save')"
@next="handleNext">
<AppList v-bind="attrsTableOptions" :data="detail.live_data.commodity_attrs" />
</ScoreCard>
</template>
<!-- 商品管理 -->
<template v-if="item.type == 3">
<ScoreCard
:maxScore="item.percent"
v-model:score="scoreDetails.commodity.score"
v-model:comment="scoreDetails.commodity.comment"
@save="$emit('save')"
@next="handleNext">
<AppList v-bind="productTableOptions" :data="productList" default-expand-all>
<template #table-expand="{ row }">
<div class="table-expand-box">
<el-form label-position="top">
<el-row>
<el-col :span="12">
<el-form-item label="主图">
<el-image
:src="item.url"
v-for="item in row.picture_addreses"
:key="item.url"
fit="cover"
preview-teleported
:preview-src-list="row.picture_addreses.map((item) => item.url)"
style="width: 100px; height: 100px; margin-right: 10px"></el-image>
</el-form-item>
<el-form-item label="主图3:4">
<el-image
:src="item.url"
v-for="item in row.picture_34_addreses"
:key="item.url"
fit="cover"
preview-teleported
:preview-src-list="row.picture_addreses.map((item) => item.url)"
style="width: 100px; height: 134px; margin-right: 10px"></el-image>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="主图视频">
<video
:src="row.video_url"
controls
style="width: 100%; height: 282px"
v-if="row.video_url"></video>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="商品规格">
<AppList v-bind="productSpecsTableOptions" :data="row.info?.specs" style="width: 100%"></AppList>
</el-form-item>
<el-form-item label="价格与库存">
<AppList v-bind="productSkuTableOptions" :data="row.info?.sku" style="width: 100%"></AppList>
</el-form-item>
</el-form>
</div>
</template>
</AppList>
</ScoreCard>
</template>
<template v-if="item.type == 4">
<ScoreCard
:maxScore="item.percent"
v-model:score="scoreDetails.speech.score"
v-model:comment="scoreDetails.speech.comment"
@save="$emit('save')"
@next="handleNext">
<AppList v-bind="talkTableOptions" :data="detail.live_data.speeches" default-expand-all>
<template #table-expand="{ row }">
<div class="table-expand-box">
<el-form label-position="top">
<el-form-item label="直播主题卖点">
<div class="form-box" v-html="row.selling_point"></div>
</el-form-item>
<el-form-item label="营销活动">
<div class="form-box" v-html="row.marketing_campaign"></div>
</el-form-item>
<el-form-item label="直播话术内容">
<div class="form-box" v-html="row.content"></div>
</el-form-item>
</el-form>
</div>
</template>
</AppList>
</ScoreCard>
</template>
<!-- 直播演练 -->
<template v-if="item.type == 5">
<ScoreCard
:maxScore="item.percent"
v-model:score="scoreDetails.practice_record1.score"
v-model:comment="scoreDetails.practice_record1.comment"
@save="$emit('save')"
@next="handleNext">
<ScoreCardLive
:livePracticeId="firstLivePractice.id"
:recordId="firstLivePracticeRecord.id"
v-if="firstLivePracticeRecord" />
<el-empty v-else />
</ScoreCard>
</template>
<!-- 直播总结汇报 -->
<template v-if="item.type == 6">
<ScoreCard
:maxScore="item.percent"
:hasNextButton="false"
v-model:score="scoreDetails.report.score"
v-model:comment="scoreDetails.report.comment"
@save="$emit('save')"
@next="handleNext">
<template v-if="detail.live_data.reports.length > 0">
<div v-for="item in detail.live_data.reports" :key="item.report_url" style="height: 600px">
<Preview :url="item.report_url" />
</div>
</template>
<el-empty v-else />
</ScoreCard>
</template>
</el-tab-pane>
</el-tabs>
</template>
<style lang="scss" scoped>
.score-tabs {
:deep(.el-tabs__header) {
width: 1000px;
margin: 0 auto 20px;
}
:deep(.el-tabs__nav-wrap::after) {
display: none;
}
}
.score-header {
display: flex;
align-items: center;
.el-form {
flex: 1;
}
}
.score-box {
width: 100px;
border: 1px solid #dcdfe6;
padding: 10px;
border-radius: 10px;
font-size: 30px;
color: var(--main-color);
display: flex;
align-items: center;
justify-content: center;
}
.table-expand-box {
border: 1px solid #dcdfe6;
padding: 20px;
border-radius: 10px;
}
.form-box {
width: 100%;
border: 1px solid #dcdfe6;
padding: 10px;
border-radius: 6px;
}
</style>
......@@ -10,6 +10,7 @@ const userStore = useUserStore()
const CompetitionLive = defineAsyncComponent(() => import('../components/CompetitionLive.vue'))
const CompetitionLiveProd = defineAsyncComponent(() => import('../components/CompetitionLiveProd.vue'))
const CompetitionLive3 = defineAsyncComponent(() => import('../components/CompetitionLive3.vue'))
const CompetitionOperations = defineAsyncComponent(() => import('../components/CompetitionOperations.vue'))
const route = useRoute()
const id = route.query.id
......@@ -24,6 +25,17 @@ const totalScore = computed(() => {
return Object.values(scoreDetails).reduce((acc, curr) => acc + (curr.score || 0), 0)
})
// 比赛规则
const competitionRule = computed(() => {
const competition_rule = detail.value?.competition_rule || {}
if (competition_rule.config) {
const config = JSON.parse(competition_rule.config)
return { ...competition_rule, ...config }
} else {
return competition_rule
}
})
// 所有评分人的评分列表
let scores = []
const fetchDetail = async () => {
......@@ -137,15 +149,29 @@ onBeforeUnmount(() => {
</div>
</div>
<el-divider />
<template v-if="detail.competition_rule?.competition == 1">
<!-- 网络主播赛项 -->
<template v-if="competitionRule.competition == 1">
<!-- “悦颜坊”美妆护肤案例 -->
<CompetitionLive
:detail="detail"
@save="handleSave"
v-model:scoreDetails="scoreDetails"
v-if="detail.competition_rule?.questions == 1" />
v-if="competitionRule.questions == 1" />
<!-- 襄阳牛肉面2桶装(有牛肉) -->
<CompetitionLiveProd :detail="detail" @save="handleSave" v-model:scoreDetails="scoreDetails" v-else />
</template>
<CompetitionOperations :detail="detail" @save="handleSave" v-model:scoreDetails="scoreDetails" v-else />
<!-- 全媒体运营赛项 -->
<CompetitionOperations
:detail="detail"
@save="handleSave"
v-model:scoreDetails="scoreDetails"
v-else-if="competitionRule.competition == 2" />
<!-- 互联网营销师(直播销售) -->
<CompetitionLive3
:detail="detail"
@save="handleSave"
v-model:scoreDetails="scoreDetails"
v-else-if="competitionRule.competition == 3" />
</AppCard>
</template>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论