Files
ReelShortWeb/src/views/creator-center/WorkspaceView.vue
T

331 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 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>