feat(web): 08 后台四个页面落地(内容治理 / 订单与权益 / 创作者审核 / 数据看板)
为什么:08 运营后台的接口在前几轮已经实现,但运营在界面上点不到—— 评论审核、举报工单、敏感词维护、订单补发/退款、权益回收、金币补发、对账、 创作者入驻与内容提交审核、运营大盘,都只能靠 curl。本轮把这四个页面补齐, 08 才算真正闭环。 - 内容治理:评论审核(通过/驳回/删除)、举报工单处理(可联动封禁)、敏感词库增删改查 - 订单与权益:订单检索与流水、补发、退款、权益检索/人工补发/回收、金币流水与人工补币、对账运行与历史 - 创作者审核:入驻审核(通过/驳回原因码/冻结)+ 资质抽屉;内容提交审核(通过/驳回) - 数据看板:overview 五组指标 + transcode 队列与失败任务,只读;取不到的指标显示「暂无数据源」而不是 0 - 新增 console.css(工具条/抽屉/看板卡片,含深色模式),四个页面共用;时间列统一 yyyy-MM-dd HH:mm:ss - 按钮按权限点显隐(没有 *:update / *:audit 的角色看到的是只读态),表格列与后端字段一一对应
This commit is contained in:
1 parent
44c2c46a68
commit
f037d243cd
13 files changed
+2680
No files matched your search
@@ -0,0 +1,234 @@
|
||||
<script setup>
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import PageHeading from '@/views/components/PageHeading.vue'
|
||||
import { useRbac } from '@/stores/rbac'
|
||||
import { dateCell } from '@/utils/format'
|
||||
import {
|
||||
CREATOR_STATUS,
|
||||
CREATOR_TYPE,
|
||||
creatorStatusMeta,
|
||||
creatorTypeText,
|
||||
useCreatorAudit
|
||||
} from './composables/useCreatorAudit'
|
||||
|
||||
const { can } = useRbac()
|
||||
const canAudit = can('creator:audit')
|
||||
|
||||
const {
|
||||
rows,
|
||||
total,
|
||||
loading,
|
||||
keyword,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
currentPage,
|
||||
pageSize,
|
||||
auditVisible,
|
||||
auditSaving,
|
||||
auditTarget,
|
||||
auditForm,
|
||||
documentsVisible,
|
||||
documentsLoading,
|
||||
documents,
|
||||
documentsTarget,
|
||||
load,
|
||||
query,
|
||||
reset,
|
||||
handleSizeChange,
|
||||
openDocuments,
|
||||
openAudit,
|
||||
confirmAudit,
|
||||
freeze
|
||||
} = useCreatorAudit()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageHeading
|
||||
eyebrow="创作者管理"
|
||||
title="创作者入驻"
|
||||
description="审核创作者主体与资质,通过后创作者才能提交内容。"
|
||||
/>
|
||||
|
||||
<section class="panel">
|
||||
<div class="console-toolbar">
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
class="console-keyword"
|
||||
:prefix-icon="Search"
|
||||
clearable
|
||||
placeholder="搜索名称 / 编号 / 联系人 / 联系方式"
|
||||
@keyup.enter="query"
|
||||
@clear="query"
|
||||
/>
|
||||
<el-select
|
||||
v-model="statusFilter"
|
||||
class="console-select"
|
||||
clearable
|
||||
placeholder="全部状态"
|
||||
@change="query"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in CREATOR_STATUS"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="typeFilter"
|
||||
class="console-select"
|
||||
clearable
|
||||
placeholder="全部类型"
|
||||
@change="query"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in CREATOR_TYPE"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="query">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
<span class="console-count">共 {{ total }} 位创作者</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
row-key="id"
|
||||
border
|
||||
class="drama-el-table"
|
||||
empty-text="没有符合条件的创作者"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="70"
|
||||
:index="(currentPage - 1) * pageSize + 1"
|
||||
/>
|
||||
<el-table-column prop="code" label="编号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="name" label="名称" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="类型" width="90">
|
||||
<template #default="{ row }">{{ creatorTypeText(row.type) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="contactName" label="联系人" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
prop="contactMobile"
|
||||
label="联系方式"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="countryCode" label="国家" width="80" />
|
||||
<el-table-column label="状态" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="creatorStatusMeta(row.status).tag" effect="light">
|
||||
{{ creatorStatusMeta(row.status).label }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="auditAt"
|
||||
label="审核时间"
|
||||
min-width="165"
|
||||
show-overflow-tooltip
|
||||
:formatter="dateCell"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createdAt"
|
||||
label="入驻时间"
|
||||
min-width="165"
|
||||
show-overflow-tooltip
|
||||
:formatter="dateCell"
|
||||
/>
|
||||
<el-table-column label="操作" width="230" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button type="primary" size="small" @click="openDocuments(row)">资质</el-button>
|
||||
<el-button v-if="canAudit" size="small" @click="openAudit(row, 'APPROVE')"
|
||||
>审核</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="canAudit && row.status === 'approved'"
|
||||
size="small"
|
||||
class="danger-action"
|
||||
@click="freeze(row)"
|
||||
>冻结</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, prev, pager, next, sizes, jumper"
|
||||
background
|
||||
@current-change="load"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-drawer v-model="documentsVisible" title="创作者资质" size="520px" class="console-drawer">
|
||||
<p class="console-hint">
|
||||
{{ documentsTarget ? `${documentsTarget.name}(${documentsTarget.code})` : '' }}
|
||||
</p>
|
||||
<el-table
|
||||
v-loading="documentsLoading"
|
||||
:data="documents"
|
||||
size="small"
|
||||
border
|
||||
empty-text="没有上传资质"
|
||||
>
|
||||
<el-table-column prop="type" label="证件类型" width="140" />
|
||||
<el-table-column label="文件" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" :href="row.fileUrl" target="_blank">{{ row.fileUrl }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" />
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
|
||||
<el-dialog v-model="auditVisible" title="创作者入驻审核" width="480px">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="目标创作者">
|
||||
<el-input
|
||||
:model-value="auditTarget ? `${auditTarget.name}(${auditTarget.code})` : ''"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核动作">
|
||||
<el-radio-group v-model="auditForm.action">
|
||||
<el-radio value="APPROVE">通过</el-radio>
|
||||
<el-radio value="REJECT">驳回</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="auditForm.action === 'REJECT'" label="驳回原因码">
|
||||
<el-input
|
||||
v-model="auditForm.rejectCode"
|
||||
placeholder="例如:DOC_INCOMPLETE"
|
||||
maxlength="32"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="auditForm.action === 'REJECT' ? '驳回原因(必填)' : '备注(可选)'">
|
||||
<el-input
|
||||
v-model="auditForm.reason"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="auditVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="auditSaving" @click="confirmAudit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,201 @@
|
||||
<script setup>
|
||||
import PageHeading from '@/views/components/PageHeading.vue'
|
||||
import { useRbac } from '@/stores/rbac'
|
||||
import { dateCell } from '@/utils/format'
|
||||
import {
|
||||
SUBMISSION_STATUS,
|
||||
SUBMISSION_TYPE,
|
||||
submissionStatusMeta,
|
||||
submissionTypeText,
|
||||
useSubmissionAudit
|
||||
} from './composables/useSubmissionAudit'
|
||||
|
||||
const { can } = useRbac()
|
||||
const canAudit = can('submission:audit')
|
||||
|
||||
const {
|
||||
rows,
|
||||
total,
|
||||
loading,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
dramaId,
|
||||
currentPage,
|
||||
pageSize,
|
||||
auditVisible,
|
||||
auditSaving,
|
||||
auditTarget,
|
||||
auditForm,
|
||||
load,
|
||||
query,
|
||||
reset,
|
||||
handleSizeChange,
|
||||
openAudit,
|
||||
confirmAudit
|
||||
} = useSubmissionAudit()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageHeading
|
||||
eyebrow="创作者管理"
|
||||
title="内容审核"
|
||||
description="审核创作者提交的内容;通过后按提交类型落到短剧状态机(上线 / 下线)。"
|
||||
/>
|
||||
|
||||
<section class="panel">
|
||||
<div class="console-toolbar">
|
||||
<el-select
|
||||
v-model="statusFilter"
|
||||
class="console-select"
|
||||
clearable
|
||||
placeholder="全部状态"
|
||||
@change="query"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in SUBMISSION_STATUS"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="typeFilter"
|
||||
class="console-select"
|
||||
clearable
|
||||
placeholder="全部类型"
|
||||
@change="query"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in SUBMISSION_TYPE"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-model="dramaId"
|
||||
class="console-drama"
|
||||
placeholder="按短剧 ID 过滤"
|
||||
clearable
|
||||
@keyup.enter="query"
|
||||
/>
|
||||
<el-button type="primary" @click="query">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
<span class="console-count">共 {{ total }} 条提交</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
row-key="id"
|
||||
border
|
||||
class="drama-el-table"
|
||||
empty-text="没有符合条件的提交记录"
|
||||
>
|
||||
<el-table-column prop="id" label="提交ID" width="90" />
|
||||
<el-table-column prop="dramaId" label="短剧ID" width="90" />
|
||||
<el-table-column prop="creatorId" label="创作者ID" width="100" />
|
||||
<el-table-column label="提交类型" width="110">
|
||||
<template #default="{ row }">{{ submissionTypeText(row.type) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="submissionStatusMeta(row.status).tag" effect="light">
|
||||
{{ submissionStatusMeta(row.status).label }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="version" label="版本" width="80" />
|
||||
<el-table-column
|
||||
prop="submitAt"
|
||||
label="提交时间"
|
||||
min-width="165"
|
||||
show-overflow-tooltip
|
||||
:formatter="dateCell"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="reviewAt"
|
||||
label="审核时间"
|
||||
min-width="165"
|
||||
show-overflow-tooltip
|
||||
:formatter="dateCell"
|
||||
/>
|
||||
<el-table-column prop="reviewNote" label="审核说明" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button
|
||||
v-if="canAudit"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="openAudit(row, 'APPROVE')"
|
||||
>审核</el-button
|
||||
>
|
||||
<el-button v-else size="small" disabled>只读</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, prev, pager, next, sizes, jumper"
|
||||
background
|
||||
@current-change="load"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="auditVisible" title="内容提交审核" width="480px">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="提交信息">
|
||||
<el-input
|
||||
:model-value="
|
||||
auditTarget
|
||||
? `提交 #${auditTarget.id} · 短剧 ${auditTarget.dramaId} · ${submissionTypeText(auditTarget.type)}`
|
||||
: ''
|
||||
"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核结果">
|
||||
<el-radio-group v-model="auditForm.action">
|
||||
<el-radio value="APPROVE">通过</el-radio>
|
||||
<el-radio value="REJECT">驳回</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="auditForm.action === 'REJECT'" label="驳回原因码">
|
||||
<el-input
|
||||
v-model="auditForm.rejectCode"
|
||||
placeholder="例如:CONTENT_VIOLATION"
|
||||
maxlength="32"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="auditForm.action === 'REJECT' ? '驳回原因(必填)' : '备注(可选)'">
|
||||
<el-input
|
||||
v-model="auditForm.reason"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-alert
|
||||
v-if="auditForm.action === 'APPROVE'"
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="通过后按提交类型落到短剧状态机:申请上线会顺推至已上线,申请下线会下线"
|
||||
/>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="auditVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="auditSaving" @click="confirmAudit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,167 @@
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { auditCreatorApi, listCreatorDocumentsApi, pageCreatorsApi } from '@/api/admin/creator'
|
||||
|
||||
/** 与后端 CreatorService 的状态取值保持一致 */
|
||||
export const CREATOR_STATUS = [
|
||||
{ value: 'pending', label: '待审核', tag: 'warning' },
|
||||
{ value: 'approved', label: '已通过', tag: 'success' },
|
||||
{ value: 'rejected', label: '已驳回', tag: 'danger' },
|
||||
{ value: 'frozen', label: '已冻结', tag: 'info' }
|
||||
]
|
||||
|
||||
export const CREATOR_TYPE = [
|
||||
{ value: 'INDIVIDUAL', label: '个人' },
|
||||
{ value: 'COMPANY', label: '机构' }
|
||||
]
|
||||
|
||||
export function creatorStatusMeta(status) {
|
||||
return (
|
||||
CREATOR_STATUS.find((item) => item.value === status) || { label: status || '-', tag: 'info' }
|
||||
)
|
||||
}
|
||||
|
||||
export function creatorTypeText(type) {
|
||||
return CREATOR_TYPE.find((item) => item.value === type)?.label || type || '-'
|
||||
}
|
||||
|
||||
export function useCreatorAudit() {
|
||||
const rows = ref([])
|
||||
const total = ref(0)
|
||||
const loading = ref(false)
|
||||
const keyword = ref('')
|
||||
const statusFilter = ref(undefined)
|
||||
const typeFilter = ref(undefined)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
const auditVisible = ref(false)
|
||||
const auditSaving = ref(false)
|
||||
const auditTarget = ref(null)
|
||||
const auditForm = reactive({ action: 'APPROVE', reason: '', rejectCode: '' })
|
||||
|
||||
const documentsVisible = ref(false)
|
||||
const documentsLoading = ref(false)
|
||||
const documents = ref([])
|
||||
const documentsTarget = ref(null)
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await pageCreatorsApi({
|
||||
pageIndex: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
keyword: keyword.value.trim() || undefined,
|
||||
status: statusFilter.value,
|
||||
type: typeFilter.value
|
||||
})
|
||||
rows.value = res.data?.list || []
|
||||
total.value = res.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function query() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function reset() {
|
||||
keyword.value = ''
|
||||
statusFilter.value = undefined
|
||||
typeFilter.value = undefined
|
||||
query()
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
async function openDocuments(row) {
|
||||
documentsTarget.value = row
|
||||
documentsVisible.value = true
|
||||
documentsLoading.value = true
|
||||
documents.value = []
|
||||
try {
|
||||
documents.value = (await listCreatorDocumentsApi(row.id)).data || []
|
||||
} finally {
|
||||
documentsLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openAudit(row, action = 'APPROVE') {
|
||||
auditTarget.value = row
|
||||
auditForm.action = action
|
||||
auditForm.reason = ''
|
||||
auditForm.rejectCode = ''
|
||||
auditVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmAudit() {
|
||||
const row = auditTarget.value
|
||||
if (!row) return
|
||||
if (auditForm.action === 'REJECT' && !auditForm.reason.trim()) {
|
||||
return ElMessage.warning('驳回必须填写原因')
|
||||
}
|
||||
auditSaving.value = true
|
||||
try {
|
||||
await auditCreatorApi(row.id, {
|
||||
action: auditForm.action,
|
||||
reason: auditForm.reason.trim(),
|
||||
rejectCode: auditForm.rejectCode.trim()
|
||||
})
|
||||
ElMessage.success('审核已提交')
|
||||
auditVisible.value = false
|
||||
await load()
|
||||
} finally {
|
||||
auditSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 冻结是不可逆的运营动作,单独二次确认 */
|
||||
async function freeze(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`冻结后「${row.name}」将无法提交内容,确认冻结?`, '冻结创作者', {
|
||||
confirmButtonText: '确认冻结',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
await auditCreatorApi(row.id, { action: 'FREEZE', reason: '运营冻结' })
|
||||
ElMessage.success('已冻结')
|
||||
await load()
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
|
||||
return {
|
||||
rows,
|
||||
total,
|
||||
loading,
|
||||
keyword,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
currentPage,
|
||||
pageSize,
|
||||
auditVisible,
|
||||
auditSaving,
|
||||
auditTarget,
|
||||
auditForm,
|
||||
documentsVisible,
|
||||
documentsLoading,
|
||||
documents,
|
||||
documentsTarget,
|
||||
load,
|
||||
query,
|
||||
reset,
|
||||
handleSizeChange,
|
||||
openDocuments,
|
||||
openAudit,
|
||||
confirmAudit,
|
||||
freeze
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { auditSubmissionApi, pageSubmissionsApi } from '@/api/admin/creator'
|
||||
|
||||
export const SUBMISSION_STATUS = [
|
||||
{ value: 'DRAFT', label: '草稿', tag: 'info' },
|
||||
{ value: 'SUBMITTED', label: '已提交', tag: 'warning' },
|
||||
{ value: 'REVIEWING', label: '审核中', tag: 'warning' },
|
||||
{ value: 'APPROVED', label: '已通过', tag: 'success' },
|
||||
{ value: 'REJECTED', label: '已驳回', tag: 'danger' },
|
||||
{ value: 'WITHDRAWN', label: '已撤回', tag: 'info' }
|
||||
]
|
||||
|
||||
export const SUBMISSION_TYPE = [
|
||||
{ value: 'CREATE', label: '新建' },
|
||||
{ value: 'UPDATE', label: '更新' },
|
||||
{ value: 'PUBLISH', label: '申请上线' },
|
||||
{ value: 'OFFLINE', label: '申请下线' }
|
||||
]
|
||||
|
||||
export function submissionStatusMeta(status) {
|
||||
return (
|
||||
SUBMISSION_STATUS.find((item) => item.value === status) || {
|
||||
label: status || '-',
|
||||
tag: 'info'
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export function submissionTypeText(type) {
|
||||
return SUBMISSION_TYPE.find((item) => item.value === type)?.label || type || '-'
|
||||
}
|
||||
|
||||
export function useSubmissionAudit() {
|
||||
const rows = ref([])
|
||||
const total = ref(0)
|
||||
const loading = ref(false)
|
||||
const statusFilter = ref('SUBMITTED')
|
||||
const typeFilter = ref(undefined)
|
||||
const dramaId = ref(undefined)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
const auditVisible = ref(false)
|
||||
const auditSaving = ref(false)
|
||||
const auditTarget = ref(null)
|
||||
const auditForm = reactive({ action: 'APPROVE', reason: '', rejectCode: '' })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await pageSubmissionsApi({
|
||||
pageIndex: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
status: statusFilter.value,
|
||||
type: typeFilter.value,
|
||||
dramaId: dramaId.value || undefined
|
||||
})
|
||||
rows.value = res.data?.list || []
|
||||
total.value = res.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function query() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function reset() {
|
||||
statusFilter.value = 'SUBMITTED'
|
||||
typeFilter.value = undefined
|
||||
dramaId.value = undefined
|
||||
query()
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
function openAudit(row, action = 'APPROVE') {
|
||||
auditTarget.value = row
|
||||
auditForm.action = action
|
||||
auditForm.reason = ''
|
||||
auditForm.rejectCode = ''
|
||||
auditVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmAudit() {
|
||||
const row = auditTarget.value
|
||||
if (!row) return
|
||||
if (auditForm.action === 'REJECT' && !auditForm.reason.trim()) {
|
||||
return ElMessage.warning('驳回必须填写原因')
|
||||
}
|
||||
auditSaving.value = true
|
||||
try {
|
||||
await auditSubmissionApi(row.id, {
|
||||
action: auditForm.action,
|
||||
reason: auditForm.reason.trim(),
|
||||
rejectCode: auditForm.rejectCode.trim()
|
||||
})
|
||||
ElMessage.success(
|
||||
auditForm.action === 'APPROVE' ? '审核通过,已按类型落到短剧状态' : '审核结果已保存'
|
||||
)
|
||||
auditVisible.value = false
|
||||
await load()
|
||||
} finally {
|
||||
auditSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
|
||||
return {
|
||||
rows,
|
||||
total,
|
||||
loading,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
dramaId,
|
||||
currentPage,
|
||||
pageSize,
|
||||
auditVisible,
|
||||
auditSaving,
|
||||
auditTarget,
|
||||
auditForm,
|
||||
load,
|
||||
query,
|
||||
reset,
|
||||
handleSizeChange,
|
||||
openAudit,
|
||||
confirmAudit
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user