331 lines
11 KiB
Vue
331 lines
11 KiB
Vue
<!-- Author: fruit.com.cn -->
|
||
|
||
<script setup>
|
||
import { computed, ref } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { AppIcons } from '@/constants/icons'
|
||
import { AppImage } from '@/components/AppImage'
|
||
import PageHeading from '@/views/components/PageHeading.vue'
|
||
import CreatorCenterPage from './components/CreatorCenterPage.vue'
|
||
import { useCreatorAccess } from './composables/useCreatorAccess'
|
||
import { useRbac } from '@/stores/rbac'
|
||
import { dateCell } from '@/utils/format'
|
||
import {
|
||
DRAMA_STATUS,
|
||
dramaStatusMeta,
|
||
submissionStatusMeta,
|
||
submissionTypeText,
|
||
submitOptions,
|
||
useCreatorWorkspace
|
||
} from './composables/useCreatorWorkspace'
|
||
|
||
const router = useRouter()
|
||
const { can } = useRbac()
|
||
const canEdit = can('creator-center:drama:edit')
|
||
// 代看是只读:写操作按钮直接不渲染(后端也会拒,界面不该给出做不到的入口)
|
||
const { impersonating } = useCreatorAccess()
|
||
|
||
const {
|
||
profile,
|
||
profileLoading,
|
||
dramas,
|
||
notices,
|
||
createVisible,
|
||
createSaving,
|
||
createForm,
|
||
queryDramas,
|
||
loadDramas,
|
||
loadNotices,
|
||
submit,
|
||
withdraw,
|
||
openCreate,
|
||
confirmCreate
|
||
} = useCreatorWorkspace()
|
||
|
||
const activeTab = ref('dramas')
|
||
|
||
const workspaceCoverPreviewList = computed(() =>
|
||
(dramas.rows || []).map((row) => row.cover).filter(Boolean)
|
||
)
|
||
|
||
function workspaceCoverPreviewIndex(row) {
|
||
return Math.max(0, workspaceCoverPreviewList.value.indexOf(row.cover))
|
||
}
|
||
|
||
function onTabChange(name) {
|
||
if (name === 'notices' && !notices.loaded) loadNotices()
|
||
}
|
||
|
||
function openEdit(row) {
|
||
router.push(`/creator-center/dramas/${row.id}`)
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<CreatorCenterPage>
|
||
<PageHeading
|
||
eyebrow="创作者中心"
|
||
title="我的作品"
|
||
description="查看作品与审核进度,提交上线 / 下线申请。"
|
||
>
|
||
<el-button v-if="canEdit && !impersonating" type="primary" @click="openCreate"
|
||
>新建作品</el-button
|
||
>
|
||
</PageHeading>
|
||
|
||
<section v-loading="profileLoading" class="panel creator-profile">
|
||
<div class="creator-profile-main">
|
||
<span class="creator-profile-name">{{ profile?.name || '—' }}</span>
|
||
<el-tag
|
||
size="small"
|
||
effect="light"
|
||
:type="profile?.status === 'approved' ? 'success' : 'warning'"
|
||
>
|
||
{{ profile?.statusText || '—' }}
|
||
</el-tag>
|
||
<span class="console-muted">{{ profile?.code || '' }}</span>
|
||
</div>
|
||
<div class="creator-profile-meta">
|
||
<span
|
||
>作品数 <b>{{ profile?.dramaTotal ?? 0 }}</b></span
|
||
>
|
||
<span
|
||
>联系人 <b>{{ profile?.contactName || '—' }}</b></span
|
||
>
|
||
<span
|
||
>联系邮箱 <b>{{ profile?.contactEmail || '—' }}</b></span
|
||
>
|
||
</div>
|
||
<el-alert
|
||
v-if="profile && profile.status === 'rejected'"
|
||
class="creator-profile-alert"
|
||
type="error"
|
||
:closable="false"
|
||
show-icon
|
||
:title="`入驻审核未通过:${profile.auditNote || '未填写原因'}`"
|
||
/>
|
||
<el-alert
|
||
v-else-if="profile && profile.status !== 'approved'"
|
||
class="creator-profile-alert"
|
||
type="warning"
|
||
:closable="false"
|
||
show-icon
|
||
title="入驻审核通过后才能创建作品与提交审核"
|
||
/>
|
||
</section>
|
||
|
||
<section class="panel">
|
||
<el-tabs v-model="activeTab" @tab-change="onTabChange">
|
||
<el-tab-pane label="我的作品" name="dramas">
|
||
<div class="console-toolbar">
|
||
<el-input
|
||
v-model="dramas.keyword"
|
||
class="console-keyword"
|
||
clearable
|
||
placeholder="搜索作品名称"
|
||
@keyup.enter="queryDramas"
|
||
@clear="queryDramas"
|
||
>
|
||
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||
</el-input>
|
||
<el-select
|
||
v-model="dramas.status"
|
||
class="console-select"
|
||
clearable
|
||
placeholder="全部状态"
|
||
@change="queryDramas"
|
||
>
|
||
<el-option
|
||
v-for="item in DRAMA_STATUS"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
<el-button type="primary" @click="queryDramas">查询</el-button>
|
||
<span class="console-count">共 {{ dramas.total }} 部作品</span>
|
||
</div>
|
||
|
||
<el-table
|
||
v-loading="dramas.loading"
|
||
:data="dramas.rows"
|
||
row-key="id"
|
||
border
|
||
class="drama-el-table"
|
||
empty-text="还没有作品,点右上角「新建作品」开始"
|
||
>
|
||
<el-table-column label="作品" min-width="220">
|
||
<template #default="{ row }">
|
||
<div class="creator-drama-cell">
|
||
<div class="creator-drama-cover">
|
||
<AppImage
|
||
v-if="row.cover"
|
||
:src="row.cover"
|
||
:preview-list="workspaceCoverPreviewList"
|
||
:initial-index="workspaceCoverPreviewIndex(row)"
|
||
fit="cover"
|
||
class="creator-drama-image"
|
||
:alt="row.title"
|
||
/>
|
||
<span v-else>{{ (row.title || '?').slice(0, 1) }}</span>
|
||
</div>
|
||
<div class="creator-drama-meta">
|
||
<span class="creator-drama-title">{{ row.title }}</span>
|
||
<span class="creator-drama-code">{{ row.code }}</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" width="100">
|
||
<template #default="{ row }">
|
||
<el-tag :type="dramaStatusMeta(row.status).tag" effect="light">{{
|
||
dramaStatusMeta(row.status).label
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="episodes" label="分集" width="80" />
|
||
<el-table-column prop="views" label="播放" width="100" />
|
||
<el-table-column label="审核进度" min-width="200">
|
||
<template #default="{ row }">
|
||
<div v-if="row.submissionStatus" class="creator-progress">
|
||
<el-tag
|
||
size="small"
|
||
:type="submissionStatusMeta(row.submissionStatus).tag"
|
||
effect="plain"
|
||
>
|
||
{{ submissionTypeText(row.submissionType) }}·{{
|
||
submissionStatusMeta(row.submissionStatus).label
|
||
}}
|
||
</el-tag>
|
||
<span v-if="row.reviewNote" class="console-muted" :title="row.reviewNote">{{
|
||
row.reviewNote
|
||
}}</span>
|
||
</div>
|
||
<span v-else class="console-muted">尚未提交</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="updatedAt"
|
||
label="更新时间"
|
||
min-width="165"
|
||
:formatter="dateCell"
|
||
show-overflow-tooltip
|
||
/>
|
||
<el-table-column label="操作" width="210" fixed="right">
|
||
<template #default="{ row }">
|
||
<div class="table-actions">
|
||
<el-button
|
||
v-if="canEdit && !impersonating"
|
||
type="primary"
|
||
size="small"
|
||
@click="openEdit(row)"
|
||
>编辑</el-button
|
||
>
|
||
<el-dropdown
|
||
v-if="canEdit && !impersonating && submitOptions(row).length"
|
||
trigger="click"
|
||
@command="(type) => submit(row, type)"
|
||
>
|
||
<el-button size="small">提交审核</el-button>
|
||
<template #dropdown>
|
||
<el-dropdown-menu>
|
||
<el-dropdown-item
|
||
v-for="type in submitOptions(row)"
|
||
:key="type"
|
||
:command="type"
|
||
>
|
||
{{ submissionTypeText(type) }}
|
||
</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</template>
|
||
</el-dropdown>
|
||
<el-button
|
||
v-if="
|
||
canEdit &&
|
||
!impersonating &&
|
||
row.submissionId &&
|
||
['SUBMITTED', 'REVIEWING'].includes(row.submissionStatus)
|
||
"
|
||
type="danger"
|
||
size="small"
|
||
@click="withdraw(row)"
|
||
>撤回</el-button
|
||
>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="dramas.page"
|
||
v-model:page-size="dramas.size"
|
||
:page-sizes="[10, 20, 50]"
|
||
:total="dramas.total"
|
||
layout="total, prev, pager, next, sizes"
|
||
background
|
||
@current-change="loadDramas"
|
||
@size-change="queryDramas"
|
||
/>
|
||
</div>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="通知" name="notices">
|
||
<div v-loading="notices.loading" class="creator-notice-list">
|
||
<el-empty v-if="!notices.rows.length" description="还没有审核结果通知" />
|
||
<div
|
||
v-for="item in notices.rows"
|
||
:key="`${item.bizType}-${item.id}`"
|
||
class="creator-notice"
|
||
>
|
||
<div class="creator-notice-head">
|
||
<span class="creator-notice-title">{{ item.title }}</span>
|
||
<span class="console-muted">{{
|
||
item.time ? String(item.time).replace('T', ' ').slice(0, 19) : ''
|
||
}}</span>
|
||
</div>
|
||
<p class="creator-notice-body">{{ item.content || '—' }}</p>
|
||
</div>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</section>
|
||
|
||
<el-dialog v-model="createVisible" title="新建作品" width="480px">
|
||
<el-form label-position="top">
|
||
<el-form-item label="作品名称" required>
|
||
<el-input
|
||
v-model="createForm.title"
|
||
maxlength="64"
|
||
placeholder="例如:闪婚后,傅先生每天都在撒糖"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="题材">
|
||
<el-input v-model="createForm.genre" maxlength="32" placeholder="例如:都市情感" />
|
||
</el-form-item>
|
||
<el-form-item label="简介">
|
||
<el-input
|
||
v-model="createForm.description"
|
||
type="textarea"
|
||
:rows="3"
|
||
maxlength="200"
|
||
show-word-limit
|
||
/>
|
||
</el-form-item>
|
||
<el-alert
|
||
type="info"
|
||
:closable="false"
|
||
show-icon
|
||
title="先建草稿,再去作品编辑页完善信息、分集与视频,然后提交审核"
|
||
/>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="createVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="createSaving" @click="confirmCreate"
|
||
>创建草稿</el-button
|
||
>
|
||
</template>
|
||
</el-dialog>
|
||
</CreatorCenterPage>
|
||
</template>
|