Commit 6c2fc5cb authored by nick zheng's avatar nick zheng

chore: 数字人对话配置及我的对话

parent 621bdca9
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"@unocss/reset": "^0.61.9", "@unocss/reset": "^0.61.9",
"@vueuse/core": "^10.11.1", "@vueuse/core": "^10.11.1",
"axios": "^1.7.7", "axios": "^1.7.7",
"clipboardy": "^4.0.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"pinia": "^2.2.2", "pinia": "^2.2.2",
......
...@@ -23,6 +23,9 @@ importers: ...@@ -23,6 +23,9 @@ importers:
axios: axios:
specifier: ^1.7.7 specifier: ^1.7.7
version: 1.7.7 version: 1.7.7
clipboardy:
specifier: ^4.0.0
version: 4.0.0
dayjs: dayjs:
specifier: ^1.11.13 specifier: ^1.11.13
version: 1.11.13 version: 1.11.13
...@@ -1292,6 +1295,10 @@ packages: ...@@ -1292,6 +1295,10 @@ packages:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'} engines: {node: '>=18'}
clipboardy@4.0.0:
resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==}
engines: {node: '>=18'}
cliui@8.0.1: cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -1855,6 +1862,11 @@ packages: ...@@ -1855,6 +1862,11 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
hasBin: true hasBin: true
is-docker@3.0.0:
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true
is-extglob@2.1.1: is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
...@@ -1875,6 +1887,11 @@ packages: ...@@ -1875,6 +1887,11 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
hasBin: true
is-number@7.0.0: is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'} engines: {node: '>=0.12.0'}
...@@ -1903,6 +1920,14 @@ packages: ...@@ -1903,6 +1920,14 @@ packages:
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
engines: {node: '>=8'} engines: {node: '>=8'}
is-wsl@3.1.0:
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
engines: {node: '>=16'}
is64bit@2.0.0:
resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==}
engines: {node: '>=18'}
isexe@2.0.0: isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
...@@ -2640,6 +2665,10 @@ packages: ...@@ -2640,6 +2665,10 @@ packages:
resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
system-architecture@0.1.0:
resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==}
engines: {node: '>=18'}
table@6.8.2: table@6.8.2:
resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
...@@ -4199,6 +4228,12 @@ snapshots: ...@@ -4199,6 +4228,12 @@ snapshots:
slice-ansi: 5.0.0 slice-ansi: 5.0.0
string-width: 7.2.0 string-width: 7.2.0
clipboardy@4.0.0:
dependencies:
execa: 8.0.1
is-wsl: 3.1.0
is64bit: 2.0.0
cliui@8.0.1: cliui@8.0.1:
dependencies: dependencies:
string-width: 4.2.3 string-width: 4.2.3
...@@ -4775,6 +4810,8 @@ snapshots: ...@@ -4775,6 +4810,8 @@ snapshots:
is-docker@2.2.1: {} is-docker@2.2.1: {}
is-docker@3.0.0: {}
is-extglob@2.1.1: {} is-extglob@2.1.1: {}
is-fullwidth-code-point@3.0.0: {} is-fullwidth-code-point@3.0.0: {}
...@@ -4789,6 +4826,10 @@ snapshots: ...@@ -4789,6 +4826,10 @@ snapshots:
dependencies: dependencies:
is-extglob: 2.1.1 is-extglob: 2.1.1
is-inside-container@1.0.0:
dependencies:
is-docker: 3.0.0
is-number@7.0.0: {} is-number@7.0.0: {}
is-obj@2.0.0: {} is-obj@2.0.0: {}
...@@ -4807,6 +4848,14 @@ snapshots: ...@@ -4807,6 +4848,14 @@ snapshots:
dependencies: dependencies:
is-docker: 2.2.1 is-docker: 2.2.1
is-wsl@3.1.0:
dependencies:
is-inside-container: 1.0.0
is64bit@2.0.0:
dependencies:
system-architecture: 0.1.0
isexe@2.0.0: {} isexe@2.0.0: {}
jiti@1.21.6: {} jiti@1.21.6: {}
...@@ -5476,6 +5525,8 @@ snapshots: ...@@ -5476,6 +5525,8 @@ snapshots:
'@pkgr/core': 0.1.1 '@pkgr/core': 0.1.1
tslib: 2.7.0 tslib: 2.7.0
system-architecture@0.1.0: {}
table@6.8.2: table@6.8.2:
dependencies: dependencies:
ajv: 8.17.1 ajv: 8.17.1
......
...@@ -21,8 +21,8 @@ export function fetchMultiDelectDigitalHumanDialogueConfig<T>(payload: string[]) ...@@ -21,8 +21,8 @@ export function fetchMultiDelectDigitalHumanDialogueConfig<T>(payload: string[])
} }
// 通过对话数字人列表 // 通过对话数字人列表
export function fetchGetDigitalHumanDialogueList<T>(query: string) { export function fetchGetDigitalHumanDialogueList<T>(query: string, payload: object) {
return request.post<T>(`/bizDigitalHumanDialogueConfigRest/getList.json?query=${query || null}`) return request.post<T>(`/bizDigitalHumanDialogueConfigRest/getList.json?query=${query}`, payload)
} }
// 更改对话数字人开关配置 // 更改对话数字人开关配置
...@@ -30,6 +30,11 @@ export function fetchUpdateDigitalHumanDialogueOpen<T>(configId: string, isOpen: ...@@ -30,6 +30,11 @@ export function fetchUpdateDigitalHumanDialogueOpen<T>(configId: string, isOpen:
return request.post<T>(`/bizDigitalHumanDialogueConfigRest/openConfig.json?configId=${configId}&isOpen=${isOpen}`) return request.post<T>(`/bizDigitalHumanDialogueConfigRest/openConfig.json?configId=${configId}&isOpen=${isOpen}`)
} }
// 发布对话数字人
export function fetchPublishDigitalHumanDialogue<T>(configId: string) {
return request.post<T>(`/bizDigitalHumanDialogueConfigRest/publish.json?configId=${configId}`)
}
// 获取角色模型列表 // 获取角色模型列表
export function fetchDigitalHumanDialogueSystemList<T>(payload: object) { export function fetchDigitalHumanDialogueSystemList<T>(payload: object) {
return request.post<T>('/bizDigitalHumanDialogueSystemModelRest/getList.json', payload) return request.post<T>('/bizDigitalHumanDialogueSystemModelRest/getList.json', payload)
...@@ -40,7 +45,25 @@ export function fetchGetInfoByFigureId<T>(figureId: string) { ...@@ -40,7 +45,25 @@ export function fetchGetInfoByFigureId<T>(figureId: string) {
return request.post<T>(`/bizDigitalHumanImageRest/getInfoByFigureId.json?figureId=${figureId}`) return request.post<T>(`/bizDigitalHumanImageRest/getInfoByFigureId.json?figureId=${figureId}`)
} }
// 用户上传背景图
export function handleUploadBackgroundImageFile<T>(imageName: string, formData: FormData) {
return request.post<T>(`/baiduDigitalHumanFileRest/uploadBackgroundImageFile.json?imageName=${imageName}`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 12000,
})
}
// 根据背景图id删除背景图
export function handleDeleteBackgroundImageById<T>(id: number) {
return request.post<T>(`/bizDigitalHumanMemberImageRest/deletedById.json?id=${id}`)
}
// 获取当前用户背景图 // 获取当前用户背景图
export function fetchGetBackgroundImageList<T>() { export function fetchGetBackgroundImageList<T>() {
return request.post<T>('/aiDigitalHumanImageRest/getBackgroundImageList.json') return request.post<T>('/aiDigitalHumanImageRest/getBackgroundImageList.json')
} }
// 模糊搜索查询背景图
export function fetchSearchBackgroundImageList<T>(imageName: string) {
return request.post<T>(`/aiDigitalHumanImageRest/searchBackgroundImageList.json?imageName=${imageName}`)
}
...@@ -11,7 +11,7 @@ function defaultDigitalHumanDialogue(): DigitalHumanDialogueConfig { ...@@ -11,7 +11,7 @@ function defaultDigitalHumanDialogue(): DigitalHumanDialogueConfig {
publishStatus: 'N', publishStatus: 'N',
}, },
humanInfo: { humanInfo: {
figureId: 'A2A_V2-3to2_leqing', figureId: '',
speed: 5, speed: 5,
intonation: 5, intonation: 5,
timebreId: '5132', timebreId: '5132',
......
import clipboard from 'clipboardy'
export function copyToClip(text: string) {
return clipboard.write(text)
}
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import CustomIcon from '@/components/custom-icon/custom-icon.vue' import CustomIcon from '@/components/custom-icon/custom-icon.vue'
import { uploadImageFile } from '@/apis/digital-creation'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue' import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import { fetchGetBackgroundImageList } from '@/apis/digital-human-dialogue' import {
fetchGetBackgroundImageList,
fetchSearchBackgroundImageList,
handleDeleteBackgroundImageById,
handleUploadBackgroundImageFile,
} from '@/apis/digital-human-dialogue'
interface BackgroundImageItem { interface BackgroundImageItem {
id?: number id?: number
...@@ -50,7 +54,19 @@ async function getBackgroundImageList() { ...@@ -50,7 +54,19 @@ async function getBackgroundImageList() {
} }
} }
async function handleSearchImageList() {} async function handleSearchImageList(searchNameValue: string) {
if (!searchNameValue) {
getBackgroundImageList()
return
}
const res = await fetchSearchBackgroundImageList<BackgroundImageItem[]>(searchNameValue)
if (res.code === 0) {
publicBackgroundImageList.value = res.data.filter((i) => i.imageSource === 'PUBLIC')
personBackgroundImageList.value = res.data.filter((i) => i.imageSource === 'PERSON')
}
}
async function uploadImage(event: any) { async function uploadImage(event: any) {
const e = window.event || event const e = window.event || event
...@@ -78,7 +94,7 @@ async function uploadImage(event: any) { ...@@ -78,7 +94,7 @@ async function uploadImage(event: any) {
uploadLoading.value = true uploadLoading.value = true
const res = await uploadImageFile(fileName, formData).finally(() => (uploadLoading.value = false)) const res = await handleUploadBackgroundImageFile(fileName, formData).finally(() => (uploadLoading.value = false))
if (res.code === 0) { if (res.code === 0) {
getBackgroundImageList() getBackgroundImageList()
...@@ -96,9 +112,13 @@ function handleDelete(id: number) { ...@@ -96,9 +112,13 @@ function handleDelete(id: number) {
content: '是否刪除該圖片?', content: '是否刪除該圖片?',
positiveText: '確認', positiveText: '確認',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: async () => {
console.log(id) const res = await handleDeleteBackgroundImageById(id)
if (res.code === 0) {
window.$message.success('刪除成功') window.$message.success('刪除成功')
getBackgroundImageList()
}
}, },
}) })
} }
...@@ -128,13 +148,7 @@ function handleUpdateBackgroundImageType(backgroundImageType: string) { ...@@ -128,13 +148,7 @@ function handleUpdateBackgroundImageType(backgroundImageType: string) {
</NButton> </NButton>
</NButtonGroup> </NButtonGroup>
<NInput <NInput v-model:value="searchImageName" round placeholder="請輸入名稱" @input="handleSearchImageList">
v-model:value="searchImageName"
round
placeholder="請輸入名稱"
@blur="handleSearchImageList"
@keyup.enter="handleSearchImageList"
>
<template #prefix> <template #prefix>
<CustomIcon class="text-lg" icon="mingcute:search-line" /> <CustomIcon class="text-lg" icon="mingcute:search-line" />
</template> </template>
......
...@@ -59,7 +59,6 @@ watch( ...@@ -59,7 +59,6 @@ watch(
) )
onMounted(() => { onMounted(() => {
currentSelectedAudioType.value = 'cantonese'
getDigitalTimbreList() getDigitalTimbreList()
}) })
...@@ -72,6 +71,10 @@ async function getDigitalTimbreList() { ...@@ -72,6 +71,10 @@ async function getDigitalTimbreList() {
} }
} }
function handleUpdateAudioType(audioType: string) {
digitalHumanDialogueStore.humanInfo.timebreId = audioType === 'mandarin' ? '5132' : '101019'
}
async function handleSearch(value: string) { async function handleSearch(value: string) {
const res = await fetchTimbreByExample<DigitalHumanDialogueTimbreItem[]>(value) const res = await fetchTimbreByExample<DigitalHumanDialogueTimbreItem[]>(value)
if (res.code === 0) { if (res.code === 0) {
...@@ -95,14 +98,13 @@ function handleClickAudioCard(timbreId: string) { ...@@ -95,14 +98,13 @@ function handleClickAudioCard(timbreId: string) {
size="small" size="small"
:options="audioTypeList" :options="audioTypeList"
placeholder="請選擇語言" placeholder="請選擇語言"
@update:value="handleUpdateAudioType"
/> />
</div> </div>
<DigitalAudioCard <div v-show="isMandarinAudioType">
:dialogue-timbre-item="digitalTimbreValue" <DigitalAudioCard :dialogue-timbre-item="digitalTimbreValue" :show-toggle="true" @toggle="showAll = true" />
:show-toggle="isMandarinAudioType" </div>
@toggle="showAll = true"
/>
<div class="mt-4 text-lg">聲音</div> <div class="mt-4 text-lg">聲音</div>
<div class="mt-4 flex items-center gap-2"> <div class="mt-4 flex items-center gap-2">
......
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue' import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import { ImageItem } from '@/store/types/creation' import { DigitalImageItem } from '../../dialogue-type'
interface Props { interface Props {
imageItem: ImageItem imageItem: DigitalImageItem
} }
interface Emits { interface Emits {
......
...@@ -9,14 +9,14 @@ import { ...@@ -9,14 +9,14 @@ import {
fetchInfoByImageName, fetchInfoByImageName,
} from '@/apis/digital-creation' } from '@/apis/digital-creation'
import { ImageItem, ImageType } from '@/store/types/creation'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue' import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import { DigitalImageItem, ImageType } from '../../dialogue-type'
const digitalHumanDialogueStore = useDigitalHumanDialogueStore() const digitalHumanDialogueStore = useDigitalHumanDialogueStore()
const threeDImageList = ref<ImageItem[]>([]) const threeDImageList = ref<DigitalImageItem[]>([])
const twoDBoutiqueImageList = ref<ImageItem[]>([]) const twoDBoutiqueImageList = ref<DigitalImageItem[]>([])
const twoDFewShotImageList = ref<ImageItem[]>([]) const twoDFewShotImageList = ref<DigitalImageItem[]>([])
const allImageList = ref<ImageItem[]>([]) const allImageList = ref<DigitalImageItem[]>([])
const showAll = ref(false) const showAll = ref(false)
const searchImageName = ref('') const searchImageName = ref('')
...@@ -26,9 +26,9 @@ onMounted(() => { ...@@ -26,9 +26,9 @@ onMounted(() => {
async function getDigitalImageList() { async function getDigitalImageList() {
const [res1, res2, res3] = await Promise.all([ const [res1, res2, res3] = await Promise.all([
fetch3DImageList<ImageItem[]>(), fetch3DImageList<DigitalImageItem[]>(),
fetch2DBoutiqueImageList<ImageItem[]>(), fetch2DBoutiqueImageList<DigitalImageItem[]>(),
fetch2DFewShotImageList<ImageItem[]>(), fetch2DFewShotImageList<DigitalImageItem[]>(),
]) ])
res1.code === 0 && (threeDImageList.value = res1.data) res1.code === 0 && (threeDImageList.value = res1.data)
res2.code === 0 && (twoDBoutiqueImageList.value = res2.data) res2.code === 0 && (twoDBoutiqueImageList.value = res2.data)
...@@ -36,7 +36,7 @@ async function getDigitalImageList() { ...@@ -36,7 +36,7 @@ async function getDigitalImageList() {
} }
async function handleSearchImage() { async function handleSearchImage() {
const res = await fetchInfoByImageName<ImageItem[]>(searchImageName.value) const res = await fetchInfoByImageName<DigitalImageItem[]>(searchImageName.value)
if (res.code === 0) { if (res.code === 0) {
allImageList.value = res.data allImageList.value = res.data
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed, ref, watch } from 'vue'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue' import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import { fetchGetInfoByFigureId } from '@/apis/digital-human-dialogue'
const digitalHumanDialogueStore = useDigitalHumanDialogueStore() const digitalHumanDialogueStore = useDigitalHumanDialogueStore()
const figureImageUrl = ref('')
const figureId = computed(() => {
return digitalHumanDialogueStore.humanInfo.figureId
})
const backgroundImageUrl = computed(() => { const backgroundImageUrl = computed(() => {
return digitalHumanDialogueStore.backgroundInfo.backgroundUrl return digitalHumanDialogueStore.backgroundInfo.backgroundUrl
}) })
const isEmptyPreview = computed(() => {
return !figureImageUrl.value || !backgroundImageUrl.value
})
watch(
() => figureId.value,
(newValue) => {
newValue && handleGetInfoByFigureId(newValue)
},
{ immediate: true },
)
async function handleGetInfoByFigureId(figureId: string) {
const res = await fetchGetInfoByFigureId<{ imageUrl: string }>(figureId)
if (res.code === 0) {
figureImageUrl.value = res.data.imageUrl
}
}
</script> </script>
<template> <template>
<div class="h-[calc(100%-190px)] w-[calc(100%-32px)] overflow-hidden rounded-2xl bg-white"> <div class="relative h-[calc(100%-190px)] w-[calc(100%-32px)] overflow-hidden rounded-2xl bg-white">
<img v-show="backgroundImageUrl" :src="backgroundImageUrl" alt="背景圖" class="h-full w-full object-cover" /> <div
v-if="isEmptyPreview"
class="flex h-full w-full select-none items-center justify-center text-xs text-[#84868c]"
>
請你在右側選擇一個數字人
</div>
<img
v-show="backgroundImageUrl"
:src="backgroundImageUrl"
alt="背景圖"
class="absolute left-0 top-0 h-full w-full object-cover"
/>
<div class="absolute left-0 top-0 w-1/2">
<img v-show="figureImageUrl" :src="figureImageUrl" alt="數字人" class="h-full w-full" />
</div>
</div> </div>
</template> </template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { computed } from 'vue' import { computed } from 'vue'
import CustomModal from '@/components/custom-modal/custom-modal.vue' import CustomModal from '@/components/custom-modal/custom-modal.vue'
import { AI_INDEX_URLS } from '@/config/base-url' import { AI_INDEX_URLS } from '@/config/base-url'
import { copyToClip } from '@/utils/copy'
interface Props { interface Props {
isShowModal: boolean isShowModal: boolean
...@@ -33,6 +34,7 @@ const showModal = computed({ ...@@ -33,6 +34,7 @@ const showModal = computed({
}) })
function handleCopyLink() { function handleCopyLink() {
copyToClip(shareLink.value)
window.$message.success('複製成功') window.$message.success('複製成功')
} }
</script> </script>
......
...@@ -39,6 +39,7 @@ function handleUpdatePerambleStatus(isOpenPeramble: boolean) { ...@@ -39,6 +39,7 @@ function handleUpdatePerambleStatus(isOpenPeramble: boolean) {
</template> </template>
<NInput <NInput
v-show="digitalHumanDialogueSystemInfo.perambleStatus === 'Y'"
v-model:value="digitalHumanDialogueSystemInfo.preamble" v-model:value="digitalHumanDialogueSystemInfo.preamble"
type="textarea" type="textarea"
placeholder="請描述角色的開場話術" placeholder="請描述角色的開場話術"
......
...@@ -43,6 +43,7 @@ function handleUpdateRefuseAnswerStatus(isOpenRefuseAnswer: boolean) { ...@@ -43,6 +43,7 @@ function handleUpdateRefuseAnswerStatus(isOpenRefuseAnswer: boolean) {
</template> </template>
<NInput <NInput
v-show="digitalHumanDialogueSystemInfo.chitchatStatus === 'Y'"
v-model:value="digitalHumanDialogueSystemInfo.chitchat" v-model:value="digitalHumanDialogueSystemInfo.chitchat"
type="textarea" type="textarea"
placeholder="請描述角色進行閒聊的範圍" placeholder="請描述角色進行閒聊的範圍"
...@@ -76,6 +77,7 @@ function handleUpdateRefuseAnswerStatus(isOpenRefuseAnswer: boolean) { ...@@ -76,6 +77,7 @@ function handleUpdateRefuseAnswerStatus(isOpenRefuseAnswer: boolean) {
</template> </template>
<NInput <NInput
v-show="digitalHumanDialogueSystemInfo.refuseAnswerStatus === 'Y'"
v-model:value="digitalHumanDialogueSystemInfo.refuseAnswer" v-model:value="digitalHumanDialogueSystemInfo.refuseAnswer"
type="textarea" type="textarea"
placeholder="請描述角色拒絕回答的範圍" placeholder="請描述角色拒絕回答的範圍"
......
...@@ -23,6 +23,10 @@ const backgroundImageUrl = computed(() => { ...@@ -23,6 +23,10 @@ const backgroundImageUrl = computed(() => {
return digitalHumanDialogueStore.backgroundInfo.backgroundUrl return digitalHumanDialogueStore.backgroundInfo.backgroundUrl
}) })
const isEmptyPreview = computed(() => {
return !figureImageUrl.value || !backgroundImageUrl.value
})
async function handleGetInfoByFigureId(figureId: string) { async function handleGetInfoByFigureId(figureId: string) {
const res = await fetchGetInfoByFigureId<{ imageUrl: string }>(figureId) const res = await fetchGetInfoByFigureId<{ imageUrl: string }>(figureId)
...@@ -34,6 +38,13 @@ async function handleGetInfoByFigureId(figureId: string) { ...@@ -34,6 +38,13 @@ async function handleGetInfoByFigureId(figureId: string) {
<template> <template>
<div class="relative h-[667px] w-[375px] overflow-hidden rounded-2xl bg-white"> <div class="relative h-[667px] w-[375px] overflow-hidden rounded-2xl bg-white">
<div
v-if="isEmptyPreview"
class="flex h-full w-full select-none items-center justify-center text-xs text-[#84868c]"
>
請你在右側選擇一個數字人
</div>
<img <img
v-show="backgroundImageUrl" v-show="backgroundImageUrl"
:src="backgroundImageUrl" :src="backgroundImageUrl"
......
...@@ -9,3 +9,17 @@ export interface DigitalHumanDialogueTimbreItem { ...@@ -9,3 +9,17 @@ export interface DigitalHumanDialogueTimbreItem {
iconUrl: string iconUrl: string
isAudioPlay: boolean isAudioPlay: boolean
} }
export enum ImageType {
THREE_D = 'THREE_D',
TWO_D_BOUTIQUE = 'TWO_D_BOUTIQUE',
TWO_D_FEW_SHOT = 'TWO_D_FEW_SHOT',
}
export interface DigitalImageItem {
id: number
imageType: ImageType
imageName: string
figureId: string
imageUrl: string
}
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import CustomIcon from '@/components/custom-icon/custom-icon.vue' import CustomIcon from '@/components/custom-icon/custom-icon.vue'
import CreateDigitalHumanDialogueModal from '../components/create-digital-human-dialogue-modal.vue'
import PublishDigitalHumanDialogueModal from '../components/publish-digital-human-dialogue-modal.vue' import PublishDigitalHumanDialogueModal from '../components/publish-digital-human-dialogue-modal.vue'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue' import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import {
fetchGetDigitalHumanDialogueConfigByConfigId,
fetchPublishDigitalHumanDialogue,
fetchSaveDigitalHumanDialogueConfig,
} from '@/apis/digital-human-dialogue'
import { DigitalHumanDialogueConfig } from '@/store/types/digital-human-dialogue'
const router = useRouter() const router = useRouter()
const digitalHumanDialogueStore = useDigitalHumanDialogueStore() const digitalHumanDialogueStore = useDigitalHumanDialogueStore()
const isEditDigitalHumanDialogueTitle = ref(false) const currentConfigId = ref('')
const digitalHumanDialogueTitle = ref(digitalHumanDialogueStore.baseInfo.title) const digitalHumanDialogueTitle = ref(digitalHumanDialogueStore.baseInfo.title)
const isEditDigitalHumanDialogueTitle = ref(false)
const isShowPublishDialogueModal = ref(false) const isShowPublishDialogueModal = ref(false)
const isUnSavedDigitalHumanDialogueConfig = ref(false)
const digitalHumanDialogueConfig = computed(() => {
return digitalHumanDialogueStore.$state
})
watch(
() => digitalHumanDialogueConfig.value,
() => {
isUnSavedDigitalHumanDialogueConfig.value = true
},
{ deep: true },
)
onMounted(() => {
if (router.currentRoute.value.params.configId) {
currentConfigId.value = router.currentRoute.value.params.configId as string
handleGetDigitalHumanDialogueConfig()
return
}
const showExportModal = ref(false) router.replace({ name: 'Root' })
})
function handleBackHome() { async function handleGetDigitalHumanDialogueConfig() {
fetchGetDigitalHumanDialogueConfigByConfigId<DigitalHumanDialogueConfig>(currentConfigId.value)
.then(async (res) => {
if (res.code === 0) {
await digitalHumanDialogueStore.updateDigitalHumanDialogue(res.data)
isUnSavedDigitalHumanDialogueConfig.value = false
}
})
.catch(() => {
router.replace({ name: 'Home' }) router.replace({ name: 'Home' })
})
}
function handleBack() {
if (isUnSavedDigitalHumanDialogueConfig.value) {
window.$dialog.info({
title: '提示',
content: '請保存修改內容後再返回上一級頁面',
negativeText: '直接返回',
positiveText: '保 存',
onNegativeClick: () => {
router.back()
},
onPositiveClick: async () => {
const res = await fetchSaveDigitalHumanDialogueConfig(digitalHumanDialogueConfig.value)
if (res.code === 0) {
window.$message.success('保存成功')
router.back()
}
},
})
return
}
router.back()
} }
function handleShowEditDigitalHumanDialogueTitle() { function handleShowEditDigitalHumanDialogueTitle() {
isEditDigitalHumanDialogueTitle.value = true isEditDigitalHumanDialogueTitle.value = true
digitalHumanDialogueTitle.value = digitalHumanDialogueStore.baseInfo.title
} }
function handleSaveDigitalHumanDialogueTitle() { async function handleSaveDigitalHumanDialogueTitle() {
isEditDigitalHumanDialogueTitle.value = false isEditDigitalHumanDialogueTitle.value = false
if (!digitalHumanDialogueTitle.value) { if (!digitalHumanDialogueTitle.value) {
...@@ -35,25 +96,39 @@ function handleSaveDigitalHumanDialogueTitle() { ...@@ -35,25 +96,39 @@ function handleSaveDigitalHumanDialogueTitle() {
return return
} }
const res = await fetchSaveDigitalHumanDialogueConfig(digitalHumanDialogueConfig.value)
if (res.code === 0) {
window.$message.success('保存成功') window.$message.success('保存成功')
isUnSavedDigitalHumanDialogueConfig.value = false
}
} }
function handleSaveDigitalHumanDialogueConfig() { async function handleSaveDigitalHumanDialogueConfig() {
const res = await fetchSaveDigitalHumanDialogueConfig(digitalHumanDialogueConfig.value)
if (res.code === 0) {
window.$message.success('保存成功') window.$message.success('保存成功')
isUnSavedDigitalHumanDialogueConfig.value = false
}
} }
function handlePublishDigitalHumanDialogue() { async function handlePublishDigitalHumanDialogue() {
const res = await fetchPublishDigitalHumanDialogue(currentConfigId.value)
if (res.code === 0) {
isShowPublishDialogueModal.value = true isShowPublishDialogueModal.value = true
window.$message.success('發佈成功') window.$message.success('發佈成功')
}
} }
</script> </script>
<template> <template>
<header class="flex h-14 items-center justify-between bg-white px-4"> <header class="flex h-14 items-center justify-between bg-white px-4">
<div class="flex items-center"> <div class="flex items-center">
<CustomIcon class="mr-4 cursor-pointer text-lg" icon="mingcute:left-line" @click="handleBackHome" /> <CustomIcon class="mr-4 cursor-pointer text-lg" icon="mingcute:left-line" @click="handleBack" />
<div v-show="!isEditDigitalHumanDialogueTitle" class="flex items-center"> <div v-show="!isEditDigitalHumanDialogueTitle" class="flex items-center">
<span class="font-500">{{ digitalHumanDialogueTitle }}</span> <span class="font-500">{{ digitalHumanDialogueConfig.baseInfo.title }}</span>
<CustomIcon <CustomIcon
icon="bxs:edit" icon="bxs:edit"
class="text-theme-color ml-1 cursor-pointer text-lg" class="text-theme-color ml-1 cursor-pointer text-lg"
...@@ -75,7 +150,13 @@ function handlePublishDigitalHumanDialogue() { ...@@ -75,7 +150,13 @@ function handlePublishDigitalHumanDialogue() {
<div class="flex items-center"> <div class="flex items-center">
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<NButton class="w-[72px]! h-[32px]! rounded-md!" @click="handleSaveDigitalHumanDialogueConfig"> 保存 </NButton> <NButton
class="w-[72px]! h-[32px]! rounded-md!"
:disabled="!isUnSavedDigitalHumanDialogueConfig"
@click="handleSaveDigitalHumanDialogueConfig"
>
保存
</NButton>
<NButton class="w-[72px]! h-[32px]! rounded-md!" type="info" @click="handlePublishDigitalHumanDialogue"> <NButton class="w-[72px]! h-[32px]! rounded-md!" type="info" @click="handlePublishDigitalHumanDialogue">
發佈 發佈
</NButton> </NButton>
...@@ -83,12 +164,6 @@ function handlePublishDigitalHumanDialogue() { ...@@ -83,12 +164,6 @@ function handlePublishDigitalHumanDialogue() {
</div> </div>
</header> </header>
<CreateDigitalHumanDialogueModal
v-model:is-show-modal="showExportModal"
modal-title="新建對話"
:btn-loading="false"
/>
<PublishDigitalHumanDialogueModal <PublishDigitalHumanDialogueModal
v-model:is-show-modal="isShowPublishDialogueModal" v-model:is-show-modal="isShowPublishDialogueModal"
modal-title="發佈詳情" modal-title="發佈詳情"
......
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue'
import HeaderBar from './header-bar.vue' import HeaderBar from './header-bar.vue'
import MainContent from './main-content.vue' import MainContent from './main-content.vue'
import SideBar from './side-bar.vue' import SideBar from './side-bar.vue'
onMounted(() => {})
</script> </script>
<template> <template>
......
...@@ -59,10 +59,13 @@ onMounted(() => { ...@@ -59,10 +59,13 @@ onMounted(() => {
async function handleGetDiaglogList() { async function handleGetDiaglogList() {
dialogueTableLoading.value = true dialogueTableLoading.value = true
const res = await fetchGetDigitalHumanDialogueList<DiaglogueTableItem[]>(searchQuery.value) const res = await fetchGetDigitalHumanDialogueList<DiaglogueTableItem[]>(searchQuery.value, {
pagingInfo: pagingInfo.value,
})
if (res.code === 0) { if (res.code === 0) {
digitalHumanDialogueList.value = res.data digitalHumanDialogueList.value = res.data
pagingInfo.value = res.pagingInfo as PaginationInfo
dialogueTableLoading.value = false dialogueTableLoading.value = false
} }
} }
...@@ -79,6 +82,7 @@ async function handleMultiDeleteDiaglogueConfig() { ...@@ -79,6 +82,7 @@ async function handleMultiDeleteDiaglogueConfig() {
if (res.code === 0) { if (res.code === 0) {
window.$message.success('刪除成功') window.$message.success('刪除成功')
checkedConfigIdList.value = [] checkedConfigIdList.value = []
digitalHumanDialogueList.value.length === 1 && (pagingInfo.value.pageNo = pagingInfo.value.pageNo - 1)
await handleGetDiaglogList() await handleGetDiaglogList()
} }
}, },
...@@ -190,7 +194,7 @@ function handleDeleteDiaglogueConfig(configId: string) { ...@@ -190,7 +194,7 @@ function handleDeleteDiaglogueConfig(configId: string) {
const res = await fetchDelectDigitalHumanDialogueConfigByConfigId(configId) const res = await fetchDelectDigitalHumanDialogueConfigByConfigId(configId)
if (res.code === 0) { if (res.code === 0) {
window.$message.success('刪除成功') window.$message.success('刪除成功')
// agentAppList.value.length === 1 && (pagingInfo.value.pageNo = pagingInfo.value.pageNo - 1) digitalHumanDialogueList.value.length === 1 && (pagingInfo.value.pageNo = pagingInfo.value.pageNo - 1)
await handleGetDiaglogList() await handleGetDiaglogList()
} }
}, },
...@@ -201,6 +205,17 @@ function handleShowPubishDetailModal(configId: string) { ...@@ -201,6 +205,17 @@ function handleShowPubishDetailModal(configId: string) {
isShowPublishDigitalHumanDialogueModal.value = true isShowPublishDigitalHumanDialogueModal.value = true
publishDetailConfigId.value = configId publishDetailConfigId.value = configId
} }
function handleGetDialogueListUpdatePageNo(pageNo: number) {
pagingInfo.value.pageNo = pageNo
handleGetDiaglogList()
}
function handleGetDialogueListUpdatePageSize(pageSize: number) {
pagingInfo.value.pageNo = 1
pagingInfo.value.pageSize = pageSize
handleGetDiaglogList()
}
</script> </script>
<template> <template>
...@@ -244,6 +259,7 @@ function handleShowPubishDetailModal(configId: string) { ...@@ -244,6 +259,7 @@ function handleShowPubishDetailModal(configId: string) {
</div> </div>
</div> </div>
<div :style="{ height: tableContentY + 48 + 'px' }">
<NDataTable <NDataTable
:loading="dialogueTableLoading" :loading="dialogueTableLoading"
:bordered="false" :bordered="false"
...@@ -264,9 +280,14 @@ function handleShowPubishDetailModal(configId: string) { ...@@ -264,9 +280,14 @@ function handleShowPubishDetailModal(configId: string) {
</div> </div>
</template> </template>
</NDataTable> </NDataTable>
</div>
<div v-show="isShowPagination" class="mt-5 flex w-full justify-end"> <div v-show="isShowPagination" class="mt-5 flex w-full justify-end">
<CustomPagination :paging-info="pagingInfo" /> <CustomPagination
:paging-info="pagingInfo"
@update-page-no="handleGetDialogueListUpdatePageNo"
@update-page-size="handleGetDialogueListUpdatePageSize"
/>
</div> </div>
</div> </div>
......
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