Commit 28953717 by haojie

1

parent 10705f77
......@@ -93,6 +93,9 @@
<template #type="{ row }">
<slot name="type" :row="row"> </slot>
</template>
<template #status="{ row }">
<slot name="status" :row="row"> </slot>
</template>
<template #content="{ row }">
<slot name="content" :row="row"></slot>
</template>
......@@ -196,20 +199,33 @@ onMounted(() => {
});
// 过滤出表格id
const filterTableId = () => {
const is_array = DataType('array', SelectedRows.value);
if (is_array) {
let ids = '';
// 开始过滤
SelectedRows.value.forEach((item: any) => {
if (item.id) {
ids += item.id + '' + ',';
}
});
return ids;
} else {
show_message('格式错误');
const filterTable = () => {
let params: any = {};
const option = props.form.delete_options ?? [{ key: 'id', value: 'ids' }];
if (option) {
// 扩展字段
const is_array = DataType('array', SelectedRows.value);
if (is_array) {
let ids = [];
// 开始过滤
SelectedRows.value.forEach((item: any) => {
option.forEach((it: any) => {
if (item[it.key]) {
// 存在这个参数
if (!params[it.value]) {
params[it.value] = [];
}
if (params[it.value]) {
params[it.value].push(item[it.key]);
}
}
});
});
} else {
show_message('格式错误');
}
}
return params;
};
// 多选事件触发
......@@ -217,14 +233,14 @@ const MultiSelectEvent = async (item: any) => {
if (item.value == 'delete') {
const { form } = props;
loading.value = true;
const ids = filterTableId();
const stauts = await form.delete_api({
ids: ids,
});
const params = filterTable();
const stauts = await form.delete_api(params);
loading.value = false;
if (stauts) {
// 更新表格数据
table_num.value += 1;
// 清空多选项
SelectedRows.value = [];
}
}
};
......
......@@ -369,12 +369,13 @@ const formatTime = (value: string) => {
display: flex;
.audio-player-left {
max-width: 92%;
flex: 1;
}
.check-audio-box {
width: 8%;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
:deep(.check-audio) {
.t-checkbox__input {
border: 1px solid #ffffff;
......
<template>
<div class="admin-page-edit-parent custom-scrollbar">
<div class="admin-page-edit-parent narrow-scrollbar">
<div class="custom-admin-page-edit">
<div class="admin-page-header">
<div>
......@@ -59,67 +59,73 @@
v-for="it in item.lists"
:key="it.name"
>
<div class="label">
{{ it.label }}
</div>
<div class="value">
<template v-if="it.type == 'text'">
<CustomInput
align="left"
class="edit-input"
width="100%"
v-model="it.value"
:placeholder="it.placeholder"
:disabled="it.disabled ? it.disabled : false"
>
<template #rightIcon>
<template v-if="!it.disabled">
<span class="input-right-icon">
<EditInputSvg></EditInputSvg>
</span>
<template v-if="!it.is_hidden">
<div class="label">
{{ it.label }}
</div>
<div class="value">
<template v-if="it.type == 'text'">
<CustomInput
align="left"
class="edit-input"
width="100%"
v-model="it.value"
:placeholder="it.placeholder"
:disabled="it.disabled ? it.disabled : false"
>
<template #rightIcon>
<template v-if="!it.disabled">
<span class="input-right-icon">
<EditInputSvg></EditInputSvg>
</span>
</template>
</template>
</template>
</CustomInput>
</template>
<template v-else-if="it.type == 'select'">
<CustomSelect
:options="it.options"
:name="it.name"
v-model="it.value"
:item="{}"
:align="it.align"
:audio="it.audio"
:audio_list="[]"
:is_watch="it.watch ? it.watch : false"
width="100%"
@change="SelectChange"
@ValueChange="SelectValueChange"
></CustomSelect>
</template>
<template v-else-if="it.type == 'textarea'">
<CustomTextarea
v-model="it.value"
:maxlength="it.maxlength ?? null"
:disabled="form.is_send ? form.is_send.disabled : false"
></CustomTextarea>
</template>
<template v-else-if="it.type == 'number'">
<CustomInput
type="number"
align="left"
class="edit-input"
v-model="it.value"
:placeholder="it.placeholder"
:disabled="it.disabled ? it.disabled : false"
>
<template #rightIcon>
<template v-if="!it.disabled">
<span class="input-right-icon"> M </span>
</CustomInput>
</template>
<template v-else-if="it.type == 'select'">
<CustomSelect
:options="it.options"
:name="it.name"
v-model="it.value"
:item="{}"
:align="it.align"
:audio="it.audio"
:audio_list="audio_list"
:is_watch="it.watch ? it.watch : false"
width="100%"
:multiple="it.multiple ? it.multiple : false"
@change="SelectChange"
@ValueChange="SelectValueChange"
></CustomSelect>
</template>
<template v-else-if="it.type == 'textarea'">
<CustomTextarea
v-model="it.value"
:maxlength="it.maxlength ?? null"
:disabled="
form.is_send ? form.is_send.disabled : false
"
></CustomTextarea>
</template>
<template v-else-if="it.type == 'number'">
<CustomInput
type="number"
align="left"
width="100%"
class="edit-input"
v-model="it.value"
:placeholder="it.placeholder"
:disabled="it.disabled ? it.disabled : false"
>
<template #rightIcon>
<template v-if="!it.disabled">
<span class="input-right-icon"> M </span>
</template>
</template>
</template>
</CustomInput>
</template>
</div>
</CustomInput>
</template>
</div>
</template>
</div>
</div>
</template>
......@@ -194,10 +200,17 @@ import ManualResponseSvg from '@/assets/svg/form/ManualResponse.svg';
import { useRouter } from 'vue-router';
import { show_message } from '@/utils/tdesign_tool';
import { getFormParams } from '@/constants/admin_form';
import { reactive, ref } from 'vue';
const props = defineProps<{
form: any;
}>();
import { ref } from 'vue';
const props = withDefaults(
defineProps<{
form: any;
audio_list?: any[];
}>(),
{
audio_list: () => [],
}
);
const emit = defineEmits(['ConfigChange']);
const router = useRouter();
const loading = ref(false);
// 弹窗状态
......@@ -225,18 +238,22 @@ const onSend = () => {
// 下拉框事件
const SelectChange = (value: string, fun: any) => {
console.log(value);
fun(value);
};
// 开始转换语音
const StartConvert = () => {
const StartConvert = async () => {
const { form } = props;
// 校验表单完整性
let params = getFormParams(form.form_options);
if (!params) {
return;
}
form.conversion.method(params, form.page_name);
loading.value = true;
// 请求语音
await form.conversion.method(params, form.page_name);
loading.value = false;
};
// 提交接口
......@@ -257,12 +274,18 @@ const realDelete = async () => {
const { form } = props;
loading.value = true;
// 获取当前id
await form.delete_api(
{
ids: form.get_id(),
},
form.back_url
);
if (form.get_params) {
// 自定义参数
await form.delete_api(form.get_params(), form.back_url);
} else {
await form.delete_api(
{
ids: form.get_id(),
},
form.back_url
);
}
loading.value = false;
};
......@@ -276,16 +299,11 @@ const onDelete = async () => {
realDelete();
}
};
// 记录当前语音和语言
const CurrentConfig = reactive({
language: '',
voice: '',
});
// 语音列表
const SelectValueChange = (name: string, value: string) => {
if (name == 'language' || name == 'voice') {
CurrentConfig[name] = value;
if (name == 'language' || (name == 'voice' && props.form.audition)) {
emit('ConfigChange', name, value);
}
};
</script>
......
......@@ -10,9 +10,15 @@
alt=""
class="play-icon"
@click="onPlay"
v-if="!playStatus"
v-show="!playStatus"
/>
<img
:src="imgs.stop"
alt=""
class="play-icon"
@click="onPause"
v-show="playStatus"
/>
<img :src="imgs.stop" alt="" class="play-icon" @click="onPause" v-else />
<template v-if="need_progress">
<span class="play-time">
{{ transTime(audioCurrent) }}/{{ transTime(audioDuration) }}
......
......@@ -4,6 +4,7 @@
v-model="SelectValue"
:placeholder="item.placeholder"
:filterable="filterable"
:multiple="multiple"
:popupProps="{
overlayClassName: [className, 'admin-select-popup'],
}"
......@@ -40,7 +41,7 @@ const props = withDefaults(
defineProps<{
item?: any;
options: any[];
modelValue: number | string;
modelValue: number | string | string[];
width?: string;
className?: string;
align?: string;
......@@ -49,6 +50,7 @@ const props = withDefaults(
filterable?: boolean;
audio_list?: string[];
name?: string;
multiple?: boolean;
}>(),
{
width: '357px',
......@@ -57,6 +59,7 @@ const props = withDefaults(
is_watch: false,
filterable: false,
audio_list: () => [],
multiple: false,
}
);
const emit = defineEmits(['update:modelValue', 'change', 'ValueChange']);
......@@ -89,6 +92,22 @@ watch(
}
.t-select__list {
padding: 0;
.t-checkbox {
.t-checkbox__label {
color: #00dddd;
}
.t-checkbox__input {
background: transparent;
}
}
.t-is-selected {
.t-checkbox__input {
border-color: #00dddd;
&::after {
border-color: #00dddd;
}
}
}
.t-select-option {
color: white;
--ripple-color: #00dddd;
......@@ -99,11 +118,26 @@ watch(
color: #00dddd;
background: #161616 !important;
}
.t-select-option__hover {
.t-checkbox {
.t-checkbox__input {
border-color: #00dddd !important;
}
.t-checkbox__label {
color: #00dddd;
}
}
}
}
}
.custom-admin-select {
display: flex;
align-items: center;
.t-select-input--multiple {
.t-input--focused {
box-shadow: 0px 0px 0px 1px #00dddd;
}
}
.select-label {
color: white;
width: 60px;
......@@ -137,6 +171,12 @@ watch(
.t-fake-arrow {
color: #00dddd;
}
.t-input__prefix {
display: flex;
.t-tag {
background: #00dddd;
}
}
}
}
}
......
......@@ -39,6 +39,11 @@
{{ row.type }}
</slot>
</template>
<template #status="{ row }">
<slot name="status" :row="row">
{{ row.status }}
</slot>
</template>
<template #edit="{ row }">
<slot name="edit" :row="row">
<span class="edit-text" @click="onEdit(row)">编辑</span>
......
import { getLocalData, setLocalData } from '@/utils/tool';
import { DataType, getLocalData, setLocalData } from '@/utils/tool';
import router from '@/router';
import { show_message } from '@/utils/tdesign_tool';
import { Validationrules } from '@/utils/tool';
import { DeleteVioce } from '@/utils/api/ai';
import {
DeleteVioce,
InteractionTableDelete,
getLiveStreamConfig,
LiveStreamTableDelete,
} from '@/utils/api/ai';
// 语音列表
export const voice_list = [
{
......@@ -67,8 +72,18 @@ export const language_type = {
// 互动类型
export const interaction_type = {
'0': '直播互动',
'0': '直播互动', // 串场互动
'0_': 'crosstown', // name
'1': '自动回复',
'1_': 'auto',
};
// 直播管理-状态
export const live_stream_status = {
'1': '等待',
'2': '进行中',
'3': '完成',
'4': '失败',
};
// 任务类型
......@@ -83,6 +98,10 @@ export const getFormParams = (list: any[]) => {
// 遍历整个列表
for (let i = 0; i < list.length; i++) {
const item: any = list[i];
if (item.is_hidden) {
// 隐藏的内容不参与
continue;
}
for (let j = 0; j < item.lists.length; j++) {
const it = item.lists[j];
// 校验规则
......@@ -161,8 +180,22 @@ export const EditFillData = (form: any[], row: any) => {
// 查找name相同的字段
Object.keys(row).forEach((key: string) => {
if (it.name == key) {
// 填充数据
it.value = row[key] + '';
if (
typeof row[key] === 'string' &&
(row[key] + '').indexOf('[') !== -1 &&
DataType('array', it.value)
) {
const list = JSON.parse(row[key]);
list.forEach((list_item: any) => {
it.value.push(list_item);
});
} else if (
typeof row[key] === 'string' ||
typeof row[key] === 'number'
) {
// 填充数据
it.value = row[key] + '';
}
}
});
});
......@@ -194,6 +227,29 @@ export const FilterConfigFill = (resData: any, form: any[]) => {
});
};
// 直播管理基本配置,格式转换
export const LiveStreamFill = (resData: any, form: any) => {
form.forEach((item: any) => {
item.lists.forEach((it: any) => {
// 循环resdata的key
Object.keys(resData).forEach((key: any) => {
if (it.name == key && DataType('array', resData[key])) {
// 转换为select组件需要的格式
const list: any = [];
resData[key].forEach((res: any) => {
const obj = {
label: res.title,
value: res.id,
};
list.push(obj);
});
it.options = list;
}
});
});
});
};
// 话术管理删除
export const DiscourseManagementDelete = async (
data: any,
......@@ -214,3 +270,54 @@ export const DiscourseManagementDelete = async (
console.log(e);
}
};
// 互动设置删除
export const InteractiveSettingDelete = async (
data: any,
path: string = ''
) => {
try {
const res: any = await InteractionTableDelete(data);
if (res.code == 0) {
show_message('删除成功', 'success');
if (path) {
router.replace({
path: path,
});
}
return true;
}
} catch (e) {
console.log(e);
}
};
// 直播管理删除
export const LiveStreamDelete = async (data: any, path: string = '') => {
try {
const res: any = await LiveStreamTableDelete(data);
if (res.code == 0) {
show_message('删除成功', 'success');
if (path) {
router.replace({
path: path,
});
}
return true;
}
} catch (e) {
console.log(e);
}
};
// 获取直播配置并填充数据
export const LiveStreamConfigFill = async (form: any) => {
try {
const res: any = await getLiveStreamConfig();
if (res.code == 0) {
LiveStreamFill(res.data, form);
}
} catch (e) {
console.log(e);
}
};
......@@ -80,12 +80,16 @@ export default function () {
}
status.value = false;
let res: any = null;
// 话术内容
let content = '';
if (name === admin_task_type.dialogues) {
// 话术管理
res = await DiscourseManagementConvertTask(data);
content = data.content;
} else if (name === admin_task_type.interaction) {
// 互动设置
res = await SubmitTaskInteract(data);
content = data.reply ?? data.interact;
}
//
if (res.code == 0 && res.data.hash) {
......@@ -100,7 +104,7 @@ export default function () {
check_time: 0,
});
// 开始定时任务
openInterval(res.data.hash, data.content, name);
openInterval(res.data.hash, content, name);
} else {
console.log('报错了');
console.log(res);
......
......@@ -59,7 +59,7 @@ const SubmitCreateEvent = async () => {
// 获取id
const getRowid = () => {
return cur_id.value + '';
return [cur_id.value];
};
// 编辑页面组件
const ManagementForm = reactive({
......@@ -191,6 +191,21 @@ const ManagementForm = reactive({
},
],
},
// 隐藏的内容
{
type: 'text',
label: '',
name: 'is_edit',
value: '1',
align: 'left',
is_hidden: true,
rules: [
{
type: 'required',
message: '隐藏内容缺失',
},
],
},
{
type: 'select',
label: '语音',
......
......@@ -19,6 +19,7 @@ import {
FilterConfigFill,
language_list,
interaction_type,
InteractiveSettingDelete,
} from '@/constants/admin_form';
import { interactive_setting_edit } from '@/constants/token';
import {
......@@ -87,6 +88,8 @@ const ManagementForm = reactive({
edit_key: interactive_setting_edit,
// 新增页面
create_page: '/AILiveStreaming/InteractiveSetting/create',
// 删除api
delete_api: InteractiveSettingDelete,
// 多选功能操作项
row_selected_options: [
{
......
......@@ -8,12 +8,18 @@ import { reactive } from 'vue';
import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router';
import { admin_task_type } from '@/constants/admin_form';
import { admin_task_type, voice_list } from '@/constants/admin_form';
import ConvertVoice from '@/hooks/ConvertVoice';
import { InteractionTableCreate } from '@/utils/api/ai';
const { CurrentVoice, SubmitConvertTask } = ConvertVoice();
const router = useRouter();
const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
};
// 获取选中的语言hash
const getHash = () => {
let list = ManagementForm.conversion.list;
const index = list.findIndex((item: any) => item.is_check);
return index !== -1 ? list[index].hash : '';
};
// 修改组件显示状态
const ChangeComponentsShow = (value: string) => {
ManagementForm.form_options.forEach((item: any) => {
......@@ -25,6 +31,27 @@ const ChangeComponentsShow = (value: string) => {
}
});
};
const SubmitCreateEvent = async () => {
try {
// 先过滤出选中的hash
const hash = getHash();
if (!hash) {
show_message('必须选择一条语音');
return;
}
const res: any = await InteractionTableCreate({
hash: hash,
});
if (res.code == 0) {
show_message('添加成功', 'success');
router.replace({
path: ManagementForm.back_url,
});
}
} catch (e) {
console.log(e);
}
};
// 新增组件--所有value为空
const ManagementForm = reactive({
page_name: admin_task_type.interaction,
......@@ -34,17 +61,48 @@ const ManagementForm = reactive({
// 是否显示返回列表页
back: true,
back_url: '/AILiveStreaming/InteractiveSetting',
// 能否删除,
delete: false,
// 删除api
delete_api: '',
submit_api: '1',
// 新增接口
submit_api: SubmitCreateEvent,
// 是否试听
audition: true,
//能否重置
reset: true,
// 是否转换为语音
conversion: false,
// 播放音频
play_audio: false,
// 是否转换为语音 -- 自定义方法
conversion: {
list: CurrentVoice.list,
// 测试list
// list: [
// {
// audio: [
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/4c1bdfa0fd604ce3ab2b1579a788685e_0.mp3',
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/214fcc1b9c4c4d8ba4851a7d4c20b481_1.mp3',
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/adf91b511b484fe4be5a5c192c4b933d_2.mp3',
// ],
// content:
// '大家好!今天我很兴奋地向大家介绍我们最新的牙刷产品!这款牙刷采用了最先进的声波技术,可以快速且彻底地清洁牙齿,轻轻松松祛除口腔细菌,令您每天远离口臭和牙齿问题。它还拥有集多种功能于一身的设计:磁悬浮电机、充电式电池、可调节的振动模式等,完美地满足了每个人的口腔需求。与传统的牙刷相比,这款牙刷具有更强的能力和更广泛的使用范围。拥有一款优质的牙刷,是每个人在健康生活中不可或缺的一个环节。所以,我们的团队不仅将其引入这个市场,而且已经通过大量的实验和测试,证明了这款牙刷确实能够在口腔清洁方面达到出色的表现。如果您是那种注重口腔卫生的人,那么这款牙刷绝对是您的首选',
// hash: 'a6d66c701602513e93e70ae962223668',
// is_check: false,
// status: true,
// check_time: 0,
// },
// {
// audio: [
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/4c1bdfa0fd604ce3ab2b1579a788685e_0.mp3',
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/214fcc1b9c4c4d8ba4851a7d4c20b481_1.mp3',
// 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/adf91b511b484fe4be5a5c192c4b933d_2.mp3',
// ],
// content:
// '大家好!今天我很兴奋地向大家介绍我们最新的牙刷产品!这款牙刷采用了最先进的声波技术,可以快速且彻底地清洁牙齿,轻轻松松祛除口腔细菌,令您每天远离口臭和牙齿问题。它还拥有集多种功能于一身的设计:磁悬浮电机、充电式电池、可调节的振动模式等,完美地满足了每个人的口腔需求。与传统的牙刷相比,这款牙刷具有更强的能力和更广泛的使用范围。拥有一款优质的牙刷,是每个人在健康生活中不可或缺的一个环节。所以,我们的团队不仅将其引入这个市场,而且已经通过大量的实验和测试,证明了这款牙刷确实能够在口腔清洁方面达到出色的表现。如果您是那种注重口腔卫生的人,那么这款牙刷绝对是您的首选',
// hash: 'a6d66c701602513e93e70ae9622236681',
// is_check: false,
// status: true,
// check_time: 0,
// },
// ],
method: SubmitConvertTask,
},
form_options: [
{
icon: '',
......@@ -53,19 +111,25 @@ const ManagementForm = reactive({
{
type: 'select',
label: '类型',
name: 'select_type',
name: 'type',
placeholder: '请选择类型',
value: 'auto',
value: '',
align: 'left',
watch: ChangeComponentsShow,
options: [
{
label: '自动回复设置',
value: 'auto',
value: '1',
},
{
label: '串场互动话术设置',
value: 'crosstown',
value: '0',
},
],
rules: [
{
type: 'required',
message: '类型必选',
},
],
},
......@@ -92,6 +156,27 @@ const ManagementForm = reactive({
value: 'en',
},
],
rules: [
{
type: 'required',
message: '语言必选',
},
],
},
// 隐藏的内容
{
type: 'text',
label: '',
name: 'is_edit',
value: '1',
align: 'left',
is_hidden: true,
rules: [
{
type: 'required',
message: '隐藏内容缺失',
},
],
},
{
type: 'select',
......@@ -101,14 +186,11 @@ const ManagementForm = reactive({
value: '',
align: 'left',
audio: true,
options: [
{
label: '小微 (直播间专属)',
value: '123',
},
options: voice_list,
rules: [
{
label: '小爱 (直播间专属)',
value: '12345',
type: 'required',
message: '语音必选',
},
],
},
......@@ -118,22 +200,48 @@ const ManagementForm = reactive({
icon: 'message',
title: '自动回复设置',
is_hidden: false,
name: 'auto',
name: '1',
lists: [
{
type: 'text',
label: '标题',
name: 'title',
placeholder: '请输入标题',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '标题必填',
},
],
},
{
type: 'text',
label: '触发关键词',
name: 'language_20',
name: 'key_words',
placeholder: '请输入',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '触发关键词必填',
},
],
},
{
type: 'textarea',
label: '回复内容',
name: 'product_30',
name: 'reply',
placeholder: '请输入语音内容',
value: '',
rules: [
{
type: 'required',
message: '回复内容必填',
},
],
},
],
},
......@@ -141,22 +249,34 @@ const ManagementForm = reactive({
icon: 'discourseBind',
title: '串场互动话术设置',
is_hidden: true,
name: 'crosstown',
name: '0',
lists: [
{
type: 'text',
label: '标题',
name: 'language_20',
name: 'title',
placeholder: '请输入',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '标题必填',
},
],
},
{
type: 'textarea',
label: '话术内容',
name: 'product_30',
name: 'interact',
placeholder: '请输入话术内容',
value: '',
rules: [
{
type: 'required',
message: '话术内容必填',
},
],
},
],
},
......
<template>
<PageEdit :form="ManagementForm"></PageEdit>
<PageEdit
:form="ManagementForm"
:audio_list="audio_list"
@ConfigChange="ConfigChange"
></PageEdit>
</template>
<script lang="ts" setup>
import PageEdit from '@/components/Admin/PageEdit.vue';
import { onBeforeMount, reactive } from 'vue';
import { onBeforeMount, reactive, ref, watch } from 'vue';
import { interactive_setting_edit } from '@/constants/token';
import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router';
import {
......@@ -14,13 +17,40 @@ import {
EditFillData,
admin_task_type,
voice_list,
interaction_type,
InteractiveSettingDelete,
} from '@/constants/admin_form';
import { InteractionTableUpdate } from '@/utils/api/ai';
import ConvertVoice from '@/hooks/ConvertVoice';
const { CurrentVoice, SubmitConvertTask } = ConvertVoice();
const router = useRouter();
const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
// 当前试听语音
const audio_list = ref([]);
const old_hash = ref('');
const cur_id = ref('');
// 记录当前语音和语言
const CurrentConfig = reactive({
language: '',
voice: '',
});
watch(CurrentConfig, (config) => {
if (config.language && config.voice) {
// 修改试听语音
const obj = voice_list.find((item: any) => item.value == config.voice);
if (obj) {
audio_list.value = [obj.audio[config.language]];
}
}
});
const ConfigChange = (name: string, value: string) => {
CurrentConfig[name] = value;
};
// 获取row id
const getCurrentId = () => {
return [cur_id.value];
};
// 修改组件显示状态
const ChangeComponentsShow = (value: string) => {
ManagementForm.form_options.forEach((item: any) => {
......@@ -32,6 +62,36 @@ const ChangeComponentsShow = (value: string) => {
}
});
};
// 获取选中的语言hash
const getHash = () => {
let list = ManagementForm.conversion.list;
const index = list.findIndex((item: any) => item.is_check);
return index !== -1 ? list[index].hash : '';
};
//自定义提交事件
const SubmitCreateEvent = async () => {
// 先过滤出选中的hash
const hash = getHash();
if (!hash || !old_hash.value) {
show_message('必须选择一条语音');
return;
}
try {
const res: any = await InteractionTableUpdate({
hash: hash,
old_hash: old_hash.value,
});
if (res.code == 0) {
show_message('修改成功', 'success');
router.replace({
path: ManagementForm.back_url,
});
}
} catch (e) {
console.log(e);
}
};
// 编辑页面组件
const ManagementForm = reactive({
page_name: admin_task_type.interaction,
......@@ -42,10 +102,13 @@ const ManagementForm = reactive({
back: true,
back_url: '/AILiveStreaming/InteractiveSetting',
// 删除api
delete_api: '1',
submit_api: '1',
delete_api: InteractiveSettingDelete,
// 删除前是否确认
delete_confirm: true,
submit_api: SubmitCreateEvent,
get_id: getCurrentId,
// 是否试听
audition: true,
//能否重置
reset: true,
// 是否转换为语音 -- 自定义方法
......@@ -90,19 +153,25 @@ const ManagementForm = reactive({
{
type: 'select',
label: '类型',
name: 'select_type',
name: 'type',
placeholder: '请选择类型',
value: 'auto',
value: '',
align: 'left',
watch: ChangeComponentsShow,
options: [
{
label: '自动回复设置',
value: 'auto',
value: '1',
},
{
label: '串场互动话术设置',
value: 'crosstown',
value: '0',
},
],
rules: [
{
type: 'required',
message: '类型必选',
},
],
},
......@@ -129,6 +198,27 @@ const ManagementForm = reactive({
value: 'en',
},
],
rules: [
{
type: 'required',
message: '语言必选',
},
],
},
// 隐藏的内容
{
type: 'text',
label: '',
name: 'is_edit',
value: '1',
align: 'left',
is_hidden: true,
rules: [
{
type: 'required',
message: '隐藏内容缺失',
},
],
},
{
type: 'select',
......@@ -139,6 +229,12 @@ const ManagementForm = reactive({
align: 'left',
audio: true,
options: voice_list,
rules: [
{
type: 'required',
message: '语音必选',
},
],
},
],
},
......@@ -146,22 +242,48 @@ const ManagementForm = reactive({
icon: 'message',
title: '自动回复设置',
is_hidden: false,
name: 'auto',
name: '1',
lists: [
{
type: 'text',
label: '标题',
name: 'title',
placeholder: '请输入标题',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '标题必填',
},
],
},
{
type: 'text',
label: '触发关键词',
name: 'language_20',
name: 'key_words',
placeholder: '请输入',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '触发关键词必填',
},
],
},
{
type: 'textarea',
label: '回复内容',
name: 'product_30',
name: 'reply',
placeholder: '请输入语音内容',
value: '',
rules: [
{
type: 'required',
message: '回复内容必填',
},
],
},
],
},
......@@ -169,22 +291,34 @@ const ManagementForm = reactive({
icon: 'discourseBind',
title: '串场互动话术设置',
is_hidden: true,
name: 'crosstown',
name: '0',
lists: [
{
type: 'text',
label: '标题',
name: 'language_20',
name: 'title',
placeholder: '请输入',
value: '',
align: 'left',
rules: [
{
type: 'required',
message: '标题必填',
},
],
},
{
type: 'textarea',
label: '话术内容',
name: 'product_30',
name: 'interact',
placeholder: '请输入话术内容',
value: '',
rules: [
{
type: 'required',
message: '话术内容必填',
},
],
},
],
},
......@@ -199,6 +333,40 @@ onBeforeMount(() => {
);
// 填充
EditFillData(ManagementForm.form_options, row);
const content =
typeof row.interact == 'string' ? row.interact : row.interact.reply;
// 填充原有的语音列表
ManagementForm.conversion.list.push({
hash: row.hash,
status: true,
audio: JSON.parse(row.audio),
content: content,
is_check: false,
check_time: 0,
});
// 获取本地的语言语音
if (row.language && row.voice) {
CurrentConfig.language = row.language;
CurrentConfig.voice = row.voice;
}
// 设置类型
ChangeComponentsShow(row.type);
if (
row.type == '1' &&
row.interact &&
row.interact.key_words &&
row.interact.reply
) {
// 自动回复
EditFillData(ManagementForm.form_options, {
key_words: row.interact.key_words,
reply: row.interact.reply,
});
}
// 获取old_hash
old_hash.value = row.hash;
cur_id.value = row.id;
});
</script>
......
......@@ -3,31 +3,81 @@
:form="ManagementForm"
v-model:list="ManagementForm.table_list"
@reset="ResetFilter"
@PageNumChange="PageNumChange"
>
<template #title>
<div>111</div>
</template>
<template #edit="{ row }">
<!-- custom -->
<div class="custom-operation" @click="onEdit(row)">编辑</div>
<div class="custom-operation" @click="onDetail(row)">查看</div>
<div class="custom-operation" @click="onReply(row)">人工回复</div>
</template>
<template #status="{ row }">
{{ live_stream_status[row.status] }}
</template>
</AdminPublicPageVue>
</template>
<script lang="ts" setup>
import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { reactive } from 'vue';
import { onBeforeMount, reactive, ref } from 'vue';
import { isDevContext } from '@/utils/tool';
import { ResetForm, EditButtonEvent } from '@/constants/admin_form';
import {
ResetForm,
EditButtonEvent,
FilterConfigFill,
live_stream_status,
LiveStreamDelete,
} from '@/constants/admin_form';
import { useRouter } from 'vue-router';
import {
live_stream_edit,
live_stream_detail,
live_stream_reply,
} from '@/constants/token';
import {
LiveStreamFilterConfig,
LiveStreamTableList,
LiveStreamFilter,
} from '@/utils/api/ai';
const router = useRouter();
const pageNum = ref(1);
const pageSize = ref(10);
// 开始筛选
const onFilter = async (params: any) => {
try {
const res: any = await LiveStreamFilter({
page: pageNum.value,
limit: pageSize.value,
...params,
});
return {
list: res.data.data,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 获取表格数据
const getTableList = async () => {
try {
const res: any = await LiveStreamTableList({
page: pageNum.value,
limit: pageSize.value,
});
return {
list: res.data.data,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 分页变化
const PageNumChange = (value: number) => {
pageNum.value = value;
};
// 表单配置项
const ManagementForm = reactive({
title: '直播管理',
......@@ -37,17 +87,27 @@ const ManagementForm = reactive({
// 能否筛选
filter: true,
// 筛选接口
filter_api: isDevContext() ? '' : '',
filter_api: onFilter,
// 能否新增
add: true,
// 表格key--用来缓存表格分页
local_key: 'admin_live_stream',
// 表格数据
table_list: [],
// 表格接口
table_api: isDevContext() ? '' : '',
// api类型
table_api_type: 'get',
table_api: getTableList,
// 删除api
delete_api: LiveStreamDelete,
// 删除api拓展字段
delete_options: [
{
key: 'id',
value: 'ids',
},
{
key: 'hash',
value: 'hash',
},
],
// 能否多选--默认为true
checkbox: true,
// 编辑页面
......@@ -76,11 +136,11 @@ const ManagementForm = reactive({
},
{
title: '直播间标题',
colKey: 'lv_title',
colKey: 'live_title',
},
{
title: '直播间接',
colKey: 'connect',
title: '直播间接',
colKey: 'live_link',
align: 'center',
},
{
......@@ -98,54 +158,31 @@ const ManagementForm = reactive({
filter_option: [
{
type: 'select',
name: 'select_title',
name: 'live_title',
label: '标题',
placeholder: '请选择标题',
value: '',
options: [
{
label: '你好',
value: '你好',
},
{
label: '你好2',
value: '你好2',
},
],
options: [],
// 能否输入
filterable: true,
},
{
type: 'select',
name: 'select_product',
label: '产品',
placeholder: '产品',
name: 'live_link',
label: '链接',
placeholder: '请选择链接',
value: '',
options: [
{
label: '你好',
value: '你好',
},
{
label: '你好2',
value: '你好2',
},
],
options: [],
// 能否输入
filterable: true,
},
{
type: 'select',
name: 'select_language',
label: '语言',
placeholder: '语言',
name: 'status',
label: '状态',
placeholder: '选择状态',
value: '',
options: [
{
label: '你好',
value: '你好',
},
{
label: '你好2',
value: '你好2',
},
],
options: [],
},
],
});
......@@ -167,6 +204,34 @@ const onReply = (row: any) => {
//
EditButtonEvent(live_stream_reply, ManagementForm.reply_page, row);
};
const getFilterConfig = async () => {
try {
const res: any = await LiveStreamFilterConfig();
if (res.data) {
FilterConfigFill(res.data, ManagementForm.filter_option);
// 修改status的数组类型
ManagementForm.filter_option.forEach((item: any) => {
if (item.name == 'status') {
item.options = [];
res.data.status.forEach((it: any) => {
let obj = {
label: live_stream_status[it],
value: it,
};
item.options.push(obj);
});
}
});
}
} catch (e) {
console.log(e);
}
};
onBeforeMount(() => {
getFilterConfig();
});
</script>
<style lang="less">
......
......@@ -4,17 +4,38 @@
<script lang="ts" setup>
import PageEdit from '@/components/Admin/PageEdit.vue';
import { reactive } from 'vue';
import { getLocalData, isDevContext } from '@/utils/tool';
import { onBeforeMount, reactive } from 'vue';
import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router';
import { LiveStreamTableCreate } from '@/utils/api/ai';
import { LiveStreamConfigFill, getFormParams } from '@/constants/admin_form';
const router = useRouter();
const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
};
// 新增接口
const SubmitCreateEvent = async () => {
try {
// 过滤出所有value
const params = getFormParams(ManagementForm.form_options);
if (!params) {
return;
}
const res: any = await LiveStreamTableCreate(params);
if (res.code == 0) {
show_message('添加成功', 'success');
router.replace({
path: ManagementForm.back_url,
});
}
} catch (e) {
console.log(e);
}
};
// 新增组件--所有value为空
const ManagementForm = reactive({
title: '互动设置',
title: '直播管理',
title_2: '新增',
body_title: '新增',
// 是否显示返回列表页
......@@ -27,7 +48,7 @@ const ManagementForm = reactive({
// 能否提交
submit: true,
// 提交接口
submit_api: isDevContext() ? '' : '',
submit_api: SubmitCreateEvent,
//能否重置
reset: true,
// 是否转换为语音
......@@ -42,16 +63,16 @@ const ManagementForm = reactive({
{
type: 'text',
label: '直播间标题',
name: 'title_1',
name: 'live_title',
value: '',
disabled: true,
placeholder: '',
placeholder: '请输入直播间标题',
},
{
type: 'text',
label: '直播间接',
name: 'title_12',
label: '直播间接',
name: 'live_link',
value: '',
placeholder: '请输入直播间链接',
},
],
},
......@@ -62,60 +83,36 @@ const ManagementForm = reactive({
{
type: 'select',
label: '直播话术',
name: 'language_1',
name: 'live_voice',
placeholder: '请选择语言',
value: '',
value: [],
align: 'left',
options: [
{
label: '话术1',
value: 'cn',
},
{
label: '话术2',
value: 'en',
},
],
options: [],
multiple: true,
},
{
type: 'select',
label: '自动回复话术',
name: 'voice',
name: 'live_auto',
placeholder: '请选择自动回复话术',
value: '',
value: [],
align: 'left',
options: [
{
label: '自动回复话术1',
value: '123',
},
{
label: '自动回复话术2',
value: '12345',
},
],
options: [],
multiple: true,
},
{
type: 'select',
label: '串场互动话术',
name: 'voice',
name: 'live_interaction',
placeholder: '请选择串场互动话术',
value: '',
value: [],
align: 'left',
options: [
{
label: '串场互动话术1',
value: '123',
},
{
label: '串场互动话术2',
value: '12345',
},
],
options: [],
multiple: true,
},
{
type: 'number',
name: 'number',
name: 'interaction_interval',
label: '串场互动触发时间间隔',
value: '',
},
......@@ -123,6 +120,15 @@ const ManagementForm = reactive({
},
],
});
const onFill = async () => {
const data = await LiveStreamConfigFill(ManagementForm.form_options);
};
onBeforeMount(() => {
// 填充数据
onFill();
});
</script>
<style lang="less"></style>
......@@ -6,7 +6,7 @@
import PageEdit from '@/components/Admin/PageEdit.vue';
import { onBeforeMount, reactive } from 'vue';
import { live_stream_detail } from '@/constants/token';
import { getLocalData, isDevContext } from '@/utils/tool';
import { isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router';
import { getEditLocalData, EditFillData } from '@/constants/admin_form';
......
......@@ -4,16 +4,50 @@
<script lang="ts" setup>
import PageEdit from '@/components/Admin/PageEdit.vue';
import { onBeforeMount, reactive } from 'vue';
import { onBeforeMount, reactive, ref } from 'vue';
import { live_stream_edit } from '@/constants/token';
import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router';
import { getEditLocalData, EditFillData } from '@/constants/admin_form';
import {
getEditLocalData,
LiveStreamConfigFill,
EditFillData,
getFormParams,
LiveStreamDelete,
} from '@/constants/admin_form';
import { LiveStreamTableUpdate } from '@/utils/api/ai';
const router = useRouter();
const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
};
const cur_id = ref('');
const cur_hash = ref('');
// 获取删除接口参数
const getDeleteParams = () => {
return {
ids: [cur_id.value],
hash: [cur_hash.value],
};
};
//自定义提交事件
const SubmitCreateEvent = async () => {
const params = getFormParams(ManagementForm.form_options);
if (!params) {
return;
}
try {
const res: any = await LiveStreamTableUpdate(params);
if (res.code == 0) {
show_message('修改成功', 'success');
router.replace({
path: ManagementForm.back_url,
});
}
} catch (e) {
console.log(e);
}
};
// 编辑页面组件
const ManagementForm = reactive({
title: '直播管理',
......@@ -23,12 +57,16 @@ const ManagementForm = reactive({
back: true,
back_url: '/AILiveStreaming/LiveStream',
// 能否删除,
delete: true,
delete: false,
// 删除api
delete_api: isDevContext() ? '' : '',
delete_api: LiveStreamDelete,
get_params: getDeleteParams,
// 能否提交
submit: true,
submit_api: isDevContext() ? '' : '',
// 提交接口
submit_api: SubmitCreateEvent,
// 删除前是否确认
delete_confirm: true,
//能否重置
reset: true,
// 是否转换为语音
......@@ -43,16 +81,16 @@ const ManagementForm = reactive({
{
type: 'text',
label: '直播间标题',
name: 'title_1',
name: 'live_title',
value: '',
disabled: true,
placeholder: '',
placeholder: '请输入直播间标题',
},
{
type: 'text',
label: '直播间接',
name: 'title_12',
label: '直播间接',
name: 'live_link',
value: '',
placeholder: '请输入直播间链接',
},
],
},
......@@ -63,72 +101,62 @@ const ManagementForm = reactive({
{
type: 'select',
label: '直播话术',
name: 'language_1',
name: 'live_voice',
placeholder: '请选择语言',
value: '',
value: [],
align: 'left',
options: [
{
label: '话术1',
value: 'cn',
},
{
label: '话术2',
value: 'en',
},
],
options: [],
multiple: true,
},
{
type: 'select',
label: '自动回复话术',
name: 'voice',
name: 'live_auto',
placeholder: '请选择自动回复话术',
value: '',
value: [],
align: 'left',
options: [
{
label: '自动回复话术1',
value: '123',
},
{
label: '自动回复话术2',
value: '12345',
},
],
options: [],
multiple: true,
},
{
type: 'select',
label: '串场互动话术',
name: 'voice',
name: 'live_interaction',
placeholder: '请选择串场互动话术',
value: '',
value: [],
align: 'left',
options: [
{
label: '串场互动话术1',
value: '123',
},
{
label: '串场互动话术2',
value: '12345',
},
],
options: [],
multiple: true,
},
{
type: 'number',
name: 'number',
name: 'interaction_interval',
label: '串场互动触发时间间隔',
value: '',
},
{
type: 'text',
name: 'hash',
label: 'hash',
value: '',
is_hidden: true,
},
],
},
],
});
const onFill = async () => {
const data = await LiveStreamConfigFill(ManagementForm.form_options);
};
onBeforeMount(() => {
onBeforeMount(async () => {
// 填充数据--话术
await onFill();
// 本地是否有缓存
const row = getEditLocalData(live_stream_edit, ManagementForm.back_url);
EditFillData(ManagementForm.form_options, row);
cur_id.value = row.id;
cur_hash.value = row.hash;
});
</script>
......
......@@ -119,6 +119,33 @@ export const InteractionTableList = (data: any) => {
});
};
// 更新行
export const InteractionTableUpdate = (data: any) => {
return request.post('/api/voices/update-interact', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 新增行
export const InteractionTableCreate = (data: any) => {
return request.post('/api/voices/save-interact', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 删除
export const InteractionTableDelete = (data: any) => {
return request.post('/api/voices/delete-interact', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 提交生成语音任务
export const SubmitTaskInteract = (data: any) => {
return request.post('/api/voices/add-task-interact', data, {
......@@ -141,3 +168,79 @@ export const QueryInteractResponse = (data: any) => {
/**
* 互动设置 end
*/
/**
* 直播管理 LiveStream
*/
// 筛选配置项
export const LiveStreamFilterConfig = () => {
return request.get('/api/voices/live-config', {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 开始筛选
export const LiveStreamFilter = (data: any) => {
return request.get('/api/voices/live-filter', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 表格数据
export const LiveStreamTableList = () => {
return request.get('/api/voices/live-manage', {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 获取配置项
export const getLiveStreamConfig = () => {
return request.post(
'/api/voices/get-live-config',
{},
{
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
}
);
};
// 新增
export const LiveStreamTableCreate = (data: any) => {
return request.post('/api/voices/set-live-config', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 修改
export const LiveStreamTableUpdate = (data: any) => {
return request.post('/api/voices/update-live-config', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 删除
export const LiveStreamTableDelete = (data: any) => {
return request.post('/api/voices/delete-live-config', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
/**
* 直播管理 end
*/
......@@ -121,15 +121,12 @@ export const Validationrules = (
for (let i = 0; i < rules.length; i++) {
const item = rules[i];
if (item.type == 'required' && !value && name.indexOf('size_') == -1) {
console.log(item);
// 必填项
console.log('我执行了21');
return item.message;
} else if (item.type == 'regex' && value) {
// 正则
const status = item.value.test(value);
if (!status) {
console.log('我执行了2');
return item.message;
}
}
......
......@@ -55,7 +55,7 @@ export default defineConfig(({ mode }) => {
build: {
minify: 'terser', // 混淆器,terser构建后文件体积更小
outDir: mode != 'app' ? `GPT-AI-${newDate}` : 'dist', //指定输出路径
cssCodeSplit: false, // 如果设置为false,整个项目中的所有 CSS 将被提取到一个 CSS 文件中
cssCodeSplit: true, // 如果设置为false,整个项目中的所有 CSS 将被提取到一个 CSS 文件中
terserOptions: {
compress: {
//生产环境时移除console
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment