Commit 56d408ab by haojie

1

parent 40b1bb9d
<template> <template>
<div class="custom-admin-page"> <div class="custom-admin-page custom-scrollbar">
<div class="admin-page-header"> <div class="admin-page-header">
<div> <div>
<span class="page-header-title">{{ form.title }}</span> <span class="page-header-title">{{ form.title }}</span>
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
:options="item.options" :options="item.options"
:item="item" :item="item"
v-model="item.value" v-model="item.value"
:filterable="item.filterable"
:align="item.align"
></CustomSelect> ></CustomSelect>
</template> </template>
</template> </template>
...@@ -68,25 +70,28 @@ ...@@ -68,25 +70,28 @@
<div class="admin-table"> <div class="admin-table">
<CustomTable <CustomTable
:list="list" :list="list"
:api="form.table_api"
:api_type="form.table_api_type"
: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"
:filter_num="filter_num"
:filter_api="form.filter_api"
:AlreadyChoose="AlreadyChoose"
@ChangeList="ChangeList" @ChangeList="ChangeList"
@ChoseList="ChoseList" @ChoseList="ChoseList"
@PageNumChange="PageNumChange"
> >
<template #title="{ row }"> <template #audio="{ row }">
<slot name="title" :row="row"></slot> <slot name="audio" :row="row"></slot>
</template>
<template #mp3="{ row }">
<slot name="mp3" :row="row"></slot>
</template> </template>
<template #edit="{ row }"> <template #edit="{ row }">
<slot name="edit" :row="row"> </slot> <slot name="edit" :row="row"> </slot>
</template> </template>
<template #content="{ row }">
<slot name="content" :row="row"></slot>
</template>
</CustomTable> </CustomTable>
</div> </div>
<slot></slot> <slot></slot>
...@@ -110,22 +115,30 @@ const props = defineProps<{ ...@@ -110,22 +115,30 @@ const props = defineProps<{
form: any; form: any;
list: any[]; list: any[];
}>(); }>();
const emit = defineEmits(['reset', 'update:list']); const emit = defineEmits(['reset', 'update:list', 'PageNumChange']);
const store = useStore(); const store = useStore();
const router = useRouter(); const router = useRouter();
// 筛选盒子打开状态 // 筛选盒子打开状态
const filterBoxStatus = ref(false); const filterBoxStatus = ref(false);
//
const filter_num = ref(1);
const defaultWidth = ref(); const defaultWidth = ref();
const adminFilter = ref(); const adminFilter = ref();
// 选中的行 // 选中的行
const SelectedRows = ref([]); const SelectedRows = ref([]);
// 已选择的筛选的数据
const AlreadyChoose = ref({});
// 重新加载页面 // 重新加载页面
const onReload = () => { const onReload = () => {
store.commit('progress/reload'); store.commit('progress/reload');
}; };
// 清空所有筛选的值并重新请求 // 清空所有筛选的值并重新请求
const onReset = () => { const onReset = () => {
// 先清空
emit('reset'); emit('reset');
setTimeout(() => {
onFilter();
}, 0);
}; };
// 选中的行 // 选中的行
const ChoseList = (list: any[]) => { const ChoseList = (list: any[]) => {
...@@ -142,7 +155,9 @@ const onFilter = () => { ...@@ -142,7 +155,9 @@ const onFilter = () => {
const { filter_option } = props.form; const { filter_option } = props.form;
if (filter_option) { if (filter_option) {
const params = getFilterParams(filter_option); const params = getFilterParams(filter_option);
// 提交 AlreadyChoose.value = params;
// 通知table筛选
filter_num.value += 1;
} }
}; };
...@@ -151,6 +166,11 @@ const ChangeList = (list: any[]) => { ...@@ -151,6 +166,11 @@ const ChangeList = (list: any[]) => {
emit('update:list', list); emit('update:list', list);
}; };
// 分页变化
const PageNumChange = (value: number) => {
emit('PageNumChange', value);
};
// 新增 // 新增
const onCreate = () => { const onCreate = () => {
const { create_page } = props.form; const { create_page } = props.form;
......
<template>
<t-tooltip :content="content">
<div class="max-content">
{{ content }}
</div>
</t-tooltip>
</template>
<script lang="ts" setup>
import { Tooltip as TTooltip } from 'tdesign-vue-next';
const props = withDefaults(
defineProps<{
content: string;
}>(),
{}
);
</script>
<style lang="less">
.max-content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>
<template>
<div class="">
<slot></slot>
{{ CurrentText }}
</div>
</template>
<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue';
const CurrentText = ref('。');
let interval: any = null;
const openInterval = () => {
interval = window.setInterval(() => {
if (CurrentText.value.length == 3) {
CurrentText.value = '。';
} else if (CurrentText.value.length == 2) {
CurrentText.value = '。。。';
} else if (CurrentText.value.length == 1) {
CurrentText.value = '。。';
}
}, 1000);
};
// 关闭定时器
const closeInterval = () => {
if (interval) {
window.clearInterval(interval);
interval = null;
}
};
onMounted(() => {
// 开启定时器
openInterval();
});
onBeforeUnmount(() => {
closeInterval();
});
</script>
<style lang="less"></style>
<template>
<div class="">
<template v-if="status === 'true'">
<CustomAudio bk="#181818" :need_progress="true" :url="url"></CustomAudio>
</template>
<template v-else-if="status === 'false'">
<!-- loading -->
<div class="voice-loading">
<DotLoop> 语音正在生成中,请耐心等待 </DotLoop>
</div>
</template>
</div>
</template>
<script lang="ts" setup>
import CustomAudio from './audio.vue';
import DotLoop from './DotLoop.vue';
const props = withDefaults(
defineProps<{
status: string;
url?: any[];
}>(),
{
url: () => [],
}
);
</script>
<style lang="less">
.voice-loading {
background: #181818;
border-radius: 42px;
font-weight: 400;
font-size: 13px;
height: 54px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<template> <template>
<div class="admin-page-edit-parent"> <div class="admin-page-edit-parent custom-scrollbar">
<div class="custom-admin-page-edit"> <div class="custom-admin-page-edit">
<div class="admin-page-header"> <div class="admin-page-header">
<div> <div>
...@@ -32,85 +32,91 @@ ...@@ -32,85 +32,91 @@
<div class="edit-form"> <div class="edit-form">
<div class="edit-form-content"> <div class="edit-form-content">
<template v-for="item in form.form_options" :key="item.title"> <template v-for="item in form.form_options" :key="item.title">
<div class="edit-form-item-label"> <div v-show="!item.is_hidden">
<template v-if="item.icon == 'TextToSpeech'"> <div class="edit-form-item-label">
<TextToSpeechSvg style="fill: white"></TextToSpeechSvg> <template v-if="item.icon == 'TextToSpeech'">
</template> <TextToSpeechSvg style="fill: white"></TextToSpeechSvg>
<template v-else-if="item.icon == 'message'">
<MessageSvg style="fill: white"></MessageSvg>
</template>
<template v-else-if="item.icon == 'crossTalk'">
<CrossTalk></CrossTalk>
</template>
<template v-else-if="item.icon == 'discourseBind'">
<DiscourseBindSvg></DiscourseBindSvg>
</template>
<template v-else-if="item.icon == 'ManualResponse'">
<ManualResponseSvg></ManualResponseSvg>
</template>
<template v-else>
<img :src="item.icon" alt="" />
</template>
{{ item.title }}
</div>
<div
class="edit-form-item"
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"
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>
</CustomInput>
</template> </template>
<template v-else-if="it.type == 'select'"> <template v-else-if="item.icon == 'message'">
<CustomSelect <MessageSvg style="fill: white"></MessageSvg>
:options="it.options"
v-model="it.value"
:item="{}"
:align="it.align"
:audio="it.audio"
width="800px"
></CustomSelect>
</template> </template>
<template v-else-if="it.type == 'textarea'"> <template v-else-if="item.icon == 'crossTalk'">
<CustomTextarea <CrossTalk></CrossTalk>
v-model="it.value"
:disabled="form.is_send ? form.is_send.disabled : false"
></CustomTextarea>
</template> </template>
<template v-else-if="it.type == 'number'"> <template v-else-if="item.icon == 'discourseBind'">
<CustomInput <DiscourseBindSvg></DiscourseBindSvg>
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>
</template>
</template>
</CustomInput>
</template> </template>
<template v-else-if="item.icon == 'ManualResponse'">
<ManualResponseSvg></ManualResponseSvg>
</template>
<template v-else>
<img :src="item.icon" alt="" />
</template>
{{ item.title }}
</div>
<div
class="edit-form-item"
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>
</template>
</CustomInput>
</template>
<template v-else-if="it.type == 'select'">
<CustomSelect
:options="it.options"
v-model="it.value"
:item="{}"
:align="it.align"
:audio="it.audio"
:is_watch="it.watch ? it.watch : false"
width="100%"
@change="SelectChange"
></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>
</template>
</template>
</CustomInput>
</template>
</div>
</div> </div>
</div> </div>
</template> </template>
...@@ -126,12 +132,11 @@ ...@@ -126,12 +132,11 @@
</CustomButton> </CustomButton>
</div> </div>
</template> </template>
<template v-if="form.play_audio"> <template v-if="form.audio">
<CustomAudio <GenerateVoice
bk="#181818" :status="form.audio.status"
:need_progress="true" :url="form.audio.url"
:url="''" ></GenerateVoice>
></CustomAudio>
</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>
...@@ -164,7 +169,7 @@ ...@@ -164,7 +169,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import CustomAudio from './audio.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';
import CustomSelect from './select.vue'; import CustomSelect from './select.vue';
...@@ -180,10 +185,12 @@ import DiscourseBindSvg from '@/assets/svg/form/discourseBind.svg'; ...@@ -180,10 +185,12 @@ 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 { ref } from 'vue';
const props = defineProps<{ const props = defineProps<{
form: any; form: any;
}>(); }>();
const router = useRouter(); const router = useRouter();
const backTable = () => { const backTable = () => {
const { back_url } = props.form; const { back_url } = props.form;
if (!back_url) { if (!back_url) {
...@@ -203,6 +210,11 @@ const onSend = () => { ...@@ -203,6 +210,11 @@ const onSend = () => {
// //
} }
}; };
// 下拉框事件
const SelectChange = (value: string, fun: any) => {
fun(value);
};
</script> </script>
<style lang="less"> <style lang="less">
...@@ -271,7 +283,10 @@ const onSend = () => { ...@@ -271,7 +283,10 @@ const onSend = () => {
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 0 30px;
box-sizing: border-box;
.edit-form-content { .edit-form-content {
width: 800px;
.edit-form-item-label { .edit-form-item-label {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -338,7 +353,7 @@ const onSend = () => { ...@@ -338,7 +353,7 @@ const onSend = () => {
.edit-input { .edit-input {
height: auto; height: auto;
width: 800px; max-width: 800px;
.custom-input-box { .custom-input-box {
height: 34px; height: 34px;
border: none; border: none;
......
...@@ -40,21 +40,21 @@ ...@@ -40,21 +40,21 @@
</template> </template>
</div> </div>
<audio ref="audioRef" :src="url" @canplay="onCanplay"></audio> <audio ref="audioRef" :src="CurrentUrl()" @canplay="onCanplay"></audio>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onBeforeMount, onBeforeUnmount } from 'vue'; import { ref, onBeforeMount, onBeforeUnmount, computed } from 'vue';
withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
url?: string; url?: string[];
need_progress?: boolean; need_progress?: boolean;
bk?: string; bk?: string;
}>(), }>(),
{ {
need_progress: false, need_progress: false,
url: '', url: () => [],
bk: 'transparent', bk: 'transparent',
} }
); );
...@@ -100,13 +100,41 @@ const playStatus = ref<boolean>(false); // 音频播放状态:true 播放,fa ...@@ -100,13 +100,41 @@ const playStatus = ref<boolean>(false); // 音频播放状态:true 播放,fa
const playProgress = ref(0); // 音频播放进度 const playProgress = ref(0); // 音频播放进度
const timeInterval = ref(); // 获取音频播放进度定时器 const timeInterval = ref(); // 获取音频播放进度定时器
// 当前播放的音频下标
const audio_index = ref(0);
// 当前播放的音频链接
const CurrentUrl = computed(() => {
return function () {
const { url } = props;
if (url && url.length) {
return url[audio_index.value];
}
};
});
// 音频加载完毕的回调 // 音频加载完毕的回调
const onCanplay = () => { const onCanplay = () => {
audioDuration.value = audioRef?.value.duration || 0; audioDuration.value = audioRef?.value.duration || 0;
}; };
// 更新音频
const UpdateAudio = async () => {
// 进入到下一个
const { url } = props;
if (url && url.length) {
if (audio_index.value === url.length - 1) {
// 最后一个,暂停播放
await onPause();
} else if (audio_index.value < url.length - 1) {
audio_index.value += 1;
await onPause();
onPlay();
}
}
};
const onPlay = async () => { const onPlay = async () => {
// 音频播放完后,重新播放 // 音频播放完后,重新播放
if (playProgress.value === 100) audioRef.value.currentTime = 0; // if (playProgress.value === 100) audioRef.value.currentTime = 0;
await audioRef.value.play(); await audioRef.value.play();
playStatus.value = true; playStatus.value = true;
...@@ -115,11 +143,15 @@ const onPlay = async () => { ...@@ -115,11 +143,15 @@ const onPlay = async () => {
timeInterval.value = setInterval(() => { timeInterval.value = setInterval(() => {
audioCurrent.value = audioRef.value.currentTime; audioCurrent.value = audioRef.value.currentTime;
playProgress.value = (audioCurrent.value / audioDuration.value) * 100; playProgress.value = (audioCurrent.value / audioDuration.value) * 100;
if (playProgress.value === 100) onPause(); if (playProgress.value === 100) {
UpdateAudio();
}
}, 100); }, 100);
}; };
const onPause = () => {
audioRef.value.pause(); // 暂停播放
const onPause = async () => {
await audioRef.value.pause();
playStatus.value = false; playStatus.value = false;
clearInterval(timeInterval.value); clearInterval(timeInterval.value);
}; };
......
<template> <template>
<div class="custom-input-global"> <div class="custom-input-global" :style="{ width: width }">
<div <div
class="custom-input-box" class="custom-input-box"
:class="{ 'custom-input-error': ruleError.status }" :class="{ 'custom-input-error': ruleError.status }"
...@@ -69,6 +69,7 @@ const props = withDefaults( ...@@ -69,6 +69,7 @@ const props = withDefaults(
needSelect?: boolean; needSelect?: boolean;
selectList?: any; selectList?: any;
align?: string; align?: string;
width?: string;
}>(), }>(),
{ {
// 输入框类型 // 输入框类型
...@@ -79,6 +80,7 @@ const props = withDefaults( ...@@ -79,6 +80,7 @@ const props = withDefaults(
selectList: [], selectList: [],
// rules: [], // rules: [],
disabled: false, disabled: false,
width: '',
} }
); );
const emit = defineEmits([ const emit = defineEmits([
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<TSelect <TSelect
v-model="SelectValue" v-model="SelectValue"
:placeholder="item.placeholder" :placeholder="item.placeholder"
:filterable="filterable"
:popupProps="{ :popupProps="{
overlayClassName: [className, 'admin-select-popup'], overlayClassName: [className, 'admin-select-popup'],
}" }"
...@@ -44,20 +45,27 @@ const props = withDefaults( ...@@ -44,20 +45,27 @@ const props = withDefaults(
className?: string; className?: string;
align?: string; align?: string;
audio?: boolean; audio?: boolean;
is_watch?: any;
filterable?: boolean;
}>(), }>(),
{ {
width: '357px', width: '357px',
align: 'center', align: 'center',
audio: false, audio: false,
is_watch: false,
filterable: false,
} }
); );
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue', 'change']);
const SelectValue = ref(props.modelValue); const SelectValue = ref(props.modelValue);
watch( watch(
() => SelectValue.value, () => SelectValue.value,
(v) => { (v) => {
emit('update:modelValue', v); emit('update:modelValue', v);
if (props.is_watch) {
emit('change', v, props.is_watch);
}
} }
); );
watch( watch(
......
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
@change="CheckOne(row)" @change="CheckOne(row)"
></TCheckbox> ></TCheckbox>
</template> </template>
<template #title="{ row }"> <template #audio="{ row }">
<slot name="title" :row="row"></slot> <slot name="audio" :row="row"></slot>
</template> </template>
<template #mp3="{ row }"> <template #content="{ row }">
<slot name="mp3" :row="row"></slot> <slot name="content" :row="row"></slot>
</template> </template>
<template #edit="{ row }"> <template #edit="{ row }">
<slot name="edit" :row="row"> <slot name="edit" :row="row">
...@@ -47,27 +47,34 @@ ...@@ -47,27 +47,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Table as TTable, Checkbox as TCheckbox } from 'tdesign-vue-next'; import { Table as TTable, Checkbox as TCheckbox } from 'tdesign-vue-next';
import { onBeforeMount, reactive, ref } from 'vue'; import { onBeforeMount, reactive, ref, watch } from 'vue';
// import { getGenerateRecords } from '@/utils/api/scenes'; // import { getGenerateRecords } from '@/utils/api/scenes';
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 } from '@/constants/admin_form';
import { show_message } from '@/utils/tdesign_tool';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
api: string;
api_type: string;
columns: any[]; columns: any[];
local_key: string; local_key: string;
edit_page: string; edit_page: string;
checkbox?: boolean; checkbox?: boolean;
edit_key: string; edit_key: string;
table_api?: any;
filter_num?: number;
filter_api?: any;
AlreadyChoose?: any;
}>(), }>(),
{ {
checkbox: true, checkbox: true,
table_api: false,
filter_num: 1,
filter_api: false,
AlreadyChoose: {},
} }
); );
const emit = defineEmits(['ChangeList', 'ChoseList']); const emit = defineEmits(['ChangeList', 'ChoseList', 'PageNumChange']);
// 获取本地的page // 获取本地的page
const getPage = () => { const getPage = () => {
const page = getLocalData(props.local_key, 'session'); const page = getLocalData(props.local_key, 'session');
...@@ -82,8 +89,14 @@ const is_check_all = ref(false); ...@@ -82,8 +89,14 @@ const is_check_all = ref(false);
const tableList = reactive({ const tableList = reactive({
list: [], list: [],
}); });
const pageChange = (value: number) => {
// 修改当前页
const ChangeCurrentPage = (value: number) => {
pageNum.value = value; pageNum.value = value;
emit('PageNumChange', value);
};
const pageChange = (value: number) => {
ChangeCurrentPage(value);
// 存本地 // 存本地
setLocalData(props.local_key, value, 'session'); setLocalData(props.local_key, value, 'session');
getLog(); getLog();
...@@ -132,6 +145,45 @@ const CheckOne = (row: any) => { ...@@ -132,6 +145,45 @@ const CheckOne = (row: any) => {
} }
}; };
// 添加表格多选框和状态
const setTableCheckBox = (res: any) => {
// 增加一个选中状态
res.list.forEach((item: any, index: number) => {
item.is_check = false;
item.index = index;
});
return res;
};
const StartFilter = async () => {
try {
const { filter_api } = props;
if (filter_api) {
// page初始化
ChangeCurrentPage(1);
loading.value = true;
let res: any = await filter_api(props.AlreadyChoose);
res = await setTableCheckBox(res);
tableList.list = res.list;
total.value = res.total;
loading.value = false;
} else {
show_message('未配置filter');
}
} catch (e) {
console.log(e);
loading.value = false;
}
};
watch(
() => props.filter_num,
(v) => {
// 开始筛选
StartFilter();
}
);
// 打开编辑页面 // 打开编辑页面
const onEdit = (row: any) => { const onEdit = (row: any) => {
const { edit_page, edit_key } = props; const { edit_page, edit_key } = props;
...@@ -142,35 +194,12 @@ const onEdit = (row: any) => { ...@@ -142,35 +194,12 @@ const onEdit = (row: any) => {
const getLog = async () => { const getLog = async () => {
try { try {
loading.value = true; loading.value = true;
// let res: any = await getGenerateRecords({ let res: any = await props.table_api();
// page: pageNum.value,
// limit: pageSize.value,
// type: TASKTYPE.CHAT,
// });
// if (res.code == 0) {
// RecordList.list = res.data.data;
// total.value = res.data.total;
// }
// console.log(res);
// 假数据
const list = [
{
title: '你好',
detail: '详细',
consumes_characters: '消耗',
download: '编辑',
mp3: new URL('../../assets/mp3/test.aac', import.meta.url).href,
},
];
if (props.checkbox) { if (props.checkbox) {
// 增加一个选中状态 res = await setTableCheckBox(res);
list.forEach((item: any, index: number) => {
item.is_check = false;
item.index = index;
});
} }
tableList.list = list; tableList.list = res.list;
total.value = res.total;
loading.value = false; loading.value = false;
} catch (e) { } catch (e) {
loading.value = false; loading.value = false;
......
...@@ -56,6 +56,8 @@ export const EditFillData = (form: any[], row: any) => { ...@@ -56,6 +56,8 @@ 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);
console.log(it.name);
if (it.name == key) { if (it.name == key) {
// 填充数据 // 填充数据
it.value = row[key]; it.value = row[key];
...@@ -63,4 +65,30 @@ export const EditFillData = (form: any[], row: any) => { ...@@ -63,4 +65,30 @@ export const EditFillData = (form: any[], row: any) => {
}); });
}); });
}); });
console.log(form);
};
// 筛选配置填充
export const FilterConfigFill = (resData: any, form: any[]) => {
form.forEach((item: any) => {
// 循环resdata的key
Object.keys(resData).forEach((it: any) => {
if (item.name == it) {
if (typeof resData[it][0] == 'string') {
// 需要转换格式
const list: any = [];
resData[it].forEach((res: any) => {
const obj = {
label: res,
value: res,
};
list.push(obj);
});
item.options = list;
} else {
item.options = resData[it];
}
}
});
});
}; };
...@@ -212,7 +212,7 @@ export default defineComponent({ ...@@ -212,7 +212,7 @@ export default defineComponent({
)} )}
</div> </div>
</div> </div>
<div class="custom-tab-content custom-scrollbar"> <div class="custom-tab-content">
{ProgressStatus.value.show ? ( {ProgressStatus.value.show ? (
<div class="admin-page-progress"> <div class="admin-page-progress">
<TProgress <TProgress
......
...@@ -3,24 +3,95 @@ ...@@ -3,24 +3,95 @@
:form="ManagementForm" :form="ManagementForm"
v-model:list="ManagementForm.table_list" v-model:list="ManagementForm.table_list"
@reset="ResetFilter" @reset="ResetFilter"
@PageNumChange="PageNumChange"
> >
<template #title> <template #audio="{ row }">
<div>111</div> <CustomAudio :url="row.audio"></CustomAudio>
</template> </template>
<template #mp3="{ row }"> <template #content="{ row }">
<CustomAudio :url="row.mp3"></CustomAudio> <ContentTooltip :content="row.content"></ContentTooltip>
</template> </template>
</AdminPublicPageVue> </AdminPublicPageVue>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import ContentTooltip from '@/components/Admin/ContentTooltip.vue';
import CustomAudio from '@/components/Admin/audio.vue'; import CustomAudio from '@/components/Admin/audio.vue';
import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue'; import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { reactive } from 'vue'; import { onBeforeMount, reactive, ref } from 'vue';
import { isDevContext } from '@/utils/tool'; import { isDevContext } from '@/utils/tool';
import { ResetForm } from '@/constants/admin_form'; import { FilterConfigFill, ResetForm } from '@/constants/admin_form';
import { AdminFilterApi } from '@/utils/api/ai';
import { discourse_management_edit } from '@/constants/token'; import { discourse_management_edit } from '@/constants/token';
import {
DiscourseManagementConfig,
DiscourseManagementList,
DiscourseManagementFilter,
} from '@/utils/api/ai';
const pageNum = ref(1);
const pageSize = ref(10);
// 转换列表中音频的格式
const changeAudio = (list: any[]) => {
list.forEach((item: any) => {
// 转换audio列表
if (typeof item.audio == 'string') {
item.audio = JSON.parse(item.audio);
}
});
return list;
};
// 请求表格接口
const getTableList = async () => {
try {
const res: any = await DiscourseManagementList({
page: pageNum.value,
limit: pageSize.value,
});
const list = changeAudio(res.data.data);
return {
list: list,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 分页变化
const PageNumChange = (value: number) => {
pageNum.value = value;
};
// 获取筛选列表配置
const getFilterList = async () => {
try {
const res: any = await DiscourseManagementConfig();
if (res.data) {
FilterConfigFill(res.data, ManagementForm.filter_option);
}
} catch (e) {
console.log(e);
}
};
// 开始筛选
const onFilter = async (params: any) => {
try {
const res: any = await DiscourseManagementFilter({
page: pageNum.value,
limit: pageSize.value,
...params,
});
const list = changeAudio(res.data.data);
return {
list: list,
total: res.data.total,
};
} catch (e) {
console.log(e);
}
};
// 表单配置项 // 表单配置项
const ManagementForm = reactive({ const ManagementForm = reactive({
title: '话术列表', title: '话术列表',
...@@ -30,17 +101,15 @@ const ManagementForm = reactive({ ...@@ -30,17 +101,15 @@ const ManagementForm = reactive({
// 能否筛选 // 能否筛选
filter: true, filter: true,
// 筛选接口 // 筛选接口
filter_api: isDevContext() ? '' : '', filter_api: onFilter,
// 能否新增 // 能否新增
add: true, add: true,
// 表格key--用来缓存表格分页 // 表格key--用来缓存表格分页
local_key: 'admin_discourse_management', local_key: 'admin_discourse_management',
// 表格数据 // 表格数据
table_list: [], table_list: [],
// 表格接口 // 表格接口function
table_api: isDevContext() ? '' : '', table_api: getTableList,
// api类型
table_api_type: 'get',
// 能否多选--默认为true // 能否多选--默认为true
checkbox: true, checkbox: true,
// 编辑页面 // 编辑页面
...@@ -64,22 +133,31 @@ const ManagementForm = reactive({ ...@@ -64,22 +133,31 @@ const ManagementForm = reactive({
colKey: 'checkbox', colKey: 'checkbox',
}, },
{ {
title: '产品', title: 'ID',
colKey: 'id',
},
{
title: '标题',
colKey: 'title', colKey: 'title',
}, },
{ {
title: '详细', title: '产品',
colKey: 'detail', colKey: 'product',
},
{
title: '语言',
colKey: 'language',
align: 'center', align: 'center',
}, },
{ {
title: '消耗字符数', title: '语音内容',
colKey: 'consumes_characters', colKey: 'content',
align: 'center', align: 'center',
width: '20%',
}, },
{ {
title: '音频', title: '音频',
colKey: 'mp3', colKey: 'audio',
align: 'center', align: 'center',
}, },
{ {
...@@ -91,52 +169,40 @@ const ManagementForm = reactive({ ...@@ -91,52 +169,40 @@ 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: '你好', align: 'left',
value: '你好', options: [],
},
{
label: '你好2',
value: '你好2',
},
],
}, },
{ {
type: 'select', type: 'select',
name: 'select_product', name: 'product',
label: '产品', label: '产品',
placeholder: '产品', placeholder: '产品',
value: '', value: '',
options: [ // 能否输入
{ filterable: true,
label: '你好', align: 'left',
value: '你好', options: [],
},
{
label: '你好2',
value: '你好2',
},
],
}, },
{ {
type: 'select', type: 'select',
name: 'select_language', name: 'language',
label: '语言', label: '语言',
placeholder: '语言', placeholder: '语言',
value: '', value: '',
options: [ options: [
{ {
label: '你好', label: '中文',
value: '你好', value: 'cn',
}, },
{ {
label: '你好2', label: '英文',
value: '你好2', value: 'en',
}, },
], ],
}, },
...@@ -147,9 +213,11 @@ const ManagementForm = reactive({ ...@@ -147,9 +213,11 @@ const ManagementForm = reactive({
const ResetFilter = () => { const ResetFilter = () => {
ResetForm(ManagementForm.filter_option); ResetForm(ManagementForm.filter_option);
// 请求接口
// AdminFilterApi();
}; };
onBeforeMount(() => {
getFilterList();
});
</script> </script>
<style lang="less"></style> <style lang="less"></style>
...@@ -31,7 +31,11 @@ const ManagementForm = reactive({ ...@@ -31,7 +31,11 @@ const ManagementForm = reactive({
//能否重置 //能否重置
reset: true, reset: true,
// 是否转换为语音 // 是否转换为语音
conversion: true, conversion: {
api: '',
options: [],
value: '',
},
// 播放音频 // 播放音频
play_audio: true, play_audio: true,
form_options: [ form_options: [
...@@ -42,7 +46,7 @@ const ManagementForm = reactive({ ...@@ -42,7 +46,7 @@ const ManagementForm = reactive({
{ {
type: 'text', type: 'text',
label: '标题', label: '标题',
name: 'title_1', name: 'title',
value: '', value: '',
// 是否禁用 // 是否禁用
disabled: false, disabled: false,
...@@ -50,7 +54,7 @@ const ManagementForm = reactive({ ...@@ -50,7 +54,7 @@ const ManagementForm = reactive({
{ {
type: 'text', type: 'text',
label: '产品', label: '产品',
name: 'product_1', name: 'product',
value: '', value: '',
}, },
], ],
...@@ -63,7 +67,7 @@ const ManagementForm = reactive({ ...@@ -63,7 +67,7 @@ const ManagementForm = reactive({
{ {
type: 'select', type: 'select',
label: '语言', label: '语言',
name: 'language_1', name: 'language',
placeholder: '请选择语言', placeholder: '请选择语言',
value: '', value: '',
align: 'left', align: 'left',
...@@ -73,7 +77,7 @@ const ManagementForm = reactive({ ...@@ -73,7 +77,7 @@ const ManagementForm = reactive({
value: 'cn', value: 'cn',
}, },
{ {
label: '英', label: '英',
value: 'en', value: 'en',
}, },
], ],
...@@ -87,12 +91,24 @@ const ManagementForm = reactive({ ...@@ -87,12 +91,24 @@ const ManagementForm = reactive({
align: 'left', align: 'left',
options: [ options: [
{ {
label: '小微 (直播间专属)', label: '柜姐',
value: '123', value: 'guijie',
},
{
label: '小仙',
value: 'xiaoxian',
},
{
label: '艾飞',
value: 'aifei',
},
{
label: '老铁',
value: 'laotie',
}, },
{ {
label: '小爱 (直播间专属)', label: '老妹',
value: '12345', value: 'laomei',
}, },
], ],
}, },
...@@ -102,6 +118,7 @@ const ManagementForm = reactive({ ...@@ -102,6 +118,7 @@ const ManagementForm = reactive({
name: 'product_1', name: 'product_1',
placeholder: '请输入语音内容', placeholder: '请输入语音内容',
value: '', value: '',
maxlength: 1000,
}, },
], ],
}, },
......
...@@ -34,7 +34,10 @@ const ManagementForm = reactive({ ...@@ -34,7 +34,10 @@ const ManagementForm = reactive({
// 是否转换为语音 // 是否转换为语音
conversion: true, conversion: true,
// 播放音频 // 播放音频
play_audio: true, audio: {
url: [],
status: '',
},
form_options: [ form_options: [
{ {
icon: imgs.fill, icon: imgs.fill,
...@@ -122,6 +125,7 @@ onBeforeMount(() => { ...@@ -122,6 +125,7 @@ onBeforeMount(() => {
discourse_management_edit, discourse_management_edit,
ManagementForm.back_url ManagementForm.back_url
); );
console.log(row);
// 填充数据 // 填充数据
EditFillData(ManagementForm.form_options, row); EditFillData(ManagementForm.form_options, row);
}); });
......
...@@ -15,7 +15,6 @@ import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue'; ...@@ -15,7 +15,6 @@ import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { reactive } from 'vue'; import { reactive } from 'vue';
import { isDevContext } from '@/utils/tool'; import { isDevContext } from '@/utils/tool';
import { ResetForm } from '@/constants/admin_form'; import { ResetForm } from '@/constants/admin_form';
import { AdminFilterApi } from '@/utils/api/ai';
import { interactive_setting_edit } from '@/constants/token'; import { interactive_setting_edit } from '@/constants/token';
// 表单配置项 // 表单配置项
const ManagementForm = reactive({ const ManagementForm = reactive({
...@@ -143,8 +142,6 @@ const ManagementForm = reactive({ ...@@ -143,8 +142,6 @@ const ManagementForm = reactive({
const ResetFilter = () => { const ResetFilter = () => {
ResetForm(ManagementForm.filter_option); ResetForm(ManagementForm.filter_option);
// 请求接口
// AdminFilterApi();
}; };
</script> </script>
......
...@@ -14,6 +14,17 @@ const router = useRouter(); ...@@ -14,6 +14,17 @@ 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;
}
});
};
// 编辑页面组件 // 编辑页面组件
const ManagementForm = reactive({ const ManagementForm = reactive({
title: '互动设置', title: '互动设置',
...@@ -41,10 +52,23 @@ const ManagementForm = reactive({ ...@@ -41,10 +52,23 @@ const ManagementForm = reactive({
title: '', title: '',
lists: [ lists: [
{ {
type: 'text', type: 'select',
label: '类型', label: '类型',
name: 'title_1', name: 'language_1',
value: '自动回复设置', placeholder: '请选择类型',
value: 'auto',
align: 'left',
watch: ChangeComponentsShow,
options: [
{
label: '自动回复设置',
value: 'auto',
},
{
label: '串场互动话术设置',
value: 'crosstown',
},
],
}, },
], ],
}, },
...@@ -94,6 +118,8 @@ const ManagementForm = reactive({ ...@@ -94,6 +118,8 @@ const ManagementForm = reactive({
{ {
icon: 'message', icon: 'message',
title: '自动回复设置', title: '自动回复设置',
is_hidden: false,
name: 'auto',
lists: [ lists: [
{ {
type: 'text', type: 'text',
...@@ -112,6 +138,29 @@ const ManagementForm = reactive({ ...@@ -112,6 +138,29 @@ const ManagementForm = reactive({
}, },
], ],
}, },
{
icon: 'discourseBind',
title: '串场互动话术设置',
is_hidden: true,
name: 'crosstown',
lists: [
{
type: 'text',
label: '标题',
name: 'language_20',
placeholder: '请输入',
value: '',
align: 'left',
},
{
type: 'textarea',
label: '话术内容',
name: 'product_30',
placeholder: '请输入话术内容',
value: '',
},
],
},
], ],
}); });
......
...@@ -21,7 +21,6 @@ import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue'; ...@@ -21,7 +21,6 @@ import AdminPublicPageVue from '@/components/Admin/AdminPublicPage.vue';
import { reactive } from 'vue'; import { reactive } from 'vue';
import { isDevContext } from '@/utils/tool'; import { isDevContext } from '@/utils/tool';
import { ResetForm, EditButtonEvent } from '@/constants/admin_form'; import { ResetForm, EditButtonEvent } from '@/constants/admin_form';
import { AdminFilterApi } from '@/utils/api/ai';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { import {
live_stream_edit, live_stream_edit,
...@@ -154,8 +153,6 @@ const ManagementForm = reactive({ ...@@ -154,8 +153,6 @@ const ManagementForm = reactive({
// 重置表单并重新请求 // 重置表单并重新请求
const ResetFilter = () => { const ResetFilter = () => {
ResetForm(ManagementForm.filter_option); ResetForm(ManagementForm.filter_option);
// 请求接口
// AdminFilterApi();
}; };
// 编辑 // 编辑
......
...@@ -19,7 +19,7 @@ const ManagementForm = reactive({ ...@@ -19,7 +19,7 @@ const ManagementForm = reactive({
body_title: '新增', body_title: '新增',
// 是否显示返回列表页 // 是否显示返回列表页
back: true, back: true,
back_url: '/AILiveStreaming/InteractiveSetting', back_url: '/AILiveStreaming/LiveStream',
// 能否删除, // 能否删除,
delete: false, delete: false,
// 删除api // 删除api
...@@ -36,81 +36,88 @@ const ManagementForm = reactive({ ...@@ -36,81 +36,88 @@ const ManagementForm = reactive({
play_audio: false, play_audio: false,
form_options: [ form_options: [
{ {
icon: '', icon: imgs.fill,
title: '', title: '基础填写',
lists: [ lists: [
{ {
type: 'text', type: 'text',
label: '类型', label: '直播间标题',
name: 'title_1', name: 'title_1',
value: '', value: '',
placeholder: '请输入类型', disabled: true,
// 是否禁用 placeholder: '',
disabled: false, },
{
type: 'text',
label: '直播间连接',
name: 'title_12',
value: '',
}, },
], ],
}, },
{ {
icon: 'TextToSpeech', icon: 'discourseBind',
title: '语音设置', title: '话术绑定',
lists: [ lists: [
{ {
type: 'select', type: 'select',
label: '语言', label: '直播话术',
name: 'language_1', name: 'language_1',
placeholder: '请选择语言', placeholder: '请选择语言',
value: '', value: '',
align: 'left', align: 'left',
options: [ options: [
{ {
label: '中文', label: '话术1',
value: 'cn', value: 'cn',
}, },
{ {
label: '英语', label: '话术2',
value: 'en', value: 'en',
}, },
], ],
}, },
{ {
type: 'select', type: 'select',
label: '语音', label: '自动回复话术',
name: 'voice', name: 'voice',
placeholder: '请选择语音', placeholder: '请选择自动回复话术',
value: '', value: '',
align: 'left', align: 'left',
audio: true,
options: [ options: [
{ {
label: '小微 (直播间专属)', label: '自动回复话术1',
value: '123', value: '123',
}, },
{ {
label: '小爱 (直播间专属)', label: '自动回复话术2',
value: '12345', value: '12345',
}, },
], ],
}, },
],
},
// 串场互动
{
icon: 'crossTalk',
title: '串场互动话术设置',
lists: [
{ {
type: 'text', type: 'select',
label: '标题', label: '串场互动话术',
name: 'title_1', name: 'voice',
placeholder: '请选择串场互动话术',
value: '', value: '',
placeholder: '请输入标题', align: 'left',
options: [
{
label: '串场互动话术1',
value: '123',
},
{
label: '串场互动话术2',
value: '12345',
},
],
}, },
{ {
type: 'textarea', type: 'number',
label: '话术内容', name: 'number',
name: 'title_2', label: '串场互动触发时间间隔',
value: '', value: '',
placeholder: '请输入话术内容',
}, },
], ],
}, },
......
import request from '@/utils/request'; import request from '@/utils/request';
export const AdminFilterApi = () => { import { getUserCookie } from './userApi';
return request.get('ddd'); /**
* ai直播模块接口
*/
// 话术管理配置信息
export const DiscourseManagementConfig = () => {
return request.get('/api/voices/get-user-config', {
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 话术管理表格
export const DiscourseManagementList = (data: any) => {
return request.get('/api/voices/get-voice-live', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
};
// 话术管理筛选
export const DiscourseManagementFilter = (data: any) => {
return request.get('/api/voices/get-config-filter', {
params: data,
headers: {
authorization: `Bearer ${getUserCookie()}`,
},
});
}; };
...@@ -13,7 +13,10 @@ export default defineConfig(({ mode }) => { ...@@ -13,7 +13,10 @@ export default defineConfig(({ mode }) => {
const newDate = `${date.getFullYear()}-${ const newDate = `${date.getFullYear()}-${
date.getMonth() + 1 date.getMonth() + 1
}-${date.getDate()}--${date.getHours()}.${date.getMinutes()}`; }-${date.getDate()}--${date.getHours()}.${date.getMinutes()}`;
const api = 1 ? 'http://156.247.11.21:85' : 'http://ai-gpt.test'; // 192.168.1.13:88 -- zh
// http://ai-gpt.test
// http://156.247.11.21:85--线上
const api = 1 ? 'http://192.168.1.13:88' : 'http://ai-gpt.test';
return { return {
base: '/', base: '/',
resolve: { resolve: {
......
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