提交 8840c701 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 be3d1054
...@@ -4,7 +4,7 @@ export function useChat() { ...@@ -4,7 +4,7 @@ export function useChat() {
const messages = ref([]) const messages = ref([])
const isLoading = ref(false) const isLoading = ref(false)
async function post(message) { async function post(message, isReplace = true) {
isLoading.value = true isLoading.value = true
await fetchEventSource('/api/lab/v1/experiment/qwen/chat', { await fetchEventSource('/api/lab/v1/experiment/qwen/chat', {
method: 'POST', method: 'POST',
...@@ -19,6 +19,9 @@ export function useChat() { ...@@ -19,6 +19,9 @@ export function useChat() {
}, },
onmessage(res) { onmessage(res) {
console.log(res.data) console.log(res.data)
if (res.data === '[DONE]') {
isLoading.value = false
}
try { try {
const message = JSON.parse(res.data) const message = JSON.parse(res.data)
if (message.error) { if (message.error) {
...@@ -28,13 +31,14 @@ export function useChat() { ...@@ -28,13 +31,14 @@ export function useChat() {
const id = message.id const id = message.id
const messageIndex = messages.value.findIndex((session) => session.id === id) const messageIndex = messages.value.findIndex((session) => session.id === id)
let content = message?.choices[0]?.delta.content || '' let content = message?.choices[0]?.delta.content || ''
content = content.replaceAll('\n', '<br/>') if (isReplace) {
content = content.replaceAll('\n', '<br/>')
}
if (messageIndex === -1) { if (messageIndex === -1) {
messages.value.push({ id, role: 'assistant', content }) messages.value.push({ id, role: 'assistant', content })
} else { } else {
messages.value[messageIndex].content = messages.value[messageIndex].content + content messages.value[messageIndex].content = messages.value[messageIndex].content + content
} }
isLoading.value = false
} catch (error) { } catch (error) {
console.log(error) console.log(error)
isLoading.value = false isLoading.value = false
......
...@@ -22,12 +22,13 @@ const emit = defineEmits(['update:modelValue']) ...@@ -22,12 +22,13 @@ const emit = defineEmits(['update:modelValue'])
const index = ref(0) const index = ref(0)
const { open, onChange } = useFileDialog({ const { open, onChange, reset } = useFileDialog({
accept: props.accept, accept: props.accept,
multiple: props.multiple, multiple: props.multiple,
}) })
onChange(async (files) => { onChange(async (files) => {
if (!files) return
const [file] = files const [file] = files
const res = await upload(file) const res = await upload(file)
const nowTime = dayjs().format('YYYY-MM-DD HH:mm:ss') const nowTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
...@@ -39,6 +40,7 @@ onChange(async (files) => { ...@@ -39,6 +40,7 @@ onChange(async (files) => {
updatedValue[index.value] = result updatedValue[index.value] = result
emit('update:modelValue', updatedValue) emit('update:modelValue', updatedValue)
} }
reset()
}) })
const handleOpen = (i = 0) => { const handleOpen = (i = 0) => {
......
...@@ -86,7 +86,14 @@ watch( ...@@ -86,7 +86,14 @@ watch(
messages, messages,
() => { () => {
const lastMessage = messages.value[messages.value.length - 1] const lastMessage = messages.value[messages.value.length - 1]
if (lastMessage) { if (lastMessage && aiActive.value === 1) {
form.selling_point = lastMessage.content
}
if (lastMessage && aiActive.value === 2) {
form.marketing_campaign = lastMessage.content
}
if (lastMessage && aiActive.value === 3) {
form.content = lastMessage.content form.content = lastMessage.content
.replace(/(商品引入|商品讲解|引导转化)/g, wrapWithStyle) .replace(/(商品引入|商品讲解|引导转化)/g, wrapWithStyle)
.replace( .replace(
...@@ -98,17 +105,43 @@ watch( ...@@ -98,17 +105,43 @@ watch(
{ deep: true } { deep: true }
) )
function handleAIGenerate() { const aiActive = ref(1)
post({
role: 'user', function handleAIGenerate(index) {
content: `你是一位网络主播。请根据以下要求撰写直播话术: aiActive.value = index
let content = ''
// 商品卖点
if (index === 1) {
content = `请根据下面的商品名称,生成3~6个商品卖点。
商品名称:${product.value.title}
要求:
1. 卖点应突出商品的特点和优势。
2. 每个卖点应简洁明了,不超过10个字。
3. 卖点应具有一定的吸引力,能够引起消费者的兴趣和购买欲望。
4. 卖点应真实反映商品的实际特点,不得夸大或误导消费者。
5. 每个卖点之间使用分号分割`
}
if (index === 2) {
content = `请根据以下商品名称,生成2~6个商品的营销活动。
商品名称:${product.value.title}
要求:
1. 营销活动应围绕商品的特点和优势展开。
2. 营销活动应包含对目标受众的定位、产品策略、价格策略、渠道策略、促销策略等。
3. 营销活动应具有创意和吸引力,能够引起目标受众的共鸣和购买欲望。
4. 营销活动应考虑到市场竞争和消费者需求,确保活动的可行性和有效性。
5. 营销活动应简洁明了,易于理解和执行,不超过10个字。
6. 每个活动之间使用分号分割。`
}
if (index === 3) {
content = `你是一位网络主播。请根据以下要求撰写直播话术:
1. 直播话术匹配的直播时长为:${form.duration}分钟。 1. 直播话术匹配的直播时长为:${form.duration}分钟。
2. 直播的商品是:${product.value.title} 2. 直播的商品是:${product.value.title}
3. 商品的卖点有:${form.selling_point} 3. 商品的卖点有:${form.selling_point}
4. 营销活动有:${form.marketing_campaign} 4. 营销活动有:${form.marketing_campaign}
5. 直播话术要求包含:商品引入(开场互动、引出话题、引出商品、目标人群锁定)、商品讲解(产品卖点讲解、观众互动、价格福利)、引导转化(催单话术、强调购买方式、结尾互动)等内容模块。而且按照模块进行内容区分。 5. 直播话术要求包含:商品引入(开场互动、引出话题、引出商品、目标人群锁定)、商品讲解(产品卖点讲解、观众互动、价格福利)、引导转化(催单话术、强调购买方式、结尾互动)等内容模块。而且按照模块进行内容区分。
请确保话术简洁明了,突出商品特点,并吸引观众购买。同时,注意控制直播时长,确保在${form.duration}分钟内完成。`, 请确保话术简洁明了,突出商品特点,并吸引观众购买。同时,注意控制直播时长,确保在${form.duration}分钟内完成。`
}) }
post({ role: 'user', content }, index === 3)
} }
</script> </script>
...@@ -124,6 +157,16 @@ function handleAIGenerate() { ...@@ -124,6 +157,16 @@ function handleAIGenerate() {
<LiveProductSelect v-model="form.live_commodity_id"></LiveProductSelect> <LiveProductSelect v-model="form.live_commodity_id"></LiveProductSelect>
</el-form-item> </el-form-item>
<el-form-item label="商品卖点" prop="selling_point"> <el-form-item label="商品卖点" prop="selling_point">
<div class="form-tips">
<el-button
type="primary"
plain
size="small"
@click="handleAIGenerate(1)"
:loading="isLoading && aiActive === 1"
>AI一键生成</el-button
>
</div>
<el-input <el-input
type="textarea" type="textarea"
v-model="form.selling_point" v-model="form.selling_point"
...@@ -131,6 +174,16 @@ function handleAIGenerate() { ...@@ -131,6 +174,16 @@ function handleAIGenerate() {
:rows="4"></el-input> :rows="4"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="营销活动" prop="marketing_campaign"> <el-form-item label="营销活动" prop="marketing_campaign">
<div class="form-tips">
<el-button
type="primary"
plain
size="small"
@click="handleAIGenerate(2)"
:loading="isLoading && aiActive === 2"
>AI一键生成</el-button
>
</div>
<el-input <el-input
type="textarea" type="textarea"
v-model="form.marketing_campaign" v-model="form.marketing_campaign"
...@@ -147,7 +200,7 @@ function handleAIGenerate() { ...@@ -147,7 +200,7 @@ function handleAIGenerate() {
<el-col :sm="24" :md="12" style="border-left: 1px solid #dcdfe6"> <el-col :sm="24" :md="12" style="border-left: 1px solid #dcdfe6">
<div style="text-align: center; margin-bottom: 20px"> <div style="text-align: center; margin-bottom: 20px">
<h2 style="margin-bottom: 20px">直播话术</h2> <h2 style="margin-bottom: 20px">直播话术</h2>
<el-button type="primary" size="large" @click="handleAIGenerate" :loading="isLoading"> <el-button type="primary" size="large" @click="handleAIGenerate(3)" :loading="isLoading && aiActive === 3">
{{ messages.length ? '再次生成直播话术' : 'AI生成直播话术' }} {{ messages.length ? '再次生成直播话术' : 'AI生成直播话术' }}
</el-button> </el-button>
</div> </div>
...@@ -173,3 +226,14 @@ function handleAIGenerate() { ...@@ -173,3 +226,14 @@ function handleAIGenerate() {
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<style scoped>
.form-tips {
position: absolute;
right: 0;
top: -30px;
z-index: 100;
line-height: 22px;
color: #92939a;
}
</style>
...@@ -19,7 +19,13 @@ const listOptions = { ...@@ -19,7 +19,13 @@ const listOptions = {
}, },
columns: [ columns: [
{ label: '序号', type: 'index', width: 60 }, { label: '序号', type: 'index', width: 60 },
{ label: '主播', prop: 'id' }, {
label: '主播',
prop: 'current_user',
computed({ row }) {
return row.current_user.real_name || row.current_user.nickname || row.current_user.username
},
},
{ {
label: '直播时长', label: '直播时长',
prop: 'live_duration', prop: 'live_duration',
......
...@@ -42,7 +42,7 @@ export interface UseLiveChatOptions { ...@@ -42,7 +42,7 @@ export interface UseLiveChatOptions {
} }
export function useLiveChat(options: UseLiveChatOptions = {}) { export function useLiveChat(options: UseLiveChatOptions = {}) {
const { initViewerCount = 20, autoStart = false, updateInterval = 500, defaultMessages } = options const { initViewerCount = 20, autoStart = false, updateInterval = 1000, defaultMessages } = options
const viewers = ref<Viewer[]>([]) const viewers = ref<Viewer[]>([])
const messages = ref<Message[]>([]) const messages = ref<Message[]>([])
const currentTime = ref(0) const currentTime = ref(0)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论