Commit cc768501 authored by nick zheng's avatar nick zheng

chore: 草稿箱、我的作品联调和对话配置调整

parent bfc4695a
...@@ -40,7 +40,7 @@ export function deleteBackgroundImageById<T>(id: number) { ...@@ -40,7 +40,7 @@ export function deleteBackgroundImageById<T>(id: number) {
// 根据人物名称分页获取人物信息 // 根据人物名称分页获取人物信息
export function fetchInfoByImageName<T>(imageName: string) { export function fetchInfoByImageName<T>(imageName: string) {
return request.post<T>(`/bizDigitalHumanImageRest/findByImageName.json?imageName=${imageName}`, { return request.post<T>(`/bizDigitalHumanImageRest/findDigitalHumanImageByImageName.json?imageName=${imageName}`, {
pagingInfo: { pageNo: 1, pageSize: 1000 }, pagingInfo: { pageNo: 1, pageSize: 1000 },
}) })
} }
......
...@@ -54,7 +54,7 @@ export function handleUploadBackgroundImageFile<T>(imageName: string, formData: ...@@ -54,7 +54,7 @@ export function handleUploadBackgroundImageFile<T>(imageName: string, formData:
} }
// 根据背景图id删除背景图 // 根据背景图id删除背景图
export function handleDeleteBackgroundImageById<T>(id: number) { export function handleDeleteBackgroundImageById<T>(id: string) {
return request.post<T>(`/bizDigitalHumanMemberImageRest/deletedById.json?id=${id}`) return request.post<T>(`/bizDigitalHumanMemberImageRest/deletedById.json?id=${id}`)
} }
......
import { request } from '@/utils/request' import { request } from '@/utils/request'
export function fetchDraftsList<T>(token: string, queryParams: { pagingInfo: any }) { // 获取草稿列表
return request.post<T>( export function fetchDraftsList<T>(payload: object) {
'/bizDigitalHumanMemberDraftConfigRest/getList.json', return request.post<T>(`/bizDigitalHumanMemberDraftConfigRest/getList.json`, payload)
{}, }
{
headers: { // 保存更新用户草稿
'X-Request-Token': token, export function fetchSaveDraftConfig<T>(payload: object) {
}, return request.post<T>('/bizDigitalHumanMemberDraftConfigRest/saveOrUpdate.json', payload)
params: queryParams.pagingInfo, }
},
) // 通过id删除用户草稿
export function fetchDeleteDraftConfigById<T>(id: string) {
return request.post<T>(`/bizDigitalHumanMemberDraftConfigRest/deletedById.json?id=${id}`)
} }
export function fetchRecentCreationList<T>(token: string) { export function fetchRecentCreationList<T>(token: string) {
......
import { request } from '@/utils/request' import { request } from '@/utils/request'
export function fetchOpusList<T>(token: string, queryParams: { pagingInfo: any }) { export function fetchGetTaskList<T>(payload: object) {
return request.post<T>( return request.post<T>('/bizDigitalHumanMemberTaskStatusRest/getMemberTaskStatusList.json', payload)
'/bizDigitalHumanMemberTaskStatusRest/getMemberTaskStatusList.json',
{},
{
headers: {
'X-Request-Token': token,
},
params: queryParams.pagingInfo,
},
)
} }
...@@ -113,7 +113,7 @@ function handleDelete(id: number) { ...@@ -113,7 +113,7 @@ function handleDelete(id: number) {
positiveText: '確認', positiveText: '確認',
negativeText: '取消', negativeText: '取消',
onPositiveClick: async () => { onPositiveClick: async () => {
const res = await handleDeleteBackgroundImageById(id) const res = await handleDeleteBackgroundImageById(`${id}`)
if (res.code === 0) { if (res.code === 0) {
window.$message.success('刪除成功') window.$message.success('刪除成功')
......
...@@ -19,6 +19,7 @@ const twoDFewShotImageList = ref<DigitalImageItem[]>([]) ...@@ -19,6 +19,7 @@ const twoDFewShotImageList = ref<DigitalImageItem[]>([])
const allImageList = ref<DigitalImageItem[]>([]) const allImageList = ref<DigitalImageItem[]>([])
const showAll = ref(false) const showAll = ref(false)
const searchImageName = ref('') const searchImageName = ref('')
const currentImageType = ref<ImageType>(ImageType.THREE_D)
onMounted(() => { onMounted(() => {
getDigitalImageList() getDigitalImageList()
...@@ -38,7 +39,7 @@ async function getDigitalImageList() { ...@@ -38,7 +39,7 @@ async function getDigitalImageList() {
async function handleSearchImage() { async function handleSearchImage() {
const res = await fetchInfoByImageName<DigitalImageItem[]>(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.filter((digitalImageItem) => digitalImageItem.imageType === currentImageType.value)
} }
} }
...@@ -47,6 +48,7 @@ function handleClickDigitalImage(figureId: string) { ...@@ -47,6 +48,7 @@ function handleClickDigitalImage(figureId: string) {
} }
function handleClickAll(imageType: ImageType) { function handleClickAll(imageType: ImageType) {
currentImageType.value = imageType
switch (imageType) { switch (imageType) {
case ImageType.THREE_D: case ImageType.THREE_D:
allImageList.value = threeDImageList.value allImageList.value = threeDImageList.value
...@@ -119,13 +121,7 @@ function handleClickAll(imageType: ImageType) { ...@@ -119,13 +121,7 @@ function handleClickAll(imageType: ImageType) {
</template> </template>
返回 返回
</NButton> </NButton>
<NInput <NInput v-model:value="searchImageName" round placeholder="輸入名稱搜索" @input="handleSearchImage">
v-model:value="searchImageName"
round
placeholder="輸入名稱搜索"
@blur="handleSearchImage"
@keyup.enter="handleSearchImage"
>
<template #prefix> <template #prefix>
<CustomIcon class="text-lg" icon="mingcute:search-line" /> <CustomIcon class="text-lg" icon="mingcute:search-line" />
</template> </template>
......
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, onUnmounted, 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 PublishDigitalHumanDialogueModal from '../components/publish-digital-human-dialogue-modal.vue' import PublishDigitalHumanDialogueModal from '../components/publish-digital-human-dialogue-modal.vue'
...@@ -45,6 +45,10 @@ onMounted(() => { ...@@ -45,6 +45,10 @@ onMounted(() => {
router.replace({ name: 'Root' }) router.replace({ name: 'Root' })
}) })
onUnmounted(() => {
digitalHumanDialogueStore.resetDigitalHumanDialogue()
})
async function handleGetDigitalHumanDialogueConfig() { async function handleGetDigitalHumanDialogueConfig() {
fetchGetDigitalHumanDialogueConfigByConfigId<DigitalHumanDialogueConfig>(currentConfigId.value) fetchGetDigitalHumanDialogueConfigByConfigId<DigitalHumanDialogueConfig>(currentConfigId.value)
.then(async (res) => { .then(async (res) => {
......
...@@ -38,7 +38,7 @@ export function createDiaglogueTableColumn( ...@@ -38,7 +38,7 @@ export function createDiaglogueTableColumn(
}, },
{ {
title: '編輯時間', title: '最後編輯時間',
key: 'modifiedTime', key: 'modifiedTime',
align: 'left', align: 'left',
ellipsis: { ellipsis: {
...@@ -75,7 +75,7 @@ export function createDiaglogueTableColumn( ...@@ -75,7 +75,7 @@ export function createDiaglogueTableColumn(
value: row.isOpen === 'Y', value: row.isOpen === 'Y',
onUpdateValue: () => handleDiaglogueAction('updateOpen', row.configId, row), onUpdateValue: () => handleDiaglogueAction('updateOpen', row.configId, row),
}, },
{}, { checked: () => '啓用', unchecked: () => '停用' },
) )
}, },
}, },
......
...@@ -41,7 +41,7 @@ const showModal = computed({ ...@@ -41,7 +41,7 @@ const showModal = computed({
watch( watch(
() => props.configTitle, () => props.configTitle,
(newValue) => { (newValue) => {
digitalHumanDialogueFormData.title = newValue + '副本' digitalHumanDialogueFormData.title = (newValue + '副本').slice(0, 30)
}, },
) )
...@@ -60,6 +60,7 @@ function handleAddDigitalHumanDialogue() { ...@@ -60,6 +60,7 @@ function handleAddDigitalHumanDialogue() {
:title="modalTitle" :title="modalTitle"
:width="448" :width="448"
:height="220" :height="220"
:btn-loading="btnLoading"
@confirm="handleAddDigitalHumanDialogue" @confirm="handleAddDigitalHumanDialogue"
> >
<template #content> <template #content>
......
...@@ -66,6 +66,7 @@ async function handleGetDiaglogList() { ...@@ -66,6 +66,7 @@ async function handleGetDiaglogList() {
if (res.code === 0) { if (res.code === 0) {
digitalHumanDialogueList.value = res.data digitalHumanDialogueList.value = res.data
pagingInfo.value = res.pagingInfo as PaginationInfo pagingInfo.value = res.pagingInfo as PaginationInfo
checkedConfigIdList.value = []
dialogueTableLoading.value = false dialogueTableLoading.value = false
} }
} }
...@@ -91,6 +92,7 @@ async function handleMultiDeleteDiaglogueConfig() { ...@@ -91,6 +92,7 @@ async function handleMultiDeleteDiaglogueConfig() {
function handleClearSearchQuery() { function handleClearSearchQuery() {
searchQuery.value = '' searchQuery.value = ''
pagingInfo.value.pageNo = 1
handleGetDiaglogList() handleGetDiaglogList()
} }
...@@ -173,12 +175,15 @@ async function handleAddDigitalHumanDialogue(title: string) { ...@@ -173,12 +175,15 @@ async function handleAddDigitalHumanDialogue(title: string) {
copyDiaglogueConfig.value!.baseInfo.configId = '' copyDiaglogueConfig.value!.baseInfo.configId = ''
copyDiaglogueConfig.value!.baseInfo.title = title copyDiaglogueConfig.value!.baseInfo.title = title
copyDiaglogueConfig.value!.baseInfo.publishStatus = 'N'
copyDiaglogueConfig.value!.baseInfo.isOpen = 'N'
const res = await fetchSaveDigitalHumanDialogueConfig(copyDiaglogueConfig.value!).finally( const res = await fetchSaveDigitalHumanDialogueConfig(copyDiaglogueConfig.value!).finally(
() => (editDigitalHumanDialogueBtnLoading.value = false), () => (editDigitalHumanDialogueBtnLoading.value = false),
) )
if (res.code === 0) { if (res.code === 0) {
window.$message.success('提交成功')
isShowEditDigitalHumanDialogueModal.value = false isShowEditDigitalHumanDialogueModal.value = false
await handleGetDiaglogList() await handleGetDiaglogList()
} }
...@@ -219,7 +224,7 @@ function handleGetDialogueListUpdatePageSize(pageSize: number) { ...@@ -219,7 +224,7 @@ function handleGetDialogueListUpdatePageSize(pageSize: number) {
</script> </script>
<template> <template>
<div ref="pageContentWrapRef" class="h-full w-full overflow-auto rounded-[16px] bg-white p-6"> <div ref="pageContentWrapRef" class="h-full w-full overflow-y-hidden rounded-[16px] bg-white p-6">
<p class="mb-6 select-none text-lg text-[#333]">我的對話</p> <p class="mb-6 select-none text-lg text-[#333]">我的對話</p>
<div class="flex justify-between"> <div class="flex justify-between">
......
import { h } from 'vue'
import { DataTableColumns, NEllipsis } from 'naive-ui'
import { formatDateTime } from '@/utils/date-formatter'
import { DraftConfig } from '@/store/types/creation'
export function createDarftTableColumns({
handleDeleteDraft,
handleEditDraft,
handleCreatCopyDraft,
}: {
handleDeleteDraft: (rowData: DraftConfig) => void
handleEditDraft: (rowData: DraftConfig) => void
handleCreatCopyDraft: (rowData: DraftConfig) => void
}): DataTableColumns<DraftConfig> {
return [
{
type: 'selection',
fixed: 'left',
},
{
title: '草稿名稱',
key: 'draftName',
align: 'left',
width: '400',
render(row) {
return h('div', { class: 'flex items-center' }, [
h(
'div',
{
style: { width: '64px', height: '36px', marginRight: '10px' },
class: 'flex items-center justify-center overflow-hidden relative',
},
[
row.coverUrl
? h('img', {
src: row.coverUrl,
alt: '作品圖',
class: 'h-full object-cover',
})
: h('div', { class: 'border w-full h-full text-xs flex items-center justify-center' }, '暫無圖片'),
],
),
h(NEllipsis, {}, { default: () => row.draftName || '--' }),
])
},
},
{
title: '類型',
key: 'type',
width: '180',
render(row) {
const typeMap = {
IMAGE_VIDEO: '照片數字人',
BASE_VIDEO: '數字人生成',
ADVANCED_VIDEO: '高級數字人',
}
return h('span', {}, typeMap[row.taskType] || '--')
},
},
{
title: '最後編輯時間',
key: 'modifiedTime',
width: 200,
render(row) {
return h('span', {}, row.modifiedTime ? formatDateTime(row.modifiedTime) : '--')
},
},
{
title: '操作',
key: 'operation',
width: 250,
render(row) {
return h('div', {}, [
h(
'span',
{
onClick: () => handleEditDraft(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'編輯',
),
h(
'span',
{
onClick: () => handleCreatCopyDraft(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'創建副本',
),
h(
h(
'span',
{
onClick: () => handleDeleteDraft(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'删除',
),
),
])
},
},
]
}
<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue'
import { FormInst } from 'naive-ui'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
interface Props {
isShowModal: boolean
draftName: string
btnLoading: boolean
modalTitle: string
}
interface Emits {
(e: 'update:isShowModal', value: boolean): void
(e: 'comfirm', value: string): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const digitalHumanDraftFormRef = ref<FormInst | null>(null)
const digitalHumanDraftFormData = reactive({
draftName: '',
})
const digitalHumanDraftFormRules = {
draftName: [{ required: true, message: '請輸入名稱', trigger: 'blur' }],
}
const showModal = computed({
get() {
return props.isShowModal
},
set(value: boolean) {
emit('update:isShowModal', value)
},
})
watch(
() => props.draftName,
(newValue) => {
digitalHumanDraftFormData.draftName = (newValue + '副本').slice(0, 30)
},
)
function handleAddDigitalHumanDialogue() {
digitalHumanDraftFormRef.value?.validate((errors) => {
if (!errors) {
emit('comfirm', digitalHumanDraftFormData.draftName)
}
})
}
</script>
<template>
<CustomModal
v-model:is-show="showModal"
:title="modalTitle"
:width="448"
:height="220"
:btn-loading="btnLoading"
@confirm="handleAddDigitalHumanDialogue"
>
<template #content>
<NForm
ref="digitalHumanDraftFormRef"
:model="digitalHumanDraftFormData"
:rules="digitalHumanDraftFormRules"
label-placement="left"
show-require-mark
label-width="80px"
class="pt-2"
>
<NFormItem label="名稱" path="draftName">
<NInput
v-model:value="digitalHumanDraftFormData.draftName"
placeholder="請輸入名稱"
:maxlength="30"
show-count
/>
</NFormItem>
</NForm>
</template>
</CustomModal>
</template>
<style lang="scss" scoped>
:deep(.n-input) {
border-radius: 4px;
.n-input-wrapper {
font-size: 12px;
}
}
</style>
This diff is collapsed.
...@@ -3,6 +3,13 @@ import { fetchUniversalCurrency } from '@/apis/user' ...@@ -3,6 +3,13 @@ import { fetchUniversalCurrency } from '@/apis/user'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import { Right } from '@icon-park/vue-next' import { Right } from '@icon-park/vue-next'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import CreateDigitalHumanDialogueModal, {
DigitalHumanDialogueForm,
} from '@/views/dialogue-detail/components/create-digital-human-dialogue-modal.vue'
import { useDigitalHumanDialogueStore } from '@/store/modules/digital-human-dialogue'
import { DigitalHumanDialogueConfig } from '@/store/types/digital-human-dialogue'
import { fetchSaveDigitalHumanDialogueConfig } from '@/apis/digital-human-dialogue'
import { useRouter } from 'vue-router'
const UniversalCurrency = ref() const UniversalCurrency = ref()
const userStore = useUserStore() const userStore = useUserStore()
...@@ -26,6 +33,30 @@ function handleRechargeCurrency() { ...@@ -26,6 +33,30 @@ function handleRechargeCurrency() {
onMounted(() => { onMounted(() => {
getUniversalCurrency() getUniversalCurrency()
}) })
const digitalHumanDialogueStore = useDigitalHumanDialogueStore()
const router = useRouter()
const isShow = ref(false)
function handleShowModal() {
isShow.value = true
}
async function handleCreateDigitalHumanDialogue(digitalHumanDialogueForm: DigitalHumanDialogueForm) {
digitalHumanDialogueStore.resetDigitalHumanDialogue()
const payload: DigitalHumanDialogueConfig = JSON.parse(JSON.stringify(digitalHumanDialogueStore.$state))
payload.baseInfo.title = digitalHumanDialogueForm.title
payload.baseInfo.pageLayout = digitalHumanDialogueForm.pageLayout
const res = await fetchSaveDigitalHumanDialogueConfig<DigitalHumanDialogueConfig>(payload)
if (res.code === 0) {
router.push({ name: 'DialogueDetail', params: { configId: res.data.baseInfo.configId } })
isShow.value = false
}
}
</script> </script>
<template> <template>
...@@ -40,7 +71,7 @@ onMounted(() => { ...@@ -40,7 +71,7 @@ onMounted(() => {
</div> </div>
<div <div
class="text-align-center mt-[20px] h-[35px] w-[90px] cursor-pointer rounded-[6px] bg-[#fff3] text-[14px] leading-[35px] text-[#fff] hover:bg-[#fff]/[.4]" class="text-align-center mt-[20px] h-[35px] w-[90px] cursor-pointer rounded-[6px] bg-[#fff3] text-[14px] leading-[35px] text-[#fff] hover:bg-[#fff]/[.4]"
@click="handleGoToCreation" @click="handleShowModal"
> >
<span>立即創作</span> <span>立即創作</span>
</div> </div>
...@@ -109,4 +140,11 @@ onMounted(() => { ...@@ -109,4 +140,11 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
<CreateDigitalHumanDialogueModal
v-model:is-show-modal="isShow"
modal-title="测试"
:btn-loading="false"
@comfirm="handleCreateDigitalHumanDialogue"
/>
</template> </template>
import { formatDateTime } from '@/utils/date-formatter'
import { DataTableColumns, NEllipsis, NPopconfirm } from 'naive-ui'
import { h } from 'vue'
type TaskType = 'IMAGE_VIDEO' | 'BASE_VIDEO' | 'ADVANCED_VIDEO'
type TaskStateType = 'SUBMIT' | 'GENERATING' | 'SUCCESS' | 'FAILED'
export interface TaskItem {
id: number
taskCoverUrl: string
baiduTaskId: string
taskName: string
callbackUrl: string
taskType: TaskType
status: TaskStateType
videoUrl: string
duration: number
subtitleFileUrl: null
createTime: null
updateTime: string
modifiedTime: Date
}
export function createOpusColumns({
handleOpusDownload,
handleOpusDeleteRow,
handleOpusExamine,
handleOpusEditing,
}: {
handleOpusDownload: (rowData: TaskItem) => void
handleOpusDeleteRow: (rowData: TaskItem) => void
handleOpusExamine: (rowData: TaskItem) => void
handleOpusEditing: (rowData: TaskItem) => void
}): DataTableColumns<TaskItem> {
return [
{
type: 'selection',
fixed: 'left',
},
{
title: '作品名稱',
key: 'opusName',
width: 320,
render(row) {
return h('div', { class: 'flex items-center' }, [
h(
'div',
{
style: { width: '111px', height: '55px' },
class: 'mr-[10px] flex items-center justify-center overflow-hidden relative',
},
[
h('img', {
src: row.taskCoverUrl,
alt: '作品圖片',
class: 'h-full object-cover',
}),
],
),
h(NEllipsis, {}, { default: () => row.taskName || '--' }),
])
},
},
{
title: '狀態',
key: 'state',
width: 150,
render(row) {
const stateMap = {
SUBMIT: { text: '待生成', color: '#BBBBBB' },
GENERATING: { text: '生成中', color: '#1684FC' },
SUCCESS: { text: '生成成功', color: '#26A50E' },
FAILED: { text: '生成失敗', color: '#CB5656' },
}
const state = stateMap[row.status] || { text: '', color: '#CCCCCC' } // 默认灰色
return h('div', { class: 'flex items-center ' }, [
h('div', {
class: 'w-[10px] h-[10px] rounded-[25px] mr-18px reading-[22px]',
style: { backgroundColor: state.color },
}),
h('span', {}, state.text),
])
},
},
{
title: '類型',
key: 'type',
width: 120,
render(row) {
const typeMap = {
IMAGE_VIDEO: '照片數字人',
BASE_VIDEO: '數字人生成',
ADVANCED_VIDEO: '高級數字人',
}
return h('span', {}, typeMap[row.taskType] || '')
},
},
{
title: '視頻時長',
key: 'videoDuration',
width: 120,
render(row) {
return h('span', {}, row.duration ? row.duration : '--')
},
},
{
title: '完成時間',
key: 'completionTime',
width: 180,
render(row) {
return h('span', {}, row.modifiedTime ? formatDateTime(row.modifiedTime) : '--')
},
},
{
title: '操作',
key: 'operation',
width: 240,
fixed: 'right',
render(row) {
return h('div', { class: 'operation-buttons' }, [
h(
'span',
{
onClick: () => handleOpusExamine(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'查看',
),
h(
'span',
{
onClick: () => handleOpusDownload(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'下載',
),
h(
'span',
{
onClick: () => handleOpusEditing(row),
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'繼續編輯',
),
h(
NPopconfirm,
{
onPositiveClick: () => handleOpusDeleteRow(row),
onNegativeClick: () => {
window.$message.info('取消删除')
},
},
{
trigger: () =>
h(
'span',
{
style: { marginRight: '20px' },
class: 'text-theme-color cursor-pointer hover:opacity-80',
},
'删除',
),
default: () => '確認要刪除這一行嗎?',
},
),
])
},
},
]
}
This diff is collapsed.
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