Commit 581b5739 by haojie

1

parent 15592f93
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<RowPopup <RowPopup
:list="form.row_selected_options" :list="form.row_selected_options"
:len="SelectedRows.length" :len="SelectedRows.length"
@change="MultiSelectEvent"
></RowPopup> ></RowPopup>
</template> </template>
<template v-if="form.refresh"> <template v-if="form.refresh">
...@@ -69,13 +70,13 @@ ...@@ -69,13 +70,13 @@
</template> </template>
<div class="admin-table"> <div class="admin-table">
<CustomTable <CustomTable
:list="list"
:columns="form.table_columns" :columns="form.table_columns"
:local_key="form.local_key" :local_key="form.local_key"
:edit_page="form.edit_page" :edit_page="form.edit_page"
:checkbox="form.checkbox" :checkbox="form.checkbox"
:edit_key="form.edit_key" :edit_key="form.edit_key"
:table_api="form.table_api" :table_api="form.table_api"
:table_num="table_num"
:filter_num="filter_num" :filter_num="filter_num"
:filter_api="form.filter_api" :filter_api="form.filter_api"
:AlreadyChoose="AlreadyChoose" :AlreadyChoose="AlreadyChoose"
...@@ -89,16 +90,21 @@ ...@@ -89,16 +90,21 @@
<template #edit="{ row }"> <template #edit="{ row }">
<slot name="edit" :row="row"> </slot> <slot name="edit" :row="row"> </slot>
</template> </template>
<template #type="{ row }">
<slot name="type" :row="row"> </slot>
</template>
<template #content="{ row }"> <template #content="{ row }">
<slot name="content" :row="row"></slot> <slot name="content" :row="row"></slot>
</template> </template>
</CustomTable> </CustomTable>
</div> </div>
<slot></slot> <slot></slot>
<CustomLoading v-show="loading"></CustomLoading>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import CustomLoading from '@/components/custom/loading2.vue';
import TransitionView from './TransitionView.vue'; import TransitionView from './TransitionView.vue';
import RowPopup from './RowPopup.vue'; import RowPopup from './RowPopup.vue';
import CustomButtom from './button.vue'; import CustomButtom from './button.vue';
...@@ -111,6 +117,8 @@ import { getFilterParams } from '@/constants/admin_form'; ...@@ -111,6 +117,8 @@ import { getFilterParams } from '@/constants/admin_form';
import CustomTable from './table.vue'; import CustomTable from './table.vue';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { DataType } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool';
const props = defineProps<{ const props = defineProps<{
form: any; form: any;
list: any[]; list: any[];
...@@ -120,6 +128,9 @@ const store = useStore(); ...@@ -120,6 +128,9 @@ const store = useStore();
const router = useRouter(); const router = useRouter();
// 筛选盒子打开状态 // 筛选盒子打开状态
const filterBoxStatus = ref(false); const filterBoxStatus = ref(false);
const loading = ref(false);
// 通知表格重新请求数据
const table_num = ref(1);
// //
const filter_num = ref(1); const filter_num = ref(1);
const defaultWidth = ref(); const defaultWidth = ref();
...@@ -183,6 +194,40 @@ const onCreate = () => { ...@@ -183,6 +194,40 @@ const onCreate = () => {
onMounted(() => { onMounted(() => {
defaultWidth.value = adminFilter.value.offsetWidth; defaultWidth.value = adminFilter.value.offsetWidth;
}); });
// 过滤出表格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 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,
});
loading.value = false;
if (stauts) {
// 更新表格数据
table_num.value += 1;
}
}
};
</script> </script>
<style lang="less"> <style lang="less">
...@@ -191,6 +236,7 @@ onMounted(() => { ...@@ -191,6 +236,7 @@ onMounted(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
position: relative;
.admin-page-header { .admin-page-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
......
<template> <template>
<div class=""> <div v-for="item in list" :key="item.hash" class="edit-audio-result">
<template v-if="status === 'true'"> <template v-if="item.status">
<CustomAudio bk="#181818" :need_progress="true" :url="url"></CustomAudio> <CompleteAudio
v-model="item.is_check"
v-model:check_time="item.check_time"
bk="#181818"
:need_progress="true"
:url="item.audio"
:content="item.content"
:checkbox="true"
></CompleteAudio>
</template> </template>
<template v-else-if="status === 'false'"> <template v-else>
<!-- loading --> <!-- loading -->
<div class="voice-loading"> <div class="voice-loading">
<DotLoop> 语音正在生成中,请耐心等待 </DotLoop> <DotLoop> 语音正在生成中,请耐心等待 </DotLoop>
...@@ -13,28 +21,55 @@ ...@@ -13,28 +21,55 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import CustomAudio from './audio.vue'; import { ref, watch } from 'vue';
import CompleteAudio from './CompleteAudio.vue';
import DotLoop from './DotLoop.vue'; import DotLoop from './DotLoop.vue';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
status: string; list: any[];
url?: any[];
}>(), }>(),
{ {}
url: () => [],
}
); );
// 修改item——check状态
const ChangeList = (list: any[]) => {
// 找到最大的时间戳
let max_time = 0;
list.forEach((item: any) => {
if (item.check_time && item.check_time > max_time && item.is_check) {
max_time = item.check_time;
}
});
const index = list.findIndex((item: any) => item.check_time === max_time);
if (index !== -1) {
// 将其他 is_check 修改为false
list.forEach((item: any, id: number) => {
if (index !== id) {
item.is_check = false;
}
});
}
};
// 当前选择的语音
const CurrentVoice = ref('');
watch(props.list, (v) => {
ChangeList(v);
});
</script> </script>
<style lang="less"> <style lang="less">
.voice-loading { .voice-loading {
background: #181818; background: #181818;
border-radius: 42px; border-radius: 8px;
font-weight: 400; font-weight: 400;
font-size: 13px; font-size: 13px;
height: 54px; height: 103px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.edit-audio-result:not(:first-child) {
margin-top: 12px;
}
</style> </style>
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
</template> </template>
</CustomButton> </CustomButton>
</template> </template>
<template v-if="form.delete"> <template v-if="form.delete_api">
<CustomButton class="body-head-btn" <CustomButton class="body-head-btn" @click="onDelete"
>删除 >删除
<template #icon> <template #icon>
<DeleteSvg></DeleteSvg> <DeleteSvg></DeleteSvg>
...@@ -122,7 +122,7 @@ ...@@ -122,7 +122,7 @@
</template> </template>
<template v-if="form.conversion"> <template v-if="form.conversion">
<div class="conversion-box"> <div class="conversion-box">
<CustomButton class="edit-conversion-btn" <CustomButton class="edit-conversion-btn" @click="StartConvert"
>转换为语音 >转换为语音
<template #icon> <template #icon>
<span class="conversion-icon"> <span class="conversion-icon">
...@@ -131,12 +131,7 @@ ...@@ -131,12 +131,7 @@
</template> </template>
</CustomButton> </CustomButton>
</div> </div>
</template> <GenerateVoice :list="form.conversion.list"></GenerateVoice>
<template v-if="form.audio">
<GenerateVoice
:status="form.audio.status"
:url="form.audio.url"
></GenerateVoice>
</template> </template>
<template v-if="form.start_broadcast"> <template v-if="form.start_broadcast">
<StartBroadcast :status="'not_on_air'"></StartBroadcast> <StartBroadcast :status="'not_on_air'"></StartBroadcast>
...@@ -161,14 +156,24 @@ ...@@ -161,14 +156,24 @@
<template v-if="form.reset"> <template v-if="form.reset">
<CustomButton class="edit-footer-btn reset">重置</CustomButton> <CustomButton class="edit-footer-btn reset">重置</CustomButton>
</template> </template>
<template v-if="form.submit"> <template v-if="form.submit_api">
<CustomButton class="edit-footer-btn submit">提交</CustomButton> <CustomButton class="edit-footer-btn submit" @click="onSubmit"
>提交</CustomButton
>
</template> </template>
</div> </div>
<CustomLoading v-show="loading"></CustomLoading>
<ConfirmDialog
v-model="dialog_visible"
:label="'删除'"
@confirm="deleteConfirm"
></ConfirmDialog>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import ConfirmDialog from './ConfirmDialog.vue';
import CustomLoading from '@/components/custom/loading2.vue';
import GenerateVoice from './GenerateVoice.vue'; import GenerateVoice from './GenerateVoice.vue';
import CustomButton from './button.vue'; import CustomButton from './button.vue';
import CustomTextarea from './Textarea.vue'; import CustomTextarea from './Textarea.vue';
...@@ -185,11 +190,15 @@ import DiscourseBindSvg from '@/assets/svg/form/discourseBind.svg'; ...@@ -185,11 +190,15 @@ import DiscourseBindSvg from '@/assets/svg/form/discourseBind.svg';
import ManualResponseSvg from '@/assets/svg/form/ManualResponse.svg'; import ManualResponseSvg from '@/assets/svg/form/ManualResponse.svg';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
import { getFormParams } from '@/constants/admin_form';
import { ref } from 'vue'; import { ref } from 'vue';
const props = defineProps<{ const props = defineProps<{
form: any; form: any;
}>(); }>();
const router = useRouter(); const router = useRouter();
const loading = ref(false);
// 弹窗状态
const dialog_visible = ref(false);
const backTable = () => { const backTable = () => {
const { back_url } = props.form; const { back_url } = props.form;
...@@ -215,6 +224,55 @@ const onSend = () => { ...@@ -215,6 +224,55 @@ const onSend = () => {
const SelectChange = (value: string, fun: any) => { const SelectChange = (value: string, fun: any) => {
fun(value); fun(value);
}; };
// 开始转换语音
const StartConvert = () => {
const { form } = props;
// 校验表单完整性
let params = getFormParams(form.form_options);
if (!params) {
return;
}
form.conversion.method(params, form.page_name);
};
// 提交接口
const onSubmit = async () => {
const { form } = props;
loading.value = true;
await form.submit_api();
loading.value = false;
};
// 弹窗确认事件
const deleteConfirm = () => {
realDelete();
};
//
const realDelete = async () => {
const { form } = props;
loading.value = true;
// 获取当前id
await form.delete_api(
{
ids: form.get_id(),
},
form.back_url
);
loading.value = false;
};
// 删除单个
const onDelete = async () => {
const { form } = props;
if (form.delete_confirm) {
// 打开确认弹窗
dialog_visible.value = true;
} else {
realDelete();
}
};
</script> </script>
<style lang="less"> <style lang="less">
...@@ -223,6 +281,7 @@ const SelectChange = (value: string, fun: any) => { ...@@ -223,6 +281,7 @@ const SelectChange = (value: string, fun: any) => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
position: relative;
.custom-admin-page-edit { .custom-admin-page-edit {
flex: 1; flex: 1;
padding: 20px 30px 30px 30px; padding: 20px 30px 30px 30px;
...@@ -283,10 +342,11 @@ const SelectChange = (value: string, fun: any) => { ...@@ -283,10 +342,11 @@ const SelectChange = (value: string, fun: any) => {
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 0 30px; padding: 0 30px 20px 30px;
box-sizing: border-box; box-sizing: border-box;
.edit-form-content { .edit-form-content {
width: 800px; width: 100%;
max-width: 800px;
.edit-form-item-label { .edit-form-item-label {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -368,6 +428,7 @@ const SelectChange = (value: string, fun: any) => { ...@@ -368,6 +428,7 @@ const SelectChange = (value: string, fun: any) => {
} }
.admin-edit-footer { .admin-edit-footer {
height: 60px; height: 60px;
min-height: 60px;
background: #2d2d2d; background: #2d2d2d;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
......
...@@ -80,7 +80,7 @@ const RowClick = (item: any) => { ...@@ -80,7 +80,7 @@ const RowClick = (item: any) => {
// 点击了确认 // 点击了确认
const DialogConfirm = () => { const DialogConfirm = () => {
console.log(current_params.value); emit('change', current_params.value);
}; };
</script> </script>
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
}" }"
></TTextarea> ></TTextarea>
<div class="position-text"> <div class="position-text">
<template v-if="maxlength">
<span> {{ textareaLength }}/{{ maxlength }}</span> <span> {{ textareaLength }}/{{ maxlength }}</span>
</template>
<span class="reset-btn" @click="reset">清空</span> <span class="reset-btn" @click="reset">清空</span>
</div> </div>
<template v-if="disabled"> <template v-if="disabled">
...@@ -39,7 +41,6 @@ const props = withDefaults( ...@@ -39,7 +41,6 @@ const props = withDefaults(
placeholder: '请输入', placeholder: '请输入',
maxRows: 5, maxRows: 5,
minRows: 5, minRows: 5,
maxlength: 500,
disabled: false, disabled: false,
} }
); );
...@@ -47,7 +48,7 @@ const emit = defineEmits(['update:modelValue']); ...@@ -47,7 +48,7 @@ const emit = defineEmits(['update:modelValue']);
const imgs = { const imgs = {
disabled: new URL('../../assets/svg/form/disabled.svg', import.meta.url).href, disabled: new URL('../../assets/svg/form/disabled.svg', import.meta.url).href,
}; };
const textarea_value = ref(''); const textarea_value = ref(props.modelValue);
const reset = () => { const reset = () => {
textarea_value.value = ''; textarea_value.value = '';
}; };
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onBeforeMount, onBeforeUnmount, computed } from 'vue'; import { ref, onBeforeMount, onBeforeUnmount, computed, watch } from 'vue';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
...@@ -58,6 +58,7 @@ const props = withDefaults( ...@@ -58,6 +58,7 @@ const props = withDefaults(
bk: 'transparent', bk: 'transparent',
} }
); );
const imgs = { const imgs = {
start: new URL('../../assets/svg/admin/audioStart.svg', import.meta.url).href, start: new URL('../../assets/svg/admin/audioStart.svg', import.meta.url).href,
stop: new URL('../../assets/svg/admin/audioStop.svg', import.meta.url).href, stop: new URL('../../assets/svg/admin/audioStop.svg', import.meta.url).href,
...@@ -103,6 +104,12 @@ const timeInterval = ref(); // 获取音频播放进度定时器 ...@@ -103,6 +104,12 @@ const timeInterval = ref(); // 获取音频播放进度定时器
// 当前播放的音频下标 // 当前播放的音频下标
const audio_index = ref(0); const audio_index = ref(0);
watch(props.url, (v) => {
// 重新初始化音频
audio_index.value = 0;
audioCurrent.value = 0;
onPause();
});
// 当前播放的音频链接 // 当前播放的音频链接
const CurrentUrl = computed(() => { const CurrentUrl = computed(() => {
return function () { return function () {
......
...@@ -8,25 +8,37 @@ ...@@ -8,25 +8,37 @@
:loading="loading" :loading="loading"
> >
<template #check_all> <template #check_all>
<template v-if="checkbox">
<TCheckbox <TCheckbox
class="check-all-box" class="check-all-box"
v-model="is_check_all" v-model="is_check_all"
@change="CheckAll" @change="CheckAll"
></TCheckbox> ></TCheckbox>
</template> </template>
</template>
<template #checkbox="{ row }"> <template #checkbox="{ row }">
<template v-if="checkbox">
<TCheckbox <TCheckbox
v-model="row.is_check" v-model="row.is_check"
class="check-all-box" class="check-all-box"
@change="CheckOne(row)" @change="CheckOne(row)"
></TCheckbox> ></TCheckbox>
</template> </template>
</template>
<template #audio="{ row }"> <template #audio="{ row }">
<slot name="audio" :row="row"></slot> <slot name="audio" :row="row"></slot>
</template> </template>
<template #content="{ row }"> <template #content="{ row }">
<slot name="content" :row="row"></slot> <slot name="content" :row="row"></slot>
</template> </template>
<template #language="{ row }">
{{ language_type[row.language] }}
</template>
<template #type="{ row }">
<slot name="type" :row="row">
{{ row.type }}
</slot>
</template>
<template #edit="{ row }"> <template #edit="{ row }">
<slot name="edit" :row="row"> <slot name="edit" :row="row">
<span class="edit-text" @click="onEdit(row)">编辑</span> <span class="edit-text" @click="onEdit(row)">编辑</span>
...@@ -52,7 +64,7 @@ import { onBeforeMount, reactive, ref, watch } from 'vue'; ...@@ -52,7 +64,7 @@ import { onBeforeMount, reactive, ref, watch } from 'vue';
import { Pagination as TPagination } from 'tdesign-vue-next'; import { Pagination as TPagination } from 'tdesign-vue-next';
// import { TASKTYPE } from '@/utils/api/Task'; // import { TASKTYPE } from '@/utils/api/Task';
import { getLocalData, setLocalData } from '@/utils/tool'; import { getLocalData, setLocalData } from '@/utils/tool';
import { EditButtonEvent } from '@/constants/admin_form'; import { EditButtonEvent, language_type } from '@/constants/admin_form';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
...@@ -65,6 +77,7 @@ const props = withDefaults( ...@@ -65,6 +77,7 @@ const props = withDefaults(
filter_num?: number; filter_num?: number;
filter_api?: any; filter_api?: any;
AlreadyChoose?: any; AlreadyChoose?: any;
table_num?: number;
}>(), }>(),
{ {
checkbox: true, checkbox: true,
...@@ -72,6 +85,7 @@ const props = withDefaults( ...@@ -72,6 +85,7 @@ const props = withDefaults(
filter_num: 1, filter_num: 1,
filter_api: false, filter_api: false,
AlreadyChoose: {}, AlreadyChoose: {},
table_num: 1,
} }
); );
const emit = defineEmits(['ChangeList', 'ChoseList', 'PageNumChange']); const emit = defineEmits(['ChangeList', 'ChoseList', 'PageNumChange']);
...@@ -147,11 +161,13 @@ const CheckOne = (row: any) => { ...@@ -147,11 +161,13 @@ const CheckOne = (row: any) => {
// 添加表格多选框和状态 // 添加表格多选框和状态
const setTableCheckBox = (res: any) => { const setTableCheckBox = (res: any) => {
if (props.checkbox) {
// 增加一个选中状态 // 增加一个选中状态
res.list.forEach((item: any, index: number) => { res.list.forEach((item: any, index: number) => {
item.is_check = false; item.is_check = false;
item.index = index; item.index = index;
}); });
}
return res; return res;
}; };
...@@ -183,6 +199,13 @@ watch( ...@@ -183,6 +199,13 @@ watch(
StartFilter(); StartFilter();
} }
); );
watch(
() => props.table_num,
(v) => {
ChangeCurrentPage(1);
getLog();
}
);
// 打开编辑页面 // 打开编辑页面
const onEdit = (row: any) => { const onEdit = (row: any) => {
...@@ -195,9 +218,7 @@ const getLog = async () => { ...@@ -195,9 +218,7 @@ const getLog = async () => {
try { try {
loading.value = true; loading.value = true;
let res: any = await props.table_api(); let res: any = await props.table_api();
if (props.checkbox) {
res = await setTableCheckBox(res); res = await setTableCheckBox(res);
}
tableList.list = res.list; tableList.list = res.list;
total.value = res.total; total.value = res.total;
loading.value = false; loading.value = false;
......
import { getLocalData, setLocalData } from '@/utils/tool'; import { getLocalData, setLocalData } from '@/utils/tool';
import router from '@/router'; import router from '@/router';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
import { Validationrules } from '@/utils/tool';
// 语言列表 import { DeleteVioce } from '@/utils/api/ai';
// 语音列表
export const voice_list = [ export const voice_list = [
{ {
label: '柜姐', label: '柜姐',
value: 'guijie', value: 'guijie',
// 试听
audio: {
cn: 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/74843270679d44e0a6a5692e972a16a0_0.mp3',
en: '',
},
}, },
{ {
label: '小仙', label: '小仙',
value: 'xiaoxian', value: 'xiaoxian',
audio: {
cn: 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/39c3b915dbbc4989aeda4a259a8fd477_0.mp3',
en: '',
},
}, },
{ {
label: '艾飞', label: '艾飞',
value: 'aifei', value: 'aifei',
audio: {
cn: 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/6efdfd4a9356462993fbe53ee2c30588_0.mp3',
en: '',
},
}, },
{ {
label: '老铁', label: '老铁',
value: 'laotie', value: 'laotie',
audio: {
cn: 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/09adc64844044bf2afdc1861b4c73dad_0.mp3',
en: '',
},
}, },
{ {
label: '老妹', label: '老妹',
value: 'laomei', value: 'laomei',
audio: {
cn: 'https://yunyi-tiktok.oss-cn-shenzhen.aliyuncs.com/da1829e4089b40d9b50faa2b973a7c15_0.mp3',
en: '',
},
},
];
// 语言列表
export const language_list = [
{
label: '中文',
value: 'cn',
},
{
label: '英文',
value: 'en',
}, },
]; ];
// 语言类型
export const language_type = {
cn: '中文',
en: '英文',
};
// 互动类型
export const interaction_type = {
'0': '直播互动',
'1': '自动回复',
};
// 任务类型
export const admin_task_type = {
dialogues: 'dialogues', // 话术管理
interaction: 'interaction', // 互动设置
};
// 获取form表单的值
export const getFormParams = (list: any[]) => {
const params: any = {};
// 遍历整个列表
for (let i = 0; i < list.length; i++) {
const item: any = list[i];
for (let j = 0; j < item.lists.length; j++) {
const it = item.lists[j];
// 校验规则
const message = Validationrules(it.rules, it.value, it.name);
if (message) {
// 提示错误信息
show_message(message);
return false;
} else {
if (it.name == 'number') {
// 转换为number类型
params[it.name] = parseFloat(it.value + '');
} else {
// 添加params
params[it.name] = it.value;
}
}
}
}
return params;
};
// 清空admin-form的value值 // 清空admin-form的value值
export const ResetForm = (list: any[]) => { export const ResetForm = (list: any[]) => {
list.forEach((item: any) => { list.forEach((item: any) => {
...@@ -80,16 +160,13 @@ export const EditFillData = (form: any[], row: any) => { ...@@ -80,16 +160,13 @@ export const EditFillData = (form: any[], row: any) => {
item.lists.forEach((it: any) => { item.lists.forEach((it: any) => {
// 查找name相同的字段 // 查找name相同的字段
Object.keys(row).forEach((key: string) => { Object.keys(row).forEach((key: string) => {
// console.log(value);
if (it.name == key) { if (it.name == key) {
console.log(it.name);
// 填充数据 // 填充数据
it.value = row[key] + ''; it.value = row[key] + '';
} }
}); });
}); });
}); });
console.log(form);
}; };
// 筛选配置填充 // 筛选配置填充
...@@ -116,3 +193,24 @@ export const FilterConfigFill = (resData: any, form: any[]) => { ...@@ -116,3 +193,24 @@ export const FilterConfigFill = (resData: any, form: any[]) => {
}); });
}); });
}; };
// 话术管理删除
export const DiscourseManagementDelete = async (
data: any,
path: string = ''
) => {
try {
const res: any = await DeleteVioce(data);
if (res.code == 0) {
show_message('删除成功', 'success');
if (path) {
router.replace({
path: path,
});
}
return true;
}
} catch (e) {
console.log(e);
}
};
import {
DiscourseManagementConvertTask,
ConvertTaskResponse,
SubmitTaskInteract,
QueryInteractResponse,
} from '@/utils/api/ai';
import { show_message } from '@/utils/tdesign_tool';
import { onBeforeUnmount, reactive, ref } from 'vue';
import { admin_task_type } from '@/constants/admin_form';
export default function () {
let Interval: any = null;
const status = ref(true);
// 已返回的语音列表
const CurrentVoice = reactive({
list: [] as any[],
});
// 轮询获取语音转换返回值
const getVoiceResponse = async (
hash: string,
content: string,
name: string
) => {
try {
let res: any = null;
if (name === admin_task_type.dialogues) {
// 话术管理
res = await ConvertTaskResponse({
hash: hash,
});
} else if (name === admin_task_type.interaction) {
// 互动设置
res = await QueryInteractResponse({
hash: hash,
});
}
if (res.code == 0 && res.data && res.data.audio) {
// 找到列表中对应的hash
CurrentVoice.list.forEach((item: any) => {
if (item.hash === hash) {
item.status = true;
item.audio =
typeof res.data.audio === 'string'
? JSON.parse(res.data.audio)
: res.data.audio;
item.content = content;
}
});
console.log(CurrentVoice.list);
// 关闭定时器
closeInterval();
status.value = true;
}
} catch (e) {
console.log(e);
}
};
// 打开定时器
const openInterval = (hash: string, content: string, name: string) => {
Interval = window.setInterval(() => {
getVoiceResponse(hash, content, name);
}, 3000);
};
// 关闭定时器
const closeInterval = () => {
if (Interval) {
window.clearInterval(Interval);
Interval = null;
}
};
// 提交语音转换任务
const SubmitConvertTask = async (data: any, name: string) => {
try {
if (!status.value) {
// 上个任务未完成
show_message('请等待上个任务完成');
return;
}
status.value = false;
let res: any = null;
if (name === admin_task_type.dialogues) {
// 话术管理
res = await DiscourseManagementConvertTask(data);
} else if (name === admin_task_type.interaction) {
// 互动设置
res = await SubmitTaskInteract(data);
}
//
if (res.code == 0 && res.data.hash) {
CurrentVoice.list.unshift({
hash: res.data.hash,
status: false,
audio: [],
content: '',
// 是否选中
is_check: false,
// 选中时间
check_time: 0,
});
// 开始定时任务
openInterval(res.data.hash, data.content, name);
} else {
console.log('报错了');
console.log(res);
status.value = true;
}
} catch (e) {
status.value = true;
console.log(e);
}
};
onBeforeUnmount(() => {
closeInterval();
});
return {
CurrentVoice,
SubmitConvertTask,
};
}
...@@ -20,7 +20,12 @@ import CustomAudio from '@/components/Admin/audio.vue'; ...@@ -20,7 +20,12 @@ import CustomAudio from '@/components/Admin/audio.vue';
import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue'; import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { onBeforeMount, reactive, ref } from 'vue'; import { onBeforeMount, reactive, ref } from 'vue';
import { isDevContext } from '@/utils/tool'; import { isDevContext } from '@/utils/tool';
import { FilterConfigFill, ResetForm } from '@/constants/admin_form'; import {
FilterConfigFill,
ResetForm,
DiscourseManagementDelete,
language_list,
} from '@/constants/admin_form';
import { discourse_management_edit } from '@/constants/token'; import { discourse_management_edit } from '@/constants/token';
import { import {
DiscourseManagementConfig, DiscourseManagementConfig,
...@@ -92,6 +97,7 @@ const onFilter = async (params: any) => { ...@@ -92,6 +97,7 @@ const onFilter = async (params: any) => {
console.log(e); console.log(e);
} }
}; };
// 表单配置项 // 表单配置项
const ManagementForm = reactive({ const ManagementForm = reactive({
title: '话术列表', title: '话术列表',
...@@ -112,6 +118,8 @@ const ManagementForm = reactive({ ...@@ -112,6 +118,8 @@ const ManagementForm = reactive({
table_api: getTableList, table_api: getTableList,
// 能否多选--默认为true // 能否多选--默认为true
checkbox: true, checkbox: true,
// 删除api
delete_api: DiscourseManagementDelete,
// 编辑页面 // 编辑页面
edit_page: '/AILiveStreaming/DiscourseManagement/edit', edit_page: '/AILiveStreaming/DiscourseManagement/edit',
// 编辑页面的key--存储行数据 // 编辑页面的key--存储行数据
...@@ -131,6 +139,7 @@ const ManagementForm = reactive({ ...@@ -131,6 +139,7 @@ const ManagementForm = reactive({
{ {
title: 'check_all', title: 'check_all',
colKey: 'checkbox', colKey: 'checkbox',
width: '80px',
}, },
{ {
title: 'ID', title: 'ID',
...@@ -195,16 +204,7 @@ const ManagementForm = reactive({ ...@@ -195,16 +204,7 @@ const ManagementForm = reactive({
label: '语言', label: '语言',
placeholder: '语言', placeholder: '语言',
value: '', value: '',
options: [ options: language_list,
{
label: '中文',
value: 'cn',
},
{
label: '英文',
value: 'en',
},
],
}, },
], ],
}); });
......
...@@ -4,17 +4,52 @@ ...@@ -4,17 +4,52 @@
<script lang="ts" setup> <script lang="ts" setup>
import PageEdit from '@/components/Admin/PageEdit.vue'; import PageEdit from '@/components/Admin/PageEdit.vue';
import { reactive } from 'vue'; import { onMounted, reactive } from 'vue';
import { getLocalData, isDevContext } from '@/utils/tool'; import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
import { voice_list } from '@/constants/admin_form'; import { voice_list, admin_task_type } from '@/constants/admin_form';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import ConvertVoice from '@/hooks/ConvertVoice';
const { CurrentVoice, SubmitConvertTask } = ConvertVoice();
import { AddNewPhrase } from '@/utils/api/ai';
const router = useRouter(); const router = useRouter();
const imgs = { const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href, 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 SubmitCreateEvent = async () => {
// 先过滤出选中的hash
const hash = getHash();
if (!hash) {
show_message('必须选择一条语音');
return;
}
try {
const res: any = await AddNewPhrase({
hash: hash,
});
if (res.code == 0) {
show_message('添加成功', 'success');
router.replace({
path: ManagementForm.back_url,
});
}
} catch (e) {
console.log(e);
}
};
// 新增组件--所有value为空 // 新增组件--所有value为空
const ManagementForm = reactive({ const ManagementForm = reactive({
page_name: admin_task_type.dialogues, // 话术管理
title: '话术管理', title: '话术管理',
title_2: '新增', title_2: '新增',
body_title: '新增', body_title: '新增',
...@@ -25,17 +60,43 @@ const ManagementForm = reactive({ ...@@ -25,17 +60,43 @@ const ManagementForm = reactive({
delete: false, delete: false,
// 删除api // 删除api
// delete_api: isDevContext() ? '' : '', // delete_api: isDevContext() ? '' : '',
// 能否提交
submit: true,
// 提交接口 // 提交接口
submit_api: isDevContext() ? '' : '', submit_api: SubmitCreateEvent,
//能否重置 //能否重置
reset: true, reset: true,
// 是否转换为语音 // 是否转换为语音 -- 自定义方法
conversion: { conversion: {
api: '', list: CurrentVoice.list,
options: [], // 测试list
value: '', // 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,
}, },
// 播放音频 // 播放音频
play_audio: true, play_audio: true,
...@@ -51,12 +112,24 @@ const ManagementForm = reactive({ ...@@ -51,12 +112,24 @@ const ManagementForm = reactive({
value: '', value: '',
// 是否禁用 // 是否禁用
disabled: false, disabled: false,
rules: [
{
type: 'required',
message: '标题必填',
},
],
}, },
{ {
type: 'text', type: 'text',
label: '产品', label: '产品',
name: 'product', name: 'product',
value: '', value: '',
rules: [
{
type: 'required',
message: '产品必填',
},
],
}, },
], ],
}, },
...@@ -82,6 +155,12 @@ const ManagementForm = reactive({ ...@@ -82,6 +155,12 @@ const ManagementForm = reactive({
value: 'en', value: 'en',
}, },
], ],
rules: [
{
type: 'required',
message: '语言必选',
},
],
}, },
{ {
type: 'select', type: 'select',
...@@ -91,14 +170,25 @@ const ManagementForm = reactive({ ...@@ -91,14 +170,25 @@ const ManagementForm = reactive({
value: '', value: '',
align: 'left', align: 'left',
options: voice_list, options: voice_list,
rules: [
{
type: 'required',
message: '语音必选',
},
],
}, },
{ {
type: 'textarea', type: 'textarea',
label: '语音内容', label: '语音内容',
name: 'product_1', name: 'content',
placeholder: '请输入语音内容', placeholder: '请输入语音内容',
value: '', value: '',
maxlength: 1000, rules: [
{
type: 'required',
message: '语音内容必填',
},
],
}, },
], ],
}, },
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import PageEdit from '@/components/Admin/PageEdit.vue'; import PageEdit from '@/components/Admin/PageEdit.vue';
import { onBeforeMount, reactive } from 'vue'; import { onBeforeMount, reactive, ref } from 'vue';
import { discourse_management_edit } from '@/constants/token'; import { discourse_management_edit } from '@/constants/token';
import { getLocalData, isDevContext } from '@/utils/tool'; import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
...@@ -13,30 +13,108 @@ import { ...@@ -13,30 +13,108 @@ import {
getEditLocalData, getEditLocalData,
EditFillData, EditFillData,
voice_list, voice_list,
DiscourseManagementDelete,
admin_task_type,
} from '@/constants/admin_form'; } from '@/constants/admin_form';
import { EditVioce } from '@/utils/api/ai';
import ConvertVoice from '@/hooks/ConvertVoice';
const { CurrentVoice, SubmitConvertTask } = ConvertVoice();
const router = useRouter(); const router = useRouter();
const old_hash = ref('');
const cur_id = ref();
const imgs = { const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href, 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 SubmitCreateEvent = async () => {
// 先过滤出选中的hash
const hash = getHash();
if (!hash || !old_hash.value) {
show_message('必须选择一条语音');
return;
}
try {
const res: any = await EditVioce({
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);
}
};
// 获取id
const getRowid = () => {
return cur_id.value + '';
};
// 编辑页面组件 // 编辑页面组件
const ManagementForm = reactive({ const ManagementForm = reactive({
page_name: admin_task_type.dialogues, // 话术管理
title: '话术管理', title: '话术管理',
title_2: '编辑', title_2: '编辑',
body_title: '编辑', body_title: '编辑',
// 是否显示返回列表页 // 是否显示返回列表页
back: true, back: true,
back_url: '/AILiveStreaming/DiscourseManagement', back_url: '/AILiveStreaming/DiscourseManagement',
// 能否删除,
delete: true,
// 删除api // 删除api
delete_api: isDevContext() ? '' : '', delete_api: DiscourseManagementDelete,
// 能否提交 // 删除前是否确认
submit: true, delete_confirm: true,
submit_api: isDevContext() ? '' : '', // 提交方法
submit_api: SubmitCreateEvent,
// 获取当前id
get_id: getRowid,
//能否重置 //能否重置
reset: true, reset: true,
// 是否转换为语音 // 是否转换为语音
conversion: true, // 是否转换为语音 -- 自定义方法
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,
},
// 播放音频 // 播放音频
audio: { audio: {
url: [], url: [],
...@@ -56,18 +134,31 @@ const ManagementForm = reactive({ ...@@ -56,18 +134,31 @@ const ManagementForm = reactive({
placeholder: '', placeholder: '',
// 是否禁用 // 是否禁用
disabled: true, disabled: true,
rules: [],
}, },
{ {
type: 'text', type: 'text',
label: '标题', label: '标题',
name: 'title_1', name: 'title',
value: '奥克斯小风扇话术', value: '',
rules: [
{
type: 'required',
message: '标题必填',
},
],
}, },
{ {
type: 'text', type: 'text',
label: '产品', label: '产品',
name: 'product_1', name: 'product',
value: '电风扇', value: '',
rules: [
{
type: 'required',
message: '产品必填',
},
],
}, },
], ],
}, },
...@@ -93,6 +184,12 @@ const ManagementForm = reactive({ ...@@ -93,6 +184,12 @@ const ManagementForm = reactive({
value: 'en', value: 'en',
}, },
], ],
rules: [
{
type: 'required',
message: '语言必选',
},
],
}, },
{ {
type: 'select', type: 'select',
...@@ -102,13 +199,25 @@ const ManagementForm = reactive({ ...@@ -102,13 +199,25 @@ const ManagementForm = reactive({
value: '', value: '',
align: 'left', align: 'left',
options: voice_list, options: voice_list,
rules: [
{
type: 'required',
message: '语音必选',
},
],
}, },
{ {
type: 'textarea', type: 'textarea',
label: '语音内容', label: '语音内容',
name: 'product_1', name: 'content',
placeholder: '请输入语音内容', placeholder: '请输入语音内容',
value: '', value: '',
rules: [
{
type: 'required',
message: '语音内容必填',
},
],
}, },
], ],
}, },
...@@ -120,8 +229,20 @@ onBeforeMount(() => { ...@@ -120,8 +229,20 @@ onBeforeMount(() => {
discourse_management_edit, discourse_management_edit,
ManagementForm.back_url ManagementForm.back_url
); );
// 填充数据 // 公共数据填充
EditFillData(ManagementForm.form_options, row); EditFillData(ManagementForm.form_options, row);
// 填充原有的语音列表
ManagementForm.conversion.list.push({
hash: row.hash,
status: true,
audio: row.audio,
content: row.content,
is_check: false,
check_time: 0,
});
// 获取old_hash
old_hash.value = row.hash;
cur_id.value = row.id;
}); });
</script> </script>
......
...@@ -4,18 +4,63 @@ ...@@ -4,18 +4,63 @@
v-model:list="ManagementForm.table_list" v-model:list="ManagementForm.table_list"
@reset="ResetFilter" @reset="ResetFilter"
> >
<template #title> <template #type="{ row }">
<div>111</div> <span>{{ interaction_type[row.type] }}</span>
</template> </template>
</AdminPublicPageVue> </AdminPublicPageVue>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue'; import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { reactive } from 'vue'; import { reactive, onBeforeMount, ref } from 'vue';
import { isDevContext } from '@/utils/tool'; import { isDevContext } from '@/utils/tool';
import { ResetForm } from '@/constants/admin_form'; import {
ResetForm,
FilterConfigFill,
language_list,
interaction_type,
} from '@/constants/admin_form';
import { interactive_setting_edit } from '@/constants/token'; import { interactive_setting_edit } from '@/constants/token';
import {
InteractionFilterConfig,
InteractionTableList,
InteractionFilter,
} from '@/utils/api/ai';
const pageNum = ref(1);
const pageSize = ref(10);
// 获取表格数据
const getTableList = async () => {
try {
const res: any = await InteractionTableList({
page: pageNum.value,
limit: pageSize.value,
});
const list = res.data.data;
return {
list: list,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 开始筛选
const onFilter = async (params: any) => {
try {
const res: any = await InteractionFilter({
page: pageNum.value,
limit: pageSize.value,
...params,
});
return {
list: res.data.data,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 表单配置项 // 表单配置项
const ManagementForm = reactive({ const ManagementForm = reactive({
title: '互动设置', title: '互动设置',
...@@ -25,7 +70,7 @@ const ManagementForm = reactive({ ...@@ -25,7 +70,7 @@ const ManagementForm = reactive({
// 能否筛选 // 能否筛选
filter: true, filter: true,
// 筛选接口 // 筛选接口
filter_api: isDevContext() ? '' : '', filter_api: onFilter,
// 能否新增 // 能否新增
add: true, add: true,
// 表格key--用来缓存表格分页 // 表格key--用来缓存表格分页
...@@ -33,9 +78,7 @@ const ManagementForm = reactive({ ...@@ -33,9 +78,7 @@ const ManagementForm = reactive({
// 表格数据 // 表格数据
table_list: [], table_list: [],
// 表格接口 // 表格接口
table_api: isDevContext() ? '' : '', table_api: getTableList,
// api类型
table_api_type: 'get',
// 能否多选--默认为true // 能否多选--默认为true
checkbox: true, checkbox: true,
// 编辑页面 // 编辑页面
...@@ -86,52 +129,36 @@ const ManagementForm = reactive({ ...@@ -86,52 +129,36 @@ const ManagementForm = reactive({
filter_option: [ filter_option: [
{ {
type: 'select', type: 'select',
name: 'select_title', name: 'title',
label: '标题', label: '标题',
placeholder: '请选择标题', placeholder: '请选择标题',
value: '', value: '',
options: [ // 能否输入
{ filterable: true,
label: '你好', options: [],
value: '你好',
},
{
label: '你好2',
value: '你好2',
},
],
}, },
{ {
type: 'select', type: 'select',
name: 'select_product', name: 'language',
label: '产品', label: '语言',
placeholder: '产品', placeholder: '请选择语言',
value: '', value: '',
options: [ options: language_list,
{
label: '你好',
value: '你好',
},
{
label: '你好2',
value: '你好2',
},
],
}, },
{ {
type: 'select', type: 'select',
name: 'select_language', name: 'type',
label: '语言', label: '类型',
placeholder: '语言', placeholder: '请选择类型',
value: '', value: '',
options: [ options: [
{ {
label: '你好', label: '直播互动',
value: '你好', value: '0',
}, },
{ {
label: '你好2', label: '自动回复',
value: '你好2', value: '1',
}, },
], ],
}, },
...@@ -143,6 +170,21 @@ const ManagementForm = reactive({ ...@@ -143,6 +170,21 @@ const ManagementForm = reactive({
const ResetFilter = () => { const ResetFilter = () => {
ResetForm(ManagementForm.filter_option); ResetForm(ManagementForm.filter_option);
}; };
// 获取筛选列表配置
const getFilterList = async () => {
try {
const res: any = await InteractionFilterConfig();
if (res.data) {
FilterConfigFill(res.data, ManagementForm.filter_option);
}
} catch (e) {
console.log(e);
}
};
onBeforeMount(() => {
getFilterList();
});
</script> </script>
<style lang="less"></style> <style lang="less"></style>
...@@ -8,12 +8,26 @@ import { reactive } from 'vue'; ...@@ -8,12 +8,26 @@ import { reactive } from 'vue';
import { getLocalData, isDevContext } from '@/utils/tool'; import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { admin_task_type } from '@/constants/admin_form';
const router = useRouter(); const router = useRouter();
const imgs = { const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href, fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
}; };
// 修改组件显示状态
const ChangeComponentsShow = (value: string) => {
ManagementForm.form_options.forEach((item: any) => {
if (item.name === value) {
item.is_hidden = false;
}
if (item.name !== value && item.is_hidden === false) {
item.is_hidden = true;
}
});
};
// 新增组件--所有value为空 // 新增组件--所有value为空
const ManagementForm = reactive({ const ManagementForm = reactive({
page_name: admin_task_type.interaction,
title: '互动设置', title: '互动设置',
title_2: '新增', title_2: '新增',
body_title: '新增', body_title: '新增',
...@@ -23,11 +37,8 @@ const ManagementForm = reactive({ ...@@ -23,11 +37,8 @@ const ManagementForm = reactive({
// 能否删除, // 能否删除,
delete: false, delete: false,
// 删除api // 删除api
// delete_api: isDevContext() ? '' : '', delete_api: '',
// 能否提交 submit_api: '1',
submit: true,
// 提交接口
submit_api: isDevContext() ? '' : '',
//能否重置 //能否重置
reset: true, reset: true,
// 是否转换为语音 // 是否转换为语音
...@@ -40,13 +51,23 @@ const ManagementForm = reactive({ ...@@ -40,13 +51,23 @@ const ManagementForm = reactive({
title: '', title: '',
lists: [ lists: [
{ {
type: 'text', type: 'select',
label: '类型', label: '类型',
name: 'title_1', name: 'select_type',
value: '', placeholder: '请选择类型',
placeholder: '请输入类型', value: 'auto',
// 是否禁用 align: 'left',
disabled: false, watch: ChangeComponentsShow,
options: [
{
label: '自动回复设置',
value: 'auto',
},
{
label: '串场互动话术设置',
value: 'crosstown',
},
],
}, },
], ],
}, },
...@@ -57,7 +78,7 @@ const ManagementForm = reactive({ ...@@ -57,7 +78,7 @@ const ManagementForm = reactive({
{ {
type: 'select', type: 'select',
label: '语言', label: '语言',
name: 'language_1', name: 'language',
placeholder: '请选择语言', placeholder: '请选择语言',
value: '', value: '',
align: 'left', align: 'left',
...@@ -93,24 +114,49 @@ const ManagementForm = reactive({ ...@@ -93,24 +114,49 @@ const ManagementForm = reactive({
}, },
], ],
}, },
// 串场互动
{ {
icon: 'crossTalk', icon: 'message',
title: '自动回复设置',
is_hidden: false,
name: 'auto',
lists: [
{
type: 'text',
label: '触发关键词',
name: 'language_20',
placeholder: '请输入',
value: '',
align: 'left',
},
{
type: 'textarea',
label: '回复内容',
name: 'product_30',
placeholder: '请输入语音内容',
value: '',
},
],
},
{
icon: 'discourseBind',
title: '串场互动话术设置', title: '串场互动话术设置',
is_hidden: true,
name: 'crosstown',
lists: [ lists: [
{ {
type: 'text', type: 'text',
label: '标题', label: '标题',
name: 'title_1', name: 'language_20',
placeholder: '请输入',
value: '', value: '',
placeholder: '请输入标题', align: 'left',
}, },
{ {
type: 'textarea', type: 'textarea',
label: '话术内容', label: '话术内容',
name: 'title_2', name: 'product_30',
value: '',
placeholder: '请输入话术内容', placeholder: '请输入话术内容',
value: '',
}, },
], ],
}, },
......
...@@ -9,7 +9,14 @@ import { interactive_setting_edit } from '@/constants/token'; ...@@ -9,7 +9,14 @@ import { interactive_setting_edit } from '@/constants/token';
import { getLocalData, isDevContext } from '@/utils/tool'; import { getLocalData, isDevContext } from '@/utils/tool';
import { show_message } from '@/utils/tdesign_tool'; import { show_message } from '@/utils/tdesign_tool';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { getEditLocalData, EditFillData } from '@/constants/admin_form'; import {
getEditLocalData,
EditFillData,
admin_task_type,
voice_list,
} from '@/constants/admin_form';
import ConvertVoice from '@/hooks/ConvertVoice';
const { CurrentVoice, SubmitConvertTask } = ConvertVoice();
const router = useRouter(); const router = useRouter();
const imgs = { const imgs = {
fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href, fill: new URL('../../../assets/svg/form/edit.svg', import.meta.url).href,
...@@ -27,25 +34,52 @@ const ChangeComponentsShow = (value: string) => { ...@@ -27,25 +34,52 @@ const ChangeComponentsShow = (value: string) => {
}; };
// 编辑页面组件 // 编辑页面组件
const ManagementForm = reactive({ const ManagementForm = reactive({
page_name: admin_task_type.interaction,
title: '互动设置', title: '互动设置',
title_2: '编辑', title_2: '编辑',
body_title: '编辑', body_title: '编辑',
// 是否显示返回列表页 // 是否显示返回列表页
back: true, back: true,
back_url: '/AILiveStreaming/InteractiveSetting', back_url: '/AILiveStreaming/InteractiveSetting',
// 能否删除,
delete: true,
// 删除api // 删除api
delete_api: isDevContext() ? '' : '', delete_api: '1',
// 能否提交 submit_api: '1',
submit: true,
submit_api: isDevContext() ? '' : '',
//能否重置 //能否重置
reset: true, reset: true,
// 是否转换为语音 // 是否转换为语音 -- 自定义方法
conversion: false, conversion: {
// 播放音频 list: CurrentVoice.list,
play_audio: false, // 测试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: [ form_options: [
{ {
icon: '', icon: '',
...@@ -54,7 +88,7 @@ const ManagementForm = reactive({ ...@@ -54,7 +88,7 @@ const ManagementForm = reactive({
{ {
type: 'select', type: 'select',
label: '类型', label: '类型',
name: 'language_1', name: 'select_type',
placeholder: '请选择类型', placeholder: '请选择类型',
value: 'auto', value: 'auto',
align: 'left', align: 'left',
...@@ -79,7 +113,7 @@ const ManagementForm = reactive({ ...@@ -79,7 +113,7 @@ const ManagementForm = reactive({
{ {
type: 'select', type: 'select',
label: '语言', label: '语言',
name: 'language_1', name: 'language',
placeholder: '请选择语言', placeholder: '请选择语言',
value: '', value: '',
align: 'left', align: 'left',
...@@ -102,16 +136,7 @@ const ManagementForm = reactive({ ...@@ -102,16 +136,7 @@ const ManagementForm = reactive({
value: '', value: '',
align: 'left', align: 'left',
audio: true, audio: true,
options: [ options: voice_list,
{
label: '小微 (直播间专属)',
value: '123',
},
{
label: '小爱 (直播间专属)',
value: '12345',
},
],
}, },
], ],
}, },
......
...@@ -4,9 +4,12 @@ import { getUserCookie } from './userApi'; ...@@ -4,9 +4,12 @@ import { getUserCookie } from './userApi';
* ai直播模块接口 * ai直播模块接口
*/ */
/**
* 话术管理模块
*/
// 话术管理配置信息 // 话术管理配置信息
export const DiscourseManagementConfig = () => { export const DiscourseManagementConfig = () => {
return request.get('/api/voices/get-user-config', { return request.get('/api/voices/voice-config', {
headers: { headers: {
authorization: `Bearer ${getUserCookie()}`, authorization: `Bearer ${getUserCookie()}`,
}, },
...@@ -15,7 +18,7 @@ export const DiscourseManagementConfig = () => { ...@@ -15,7 +18,7 @@ export const DiscourseManagementConfig = () => {
// 话术管理表格 // 话术管理表格
export const DiscourseManagementList = (data: any) => { export const DiscourseManagementList = (data: any) => {
return request.get('/api/voices/get-voice-live', { return request.get('/api/voices/voice-live', {
params: data, params: data,
headers: { headers: {
authorization: `Bearer ${getUserCookie()}`, authorization: `Bearer ${getUserCookie()}`,
...@@ -25,10 +28,116 @@ export const DiscourseManagementList = (data: any) => { ...@@ -25,10 +28,116 @@ export const DiscourseManagementList = (data: any) => {
// 话术管理筛选 // 话术管理筛选
export const DiscourseManagementFilter = (data: any) => { export const DiscourseManagementFilter = (data: any) => {
return request.get('/api/voices/get-config-filter', { return request.get('/api/voices/voice-filter', {
params: data, params: data,
headers: { headers: {
authorization: `Bearer ${getUserCookie()}`, authorization: `Bearer ${getUserCookie()}`,
}, },
}); });
}; };
// 话术管理提交语音转换任务
export const DiscourseManagementConvertTask = (data: any) => {
return request.post('/api/voices/add-task', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 语音转换任务返回值
export const ConvertTaskResponse = (data: any) => {
return request.get('/api/voices/query-voice', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 新增话术
export const AddNewPhrase = (data: any) => {
return request.post('/api/voices/save-voice', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 编辑话术
export const EditVioce = (data: any) => {
return request.post('/api/voices/update-voice', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 删除话术
export const DeleteVioce = (data: any) => {
return request.post('/api/voices/delete-voice', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
/**
* 话术管理 end
*/
/**
* 互动设置模块 Interaction
*/
// 获取筛选配置
export const InteractionFilterConfig = (data: any) => {
return request.get('/api/voices/interact-config', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 筛选
export const InteractionFilter = (data: any) => {
return request.get('/api/voices/interact-filter', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 获取表格数据
export const InteractionTableList = (data: any) => {
return request.get('/api/voices/voice-interact', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 提交生成语音任务
export const SubmitTaskInteract = (data: any) => {
return request.post('/api/voices/add-task-interact', data, {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 轮询获取语音任务返回值
export const QueryInteractResponse = (data: any) => {
return request.get('/api/voices/query-interact', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
/**
* 互动设置 end
*/
...@@ -29,7 +29,7 @@ instance.defaults.timeout = 60000; ...@@ -29,7 +29,7 @@ instance.defaults.timeout = 60000;
instance.interceptors.response.use( instance.interceptors.response.use(
(response) => { (response) => {
const { data } = response; const { data } = response;
if (data.code === 0 || data.code == 201) { if (data.code === 0 || data.code == 201 || data.code == 1) {
return data; return data;
} else { } else {
show_message(data.msg || '请求错误', 'error'); show_message(data.msg || '请求错误', 'error');
......
...@@ -237,3 +237,11 @@ export const isDevContext = () => { ...@@ -237,3 +237,11 @@ export const isDevContext = () => {
const is_dev = import.meta.env.DEV; const is_dev = import.meta.env.DEV;
return is_dev ? true : false; return is_dev ? true : false;
}; };
// 判断数据类型
export const DataType = (key: 'array' | 'string', value: any) => {
const toString = Object.prototype.toString;
if (key == 'array') {
return toString.call(value) === '[object Array]';
}
};
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