fix(admin): 批量建分集是否免费改由短剧免费集数决定
This commit is contained in:
1 parent
5741ebbf17
commit
05b977cc33
5 files changed
+59
-22
No files matched your search
+4
-2
@@ -555,11 +555,13 @@ export default {
|
|||||||
resumeUnmatched: '{count} session(s) could not match local files; pick again manually',
|
resumeUnmatched: '{count} session(s) could not match local files; pick again manually',
|
||||||
createTitle: 'Create episodes in batch',
|
createTitle: 'Create episodes in batch',
|
||||||
createHint:
|
createHint:
|
||||||
'Title uses the video file name; episode numbers are assigned automatically. You can edit them later in episode settings.',
|
'Title uses the video file name; episode numbers are assigned automatically. Free vs paid follows the drama free-episode count; episodes beyond that are paid. You can edit them later in episode settings.',
|
||||||
colSource: 'Source file',
|
colSource: 'Source file',
|
||||||
colNumber: 'Episode No.',
|
colNumber: 'Episode No.',
|
||||||
colTitle: 'Title',
|
colTitle: 'Title',
|
||||||
colFree: 'Free',
|
colFree: 'Pricing',
|
||||||
|
labelFree: 'Free',
|
||||||
|
labelPaid: 'Paid',
|
||||||
colResult: 'Result',
|
colResult: 'Result',
|
||||||
missingVideo: 'Missing video URL',
|
missingVideo: 'Missing video URL',
|
||||||
createOk: 'Created',
|
createOk: 'Created',
|
||||||
|
|||||||
@@ -546,11 +546,14 @@ export default {
|
|||||||
resumeMatched: '已匹配 {count} 个文件并开始续传',
|
resumeMatched: '已匹配 {count} 个文件并开始续传',
|
||||||
resumeUnmatched: '有 {count} 个会话无法匹配本地文件,请手动重选',
|
resumeUnmatched: '有 {count} 个会话无法匹配本地文件,请手动重选',
|
||||||
createTitle: '批量创建分集',
|
createTitle: '批量创建分集',
|
||||||
createHint: '标题取视频文件名,集号自动顺延分配,创建后可在分集编辑中修改',
|
createHint:
|
||||||
|
'标题取视频文件名,集号自动顺延分配;免费集数由短剧管理中的「免费集数」配置决定,超出部分为收费集;创建后可在分集编辑中修改',
|
||||||
colSource: '源文件',
|
colSource: '源文件',
|
||||||
colNumber: '集号',
|
colNumber: '集号',
|
||||||
colTitle: '标题',
|
colTitle: '标题',
|
||||||
colFree: '免费',
|
colFree: '收费类型',
|
||||||
|
labelFree: '免费',
|
||||||
|
labelPaid: '收费',
|
||||||
colResult: '结果',
|
colResult: '结果',
|
||||||
missingVideo: '缺少视频地址',
|
missingVideo: '缺少视频地址',
|
||||||
createOk: '已创建',
|
createOk: '已创建',
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ onMounted(async () => {
|
|||||||
:drama-id="selectedDramaId"
|
:drama-id="selectedDramaId"
|
||||||
:next-episode-number="batchNextNumber"
|
:next-episode-number="batchNextNumber"
|
||||||
:default-unlock-coin="selectedDrama?.unlockCoin ?? 0"
|
:default-unlock-coin="selectedDrama?.unlockCoin ?? 0"
|
||||||
|
:free-episodes="selectedDrama?.freeEpisodes ?? 0"
|
||||||
:existing-numbers="existingEpisodeNumbers"
|
:existing-numbers="existingEpisodeNumbers"
|
||||||
@refreshed="loadEpisodes"
|
@refreshed="loadEpisodes"
|
||||||
@created="onBatchEpisodesCreated"
|
@created="onBatchEpisodesCreated"
|
||||||
|
|||||||
@@ -12,13 +12,20 @@ import { useUploadQueue } from './useUploadQueue'
|
|||||||
import { MAX_VIDEO_SIZE, VIDEO_ACCEPT_ATTR, VIDEO_EXTENSIONS } from './videoLimit'
|
import { MAX_VIDEO_SIZE, VIDEO_ACCEPT_ATTR, VIDEO_EXTENSIONS } from './videoLimit'
|
||||||
import type { UploadSessionRecord } from './uploadSessions'
|
import type { UploadSessionRecord } from './uploadSessions'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
modelValue: boolean
|
defineProps<{
|
||||||
dramaId: string | number
|
modelValue: boolean
|
||||||
nextEpisodeNumber: number
|
dramaId: string | number
|
||||||
defaultUnlockCoin: number
|
nextEpisodeNumber: number
|
||||||
existingNumbers: number[]
|
defaultUnlockCoin: number
|
||||||
}>()
|
existingNumbers: number[]
|
||||||
|
/** 所属短剧免费集数;不传默认 0 */
|
||||||
|
freeEpisodes?: number
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
freeEpisodes: 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:modelValue': [value: boolean]
|
'update:modelValue': [value: boolean]
|
||||||
@@ -272,6 +279,7 @@ function onEpisodesCreated(): void {
|
|||||||
:done-items="queue.doneItems.value"
|
:done-items="queue.doneItems.value"
|
||||||
:next-episode-number="nextEpisodeNumber"
|
:next-episode-number="nextEpisodeNumber"
|
||||||
:default-unlock-coin="defaultUnlockCoin"
|
:default-unlock-coin="defaultUnlockCoin"
|
||||||
|
:free-episodes="freeEpisodes"
|
||||||
:existing-numbers="existingNumbers"
|
:existing-numbers="existingNumbers"
|
||||||
@settled="emit('refreshed')"
|
@settled="emit('refreshed')"
|
||||||
@created="onEpisodesCreated"
|
@created="onEpisodesCreated"
|
||||||
|
|||||||
@@ -8,14 +8,21 @@ import { createEpisodeApi } from '@/api/admin/episode'
|
|||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import type { UploadQueueItem } from './useUploadQueue'
|
import type { UploadQueueItem } from './useUploadQueue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
modelValue: boolean
|
defineProps<{
|
||||||
dramaId: string | number
|
modelValue: boolean
|
||||||
doneItems: UploadQueueItem[]
|
dramaId: string | number
|
||||||
nextEpisodeNumber: number
|
doneItems: UploadQueueItem[]
|
||||||
defaultUnlockCoin: number
|
nextEpisodeNumber: number
|
||||||
existingNumbers: number[]
|
defaultUnlockCoin: number
|
||||||
}>()
|
existingNumbers: number[]
|
||||||
|
/** 所属短剧免费集数;不传默认 0 */
|
||||||
|
freeEpisodes?: number
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
freeEpisodes: 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:modelValue': [value: boolean]
|
'update:modelValue': [value: boolean]
|
||||||
@@ -66,16 +73,18 @@ function buildRows(): void {
|
|||||||
)
|
)
|
||||||
const used = new Set(props.existingNumbers)
|
const used = new Set(props.existingNumbers)
|
||||||
let cursor = props.nextEpisodeNumber
|
let cursor = props.nextEpisodeNumber
|
||||||
|
const freeLimit = props.freeEpisodes
|
||||||
rows.value = sorted.map((item) => {
|
rows.value = sorted.map((item) => {
|
||||||
const number = nextFreeNumber(cursor, used)
|
const number = nextFreeNumber(cursor, used)
|
||||||
used.add(number)
|
used.add(number)
|
||||||
cursor = number + 1
|
cursor = number + 1
|
||||||
|
const isFree = number <= freeLimit
|
||||||
return {
|
return {
|
||||||
key: item.id,
|
key: item.id,
|
||||||
sourceName: item.fileName,
|
sourceName: item.fileName,
|
||||||
number,
|
number,
|
||||||
title: baseName(item.fileName),
|
title: baseName(item.fileName),
|
||||||
isFree: true,
|
isFree,
|
||||||
videoUrl: item.url || '',
|
videoUrl: item.url || '',
|
||||||
durationSec: item.durationSec || 0,
|
durationSec: item.durationSec || 0,
|
||||||
saved: false,
|
saved: false,
|
||||||
@@ -173,7 +182,9 @@ function hasFailed(): boolean {
|
|||||||
<b class="create-episode-source" :title="row.sourceName">{{ row.sourceName }}</b>
|
<b class="create-episode-source" :title="row.sourceName">{{ row.sourceName }}</b>
|
||||||
<span class="create-episode-number">{{ row.number }}</span>
|
<span class="create-episode-number">{{ row.number }}</span>
|
||||||
<span class="create-episode-title" :title="row.title">{{ row.title }}</span>
|
<span class="create-episode-title" :title="row.title">{{ row.title }}</span>
|
||||||
<el-switch v-model="row.isFree" :disabled="row.saved" />
|
<span class="create-episode-free" :class="row.isFree ? 'is-free' : 'is-paid'">
|
||||||
|
{{ row.isFree ? t('episodeBatch.labelFree') : t('episodeBatch.labelPaid') }}
|
||||||
|
</span>
|
||||||
<span class="create-episode-result">
|
<span class="create-episode-result">
|
||||||
{{ row.saved ? t('episodeBatch.createOk') : row.error }}
|
{{ row.saved ? t('episodeBatch.createOk') : row.error }}
|
||||||
</span>
|
</span>
|
||||||
@@ -199,11 +210,23 @@ function hasFailed(): boolean {
|
|||||||
.create-episode-head,
|
.create-episode-head,
|
||||||
.create-episode-row {
|
.create-episode-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(120px, 1.2fr) 72px minmax(140px, 1.4fr) 48px minmax(80px, 0.8fr);
|
grid-template-columns: minmax(120px, 1.2fr) 72px minmax(140px, 1.4fr) 56px minmax(80px, 0.8fr);
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.create-episode-free {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-episode-free.is-free {
|
||||||
|
color: var(--el-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-episode-free.is-paid {
|
||||||
|
color: var(--el-color-warning);
|
||||||
|
}
|
||||||
|
|
||||||
.create-episode-head {
|
.create-episode-head {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
|
|||||||
Reference in new issue
Block a user