|
|
@@ -9,10 +9,9 @@
|
|
|
zIndex: 1000,
|
|
|
}"
|
|
|
>
|
|
|
-
|
|
|
<a-drawer
|
|
|
- :label="getModalTitle()"
|
|
|
- size="600px"
|
|
|
+ label="游戏配置"
|
|
|
+ size="700px"
|
|
|
:open="open"
|
|
|
:mask="false"
|
|
|
:closable="false"
|
|
|
@@ -20,12 +19,11 @@
|
|
|
:get-container="false"
|
|
|
:style="{ position: 'absolute', top: '0px', right: '0px', width: '600px' }"
|
|
|
>
|
|
|
- <!-- -->
|
|
|
<template #title>
|
|
|
<div style="display: flex;justify-content: space-between;" >
|
|
|
<div>
|
|
|
<a-space>
|
|
|
- <div>游戏配置 {{gameStateComputed ? `: ${gameStateComputed}` : gameStateComputed}}</div>
|
|
|
+ <div>游戏配置 {{gameStateComputed}}</div>
|
|
|
<a-tooltip placement="bottom" :getPopupContainer="(node) => node.offsetParent">
|
|
|
<template #title>
|
|
|
<span v-html="operationTip"></span>
|
|
|
@@ -34,7 +32,6 @@
|
|
|
</a-tooltip>
|
|
|
</a-space>
|
|
|
</div>
|
|
|
-
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #extra >
|
|
|
@@ -55,7 +52,7 @@
|
|
|
<template #icon><left-outlined /></template>
|
|
|
返回上级
|
|
|
</a-button>
|
|
|
- <a-button v-if="currentLevel === 1" type="primary" size="small" @click="createSubItem">
|
|
|
+ <a-button v-if="currentLevel === 1" type="primary" size="small" @click="handleSaveSubItem">
|
|
|
<template #icon><plus-outlined /></template>
|
|
|
新增
|
|
|
</a-button>
|
|
|
@@ -64,106 +61,75 @@
|
|
|
<!-- 顶级文件夹内容 -->
|
|
|
<a-row v-if="currentLevel === 0" justify="flex-start" :gutter="[8, 8]" class="config-game-list">
|
|
|
<a-col
|
|
|
- :span="7"
|
|
|
+ :span="8"
|
|
|
style="height: 120px;"
|
|
|
- class="config-game-item"
|
|
|
v-for="(folder, index) in cardJson.game_list"
|
|
|
:key="index"
|
|
|
- @dblclick="enterFolder(index)"
|
|
|
>
|
|
|
- <!-- 状态图标 -->
|
|
|
- <div class="status-icon">
|
|
|
- <CheckCircleFilled v-if="validateGameConfig(folder).isValid" class="status-complete" />
|
|
|
- <ExclamationCircleFilled v-else class="status-incomplete" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <img class="folder-icon" :src="require('@/assets/common/folder.svg')" alt="">
|
|
|
-
|
|
|
- <div class="folder-footer">
|
|
|
- <div>游戏 {{ index + 1 }}</div>
|
|
|
- <div>
|
|
|
- <a-dropdown :trigger="['hover']">
|
|
|
- <SmallDashOutlined class="action-icon" />
|
|
|
- <template #overlay>
|
|
|
- <a-menu>
|
|
|
- <a-menu-item key="edit" @click="handleEdit(index)">
|
|
|
- <EditOutlined />
|
|
|
- <span style="margin-left: 8px;">编辑</span>
|
|
|
- </a-menu-item>
|
|
|
- <a-menu-item key="delete" @click="handleDelete(index)">
|
|
|
- <DeleteOutlined style="color: #ff4d4f;" />
|
|
|
- <span style="margin-left: 8px;">删除</span>
|
|
|
- </a-menu-item>
|
|
|
- </a-menu>
|
|
|
- </template>
|
|
|
- </a-dropdown>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <FolderComponens
|
|
|
+ :game="folder"
|
|
|
+ @dblclick="enterFolder(index)"
|
|
|
+ />
|
|
|
</a-col>
|
|
|
<a-empty style="margin: 0 auto;" v-if="cardJson.game_list.length === 0" description="暂无游戏"> </a-empty>
|
|
|
</a-row>
|
|
|
|
|
|
<div v-else-if="currentLevel === 1">
|
|
|
- <a-row :gutter="[8, 8]">
|
|
|
- <VueDraggableNext
|
|
|
- :list="cardJson.game_list[currentGameIndex].items"
|
|
|
- group="people"
|
|
|
- item-key="id"
|
|
|
- :animation="300"
|
|
|
- class="config-game-list"
|
|
|
- >
|
|
|
- <a-col
|
|
|
- style="height: 120px;"
|
|
|
- :span="8"
|
|
|
- class="config-game-item"
|
|
|
- v-for="(item, index) in cardJson.game_list[currentGameIndex].items"
|
|
|
- :key="index"
|
|
|
- @dblclick="enterCardConfig(index)"
|
|
|
- >
|
|
|
- <img class="folder-icon" :src="require('@/assets/common/folder.svg')" alt="">
|
|
|
-
|
|
|
- <div class="folder-footer">
|
|
|
- <a-space>
|
|
|
- <div>游戏 {{ index + 1 }}</div>
|
|
|
- <div class="folder-info">
|
|
|
- <div v-if="item.sub_subject?.music_name ? item.sub_subject.music_name : item.sub_subject.ok" class="music-badge">
|
|
|
- <sound-outlined />
|
|
|
- <span class="music-name">{{ item.sub_subject?.music_name ? item.sub_subject.music_name : item.sub_subject.ok }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-space>
|
|
|
- <div>
|
|
|
- <a-dropdown :trigger="['hover']">
|
|
|
- <SmallDashOutlined class="action-icon" />
|
|
|
- <template #overlay>
|
|
|
- <a-menu>
|
|
|
- <a-menu-item key="edit" @click="handleEditSubItem(index)">
|
|
|
- <EditOutlined />
|
|
|
- <span style="margin-left: 8px;">编辑</span>
|
|
|
- </a-menu-item>
|
|
|
- <a-menu-item key="delete" @click="handleDeleteSubItem(index)">
|
|
|
- <DeleteOutlined style="color: #ff4d4f;" />
|
|
|
- <span style="margin-left: 8px;">删除</span>
|
|
|
- </a-menu-item>
|
|
|
- </a-menu>
|
|
|
- </template>
|
|
|
- </a-dropdown>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-col>
|
|
|
- </VueDraggableNext>
|
|
|
- </a-row>
|
|
|
- <a-empty style="margin: 0 auto;" v-if="cardJson.game_list[currentGameIndex].items.length === 0" description="暂无游戏"> </a-empty>
|
|
|
+ <!-- 位置文件的rule和main_subject的music_name -->
|
|
|
+ <a-descriptions :column="1" >
|
|
|
+ <a-descriptions-item label="规则">
|
|
|
+ <a-select style="width: 100%" v-model:value="cardJson.game_list[currentGameIndex].rule" placeholder="请选择规则">
|
|
|
+ <a-select-option
|
|
|
+ v-for="rule in CardController.ruleList"
|
|
|
+ :key="rule.value"
|
|
|
+ :value="rule.value"
|
|
|
+ >
|
|
|
+ {{ rule.title }}
|
|
|
+ </a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item label="音乐">
|
|
|
+ <SelectAudioNew
|
|
|
+ v-model="cardJson.game_list[currentGameIndex].main_subject.music_name"
|
|
|
+ placeholder="请选择主题音乐"
|
|
|
+ />
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item label="items">
|
|
|
+ <a-row :gutter="[8, 8]" style="width: 100%;">
|
|
|
+ <a-col
|
|
|
+ style="height: 120px;"
|
|
|
+ :span="8"
|
|
|
+ v-for="(item, index) in transformJSON.items"
|
|
|
+ :key="index"
|
|
|
+ @dblclick="enterCardConfig(index)"
|
|
|
+ >
|
|
|
+ <FolderComponens
|
|
|
+ :game="item"
|
|
|
+ @dblclick="enterCardConfig(index)"
|
|
|
+ />
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-empty style="margin: 0 auto;" v-if="cardJson.game_list[currentGameIndex].items.length === 0" description="暂无游戏"> </a-empty>
|
|
|
+ </a-descriptions-item>
|
|
|
+ </a-descriptions>
|
|
|
</div>
|
|
|
|
|
|
<!-- 三级内容:游戏步骤配置 -->
|
|
|
<div v-else-if="currentLevel === 2">
|
|
|
<div class="card-config-content">
|
|
|
+ <gameStage3Rule7
|
|
|
+ v-if="transformJSON.rule === 7"
|
|
|
+ v-model="cardJson.game_list[currentGameIndex].items"
|
|
|
+ :rule="cardJson.game_list[currentGameIndex].rule"
|
|
|
+ @update:modelValue="changedSteps"
|
|
|
+ @step-selected="emits('step-selected', $event)"
|
|
|
+ />
|
|
|
<gameStage3
|
|
|
- v-if="cardJson.game_list[currentGameIndex]?.items?.[currentSubFolderIndex]"
|
|
|
+ v-if="cardJson.game_list[currentGameIndex]?.items?.[currentSubFolderIndex] && transformJSON.rule !== 7"
|
|
|
v-model="cardJson.game_list[currentGameIndex].items[currentSubFolderIndex]"
|
|
|
:gameIndex="currentSubFolderIndex"
|
|
|
v-model:touch_key="cardJson.game_list[currentGameIndex].touch_key"
|
|
|
+ v-model:ok_key_voice="cardJson.game_list[currentGameIndex].ok_key_voice"
|
|
|
:rule="cardJson.game_list[currentGameIndex].rule"
|
|
|
@update:modelValue="changedSteps"
|
|
|
@step-selected="emits('step-selected', $event)"
|
|
|
@@ -173,150 +139,6 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</a-drawer>
|
|
|
-
|
|
|
- <!-- 新增子项目弹窗 -->
|
|
|
- <a-modal
|
|
|
- v-model:open="subItemModalVisible"
|
|
|
- title="新增子项目"
|
|
|
- width="400px"
|
|
|
- @ok="handleSaveSubItem"
|
|
|
- >
|
|
|
- <a-form :model="subItemForm" layout="vertical">
|
|
|
- <a-form-item label="子主题音乐">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="subItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name']"
|
|
|
- placeholder="请选择子主题音乐"
|
|
|
- />
|
|
|
-
|
|
|
- <!-- 已选择的音乐名称展示区域 -->
|
|
|
- <div v-if="subItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name']" class="selected-music-display">
|
|
|
- <div class="music-info">
|
|
|
- <sound-outlined />
|
|
|
- <span class="music-name">{{ subItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name'] }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-form-item>
|
|
|
- </a-form>
|
|
|
- </a-modal>
|
|
|
-
|
|
|
- <!-- 编辑子项目弹窗 -->
|
|
|
- <a-modal
|
|
|
- v-model:open="editSubItemModalVisible"
|
|
|
- title="编辑子项目"
|
|
|
- width="400px"
|
|
|
- @ok="handleSaveSubItemEdit"
|
|
|
- @cancel="handleCancelSubItemEdit"
|
|
|
- >
|
|
|
- <a-form :model="editSubItemForm" layout="vertical">
|
|
|
- <a-form-item label="子主题音乐">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editSubItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name']"
|
|
|
- placeholder="请选择子主题音乐"
|
|
|
- />
|
|
|
-
|
|
|
- <!-- 已选择的音乐名称展示区域 -->
|
|
|
- <div v-if="editSubItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name']" class="selected-music-display">
|
|
|
- <div class="music-info">
|
|
|
- <sound-outlined />
|
|
|
- <span class="music-name">{{ editSubItemForm.sub_subject[editForm.rule == '7' ? 'ok' : 'music_name'] }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-form-item>
|
|
|
- </a-form>
|
|
|
- </a-modal>
|
|
|
-
|
|
|
- <!-- 编辑游戏弹窗 -->
|
|
|
- <a-modal
|
|
|
- v-model:open="editModalVisible"
|
|
|
- title="编辑游戏配置"
|
|
|
- width="600px"
|
|
|
- @ok="handleSaveEdit"
|
|
|
- @cancel="handleCancelEdit"
|
|
|
- >
|
|
|
- <a-form :model="editForm" layout="vertical">
|
|
|
- <!-- 规则单独一行 -->
|
|
|
- <a-form-item label="规则">
|
|
|
- <a-select v-model:value="editForm.rule" placeholder="请选择规则">
|
|
|
- <a-select-option v-for="rule in ruleOptions" :key="rule.value" :value="rule.value">
|
|
|
- {{ rule.title }}
|
|
|
- </a-select-option>
|
|
|
- </a-select>
|
|
|
- </a-form-item>
|
|
|
-
|
|
|
- <!-- 音频选择器两列布局 -->
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="主题音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.main_subject.music_name"
|
|
|
- placeholder="请选择主题音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <!-- <a-col :span="12">
|
|
|
- <a-form-item label="顺序多选错误音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.ordered_multiple_err.music_name"
|
|
|
- placeholder="请选择顺序多选错误音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col> -->
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <!-- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="重复单击音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.has_click_single.music_name"
|
|
|
- placeholder="请选择重复点击音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="再次点击音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.still_have.music_name"
|
|
|
- placeholder="请选择再次点击音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="重复组点击音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.has_click_group.music_name"
|
|
|
- placeholder="请选择重复组点击音乐乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="等待30秒音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.wait_30s.music_name"
|
|
|
- placeholder="请选择等待30秒音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="等待90秒音乐:">
|
|
|
- <SelectAudioNew
|
|
|
- v-model="editForm.wait_90s.music_name"
|
|
|
- placeholder="请选择等待90秒音乐"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
-
|
|
|
- </a-col>
|
|
|
- </a-row> -->
|
|
|
- </a-form>
|
|
|
- </a-modal>
|
|
|
-
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -325,19 +147,14 @@ import { CardController } from '@/controller'
|
|
|
import {
|
|
|
LeftOutlined,
|
|
|
PlusOutlined,
|
|
|
- SmallDashOutlined,
|
|
|
- EditOutlined,
|
|
|
- DeleteOutlined,
|
|
|
- CheckCircleFilled,
|
|
|
- ExclamationCircleFilled,
|
|
|
- SoundOutlined,
|
|
|
InfoCircleOutlined
|
|
|
} from '@ant-design/icons-vue'
|
|
|
import { reactive, ref, PropType, computed } from 'vue'
|
|
|
import { message } from 'ant-design-vue'
|
|
|
import SelectAudioNew from './select-audio-new.vue'
|
|
|
import gameStage3 from './game-stage-3.vue'
|
|
|
-import { VueDraggableNext } from 'vue-draggable-next'
|
|
|
+import gameStage3Rule7 from './game-stage-3-rule7.vue'
|
|
|
+import FolderComponens from '@/components/ui/folder.vue'
|
|
|
|
|
|
const operationTip = `
|
|
|
1. 双击文件进入下一级<br>
|
|
|
@@ -366,6 +183,29 @@ const gameStateComputed = computed(() => {
|
|
|
return CardController.ruleList.toMap('value', 'title').get(rule) || ''
|
|
|
})
|
|
|
|
|
|
+// 转换rule=7时与其他规则ok_key格式不同的问题
|
|
|
+const transformJSON = computed(() => {
|
|
|
+ const _game_list = cardJson.value.game_list[currentGameIndex.value]
|
|
|
+
|
|
|
+ if (_game_list.rule === 7) {
|
|
|
+ // _game_list.ok_key = _game_list.ok_key.join(',')
|
|
|
+ const _ok_key = _game_list.items.map(item => {
|
|
|
+ return {
|
|
|
+ ok_key_value: item.ok_key
|
|
|
+ }
|
|
|
+ }).flat(2)
|
|
|
+ return {
|
|
|
+ ..._game_list,
|
|
|
+ items: [{
|
|
|
+ ..._game_list.items[0],
|
|
|
+ ok_key: _ok_key
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return _game_list
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
const emits = defineEmits(['update:open', 'step-selected', 'update:config'])
|
|
|
|
|
|
// 卡片category为21的json
|
|
|
@@ -378,151 +218,47 @@ const cardJson = computed({
|
|
|
const game1FormJson = {
|
|
|
rule: '',
|
|
|
main_subject: { music_name: '', is_break: 1 },
|
|
|
- ordered_multiple_err: { music_name: '', is_break: 1 },
|
|
|
- has_click_single: { music_name: '', is_break: 1 },
|
|
|
- still_have: { music_name: '', is_break: 1 },
|
|
|
- has_click_group: { music_name: '', is_break: 1 },
|
|
|
- wait_30s: { music_name: '', is_break: 1 },
|
|
|
- wait_90s: { music_name: '', is_break: 1 }
|
|
|
+ err_key_voice: [{ is_break: 1, music_name: '', value: '' }] as any,
|
|
|
+ ok_key_voice: [{ is_break: 1, music_name: '', value: '' }] as any,
|
|
|
+ items: []
|
|
|
}
|
|
|
|
|
|
// 当前层级:0表示顶级文件夹,1表示sub文件夹,2表示游戏配置
|
|
|
const currentLevel = ref(0)
|
|
|
|
|
|
-// 规则下拉选项
|
|
|
-const ruleOptions = CardController.ruleList
|
|
|
-
|
|
|
-// 编辑弹窗相关
|
|
|
-const editModalVisible = ref(false)
|
|
|
-const editingIndex = ref(-1)
|
|
|
-const editForm = reactive({
|
|
|
- rule: '',
|
|
|
- main_subject: { music_name: '', is_break: 1 },
|
|
|
- ordered_multiple_err: { music_name: '', is_break: 1 },
|
|
|
- has_click_single: { music_name: '', is_break: 1 },
|
|
|
- still_have: { music_name: '', is_break: 1 },
|
|
|
- has_click_group: { music_name: '', is_break: 1 },
|
|
|
- wait_30s: { music_name: '', is_break: 1 },
|
|
|
- wait_90s: { music_name: '', is_break: 1 }
|
|
|
-})
|
|
|
-
|
|
|
-// 编辑子项目弹窗相关
|
|
|
-const editSubItemModalVisible = ref(false)
|
|
|
-const editingSubItemIndex = ref(-1)
|
|
|
-const editSubItemForm = reactive({
|
|
|
- sub_subject: {
|
|
|
- music_name: '',
|
|
|
- mb: '',
|
|
|
- ok: '',
|
|
|
- ob: '',
|
|
|
- err: '',
|
|
|
- eb: ''
|
|
|
- },
|
|
|
- ok_key: [],
|
|
|
- err_key: [],
|
|
|
- ok_key_voice: {},
|
|
|
- err_key_voice: {}
|
|
|
-})
|
|
|
-
|
|
|
-// 子项目弹窗相关
|
|
|
-const subItemModalVisible = ref(false)
|
|
|
-const subItemForm = reactive({
|
|
|
- sub_subject: {
|
|
|
- music_name: '',
|
|
|
- mb: '',
|
|
|
- ok: '',
|
|
|
- ob: '',
|
|
|
- err: '',
|
|
|
- eb: ''
|
|
|
- },
|
|
|
- ok_key: [],
|
|
|
- err_key: [],
|
|
|
- ok_key_voice: {},
|
|
|
- err_key_voice: {}
|
|
|
-})
|
|
|
-
|
|
|
// 当前选中的游戏索引
|
|
|
const currentGameIndex = ref(0)
|
|
|
|
|
|
// 当前选中的子文件夹索引
|
|
|
const currentSubFolderIndex = ref(0)
|
|
|
|
|
|
-// 获取弹窗标题
|
|
|
-const getModalTitle = () => {
|
|
|
- switch (currentLevel.value) {
|
|
|
- case 0:
|
|
|
- return '游戏配置'
|
|
|
- case 1:
|
|
|
- return '游戏配置'
|
|
|
- case 2:
|
|
|
- return '游戏配置'
|
|
|
- default:
|
|
|
- return '游戏配置'
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
const createGameOne = () => {
|
|
|
- cardJson.value.game_list.push(JSON.parse(JSON.stringify(game1FormJson)))
|
|
|
-}
|
|
|
+ const newGameList: API.CardJson21['game_list'][0] = JSON.parse(JSON.stringify(cardJson.value.game_list[0]))
|
|
|
|
|
|
-// 校验游戏配置是否完整
|
|
|
-const validateGameConfig = (gameConfig: any) => {
|
|
|
- const requiredFields = [
|
|
|
- 'rule',
|
|
|
- 'main_subject.music_name'
|
|
|
- // 'ordered_multiple_err.music_name',
|
|
|
- // 'has_click_single.music_name',
|
|
|
- // 'still_have.music_name',
|
|
|
- // 'has_click_group.music_name',
|
|
|
- // 'wait_30s.music_name',
|
|
|
- // 'wait_90s.music_name'
|
|
|
- ]
|
|
|
-
|
|
|
- const missingFields: string[] = []
|
|
|
-
|
|
|
- requiredFields.forEach(field => {
|
|
|
- const fieldParts = field.split('.')
|
|
|
- let value = gameConfig
|
|
|
-
|
|
|
- for (const part of fieldParts) {
|
|
|
- value = value?.[part]
|
|
|
- }
|
|
|
+ newGameList.rule = ''
|
|
|
|
|
|
- if (!value || value === '') {
|
|
|
- missingFields.push(field)
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- return {
|
|
|
- isValid: missingFields.length === 0,
|
|
|
- missingFields
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 进入二级文件夹
|
|
|
-const enterFolder = (index: number) => {
|
|
|
- const gameConfig = cardJson.value.game_list[index]
|
|
|
- const validation = validateGameConfig(gameConfig)
|
|
|
+ newGameList.main_subject = { music_name: '', is_break: 1 }
|
|
|
+ newGameList.items = []
|
|
|
|
|
|
- // if (!validation.isValid) {
|
|
|
- // const fieldNames = {
|
|
|
- // rule: '规则',
|
|
|
- // 'main_subject.music_name': '主题音乐',
|
|
|
- // 'ordered_multiple_err.music_name': '顺序多选错误音乐',
|
|
|
- // 'has_click_single.music_name': '重复单击音乐',
|
|
|
- // 'still_have.music_name': '再次点击音乐',
|
|
|
- // 'has_click_group.music_name': '重复组点击音乐',
|
|
|
- // 'wait_30s.music_name': '等待30秒音乐',
|
|
|
- // 'wait_90s.music_name': '等待90秒音乐'
|
|
|
- // }
|
|
|
+ newGameList.err_key_voice = [{
|
|
|
+ is_break: 1,
|
|
|
+ music_name: '',
|
|
|
+ value: ''
|
|
|
+ }] as any
|
|
|
|
|
|
- // const missingFieldNames = validation.missingFields.map(field => fieldNames[field] || field)
|
|
|
+ newGameList.ok_key_voice = [{
|
|
|
+ is_break: 1,
|
|
|
+ music_name: '',
|
|
|
+ value: ''
|
|
|
+ }] as any
|
|
|
|
|
|
- // message.error(`游戏 ${index + 1} 配置不完整,缺少以下字段:${missingFieldNames.join('、').replaceAll('、', '、\n')}`)
|
|
|
+ cardJson.value.game_list.push(newGameList)
|
|
|
|
|
|
- // return
|
|
|
- // }
|
|
|
+ cardJson.value.game_list.push(JSON.parse(JSON.stringify(game1FormJson)))
|
|
|
+}
|
|
|
|
|
|
+// 进入二级文件夹
|
|
|
+const enterFolder = (index: number) => {
|
|
|
// 验证通过,创建 items 数组(如果不存在)
|
|
|
if (!cardJson.value.game_list[index].items) {
|
|
|
cardJson.value.game_list[index].items = []
|
|
|
@@ -536,65 +272,31 @@ const changedSteps = (steps: any) => {
|
|
|
console.log('changedSteps:', cardJson.value.game_list[currentGameIndex.value].items)
|
|
|
}
|
|
|
|
|
|
-const createSubItem = () => {
|
|
|
- // 重置表单并打开弹窗
|
|
|
- subItemForm.sub_subject.music_name = ''
|
|
|
- subItemForm.sub_subject.mb = ''
|
|
|
- subItemForm.sub_subject.ok = ''
|
|
|
- subItemForm.sub_subject.ob = ''
|
|
|
- subItemForm.sub_subject.err = ''
|
|
|
- subItemForm.sub_subject.eb = ''
|
|
|
- subItemForm.ok_key = []
|
|
|
- subItemForm.err_key = []
|
|
|
- subItemForm.ok_key_voice = {}
|
|
|
- subItemForm.err_key_voice = {}
|
|
|
-
|
|
|
- subItemModalVisible.value = true
|
|
|
-}
|
|
|
-
|
|
|
-// 新建二级文件夹
|
|
|
+// 新增子游戏
|
|
|
const handleSaveSubItem = () => {
|
|
|
- // 基础校验:必须选择子主题音乐
|
|
|
- // if (!subItemForm.sub_subject.music_name) {
|
|
|
- // message.warning('请选择子主题音乐')
|
|
|
- // return
|
|
|
- // }
|
|
|
-
|
|
|
- const index = currentGameIndex.value
|
|
|
- const currentGame = cardJson.value.game_list[index]
|
|
|
- if (!currentGame) {
|
|
|
- message.error('未选择有效的游戏')
|
|
|
- return
|
|
|
- }
|
|
|
+ // 构造 items 下的新对象(遵循 API.CardJson21[game_list].items 的结构)
|
|
|
+ const newItem: API.CardJson21['game_list'][0]['items'][0] = JSON.parse(JSON.stringify(cardJson.value.game_list[0].items[0]))
|
|
|
|
|
|
- // 确保 items 数组存在
|
|
|
- if (!currentGame.items) {
|
|
|
- currentGame.items = []
|
|
|
- }
|
|
|
+ newItem.ok_key = []
|
|
|
|
|
|
- // 构造 items 下的新对象(遵循 API.CardJson21[game_list].items 的结构)
|
|
|
- const newItem = {
|
|
|
- sub_subject: {
|
|
|
- music_name: subItemForm.sub_subject.music_name,
|
|
|
- mb: 1,
|
|
|
- ok: '',
|
|
|
- ob: 1,
|
|
|
- err: '',
|
|
|
- eb: 1
|
|
|
- },
|
|
|
- ok_key: [],
|
|
|
- err_key: [],
|
|
|
- ok_key_voice: {},
|
|
|
- err_key_voice: {}
|
|
|
+ newItem.err_key = []
|
|
|
+
|
|
|
+ newItem.sub_subject = {
|
|
|
+ music_name: '',
|
|
|
+ mb: 0,
|
|
|
+ ok: '',
|
|
|
+ ob: 0,
|
|
|
+ err: '',
|
|
|
+ eb: 0
|
|
|
}
|
|
|
|
|
|
- // 追加到 items
|
|
|
- currentGame.items.push(newItem)
|
|
|
- console.log('游戏类容', cardJson.value.game_list)
|
|
|
+ cardJson.value.game_list[currentGameIndex.value].ok_key_voice.push({
|
|
|
+ is_break: 1,
|
|
|
+ music_name: '',
|
|
|
+ value: ''
|
|
|
+ })
|
|
|
|
|
|
- // 关闭弹窗并重置关键字段,便于下次新增
|
|
|
- subItemModalVisible.value = false
|
|
|
- subItemForm.sub_subject.music_name = ''
|
|
|
+ cardJson.value.game_list[currentGameIndex.value].items.push(newItem)
|
|
|
}
|
|
|
|
|
|
// 进入卡片配置
|
|
|
@@ -625,85 +327,9 @@ const goBack = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 处理编辑游戏
|
|
|
-const handleEdit = (index: number) => {
|
|
|
- editingIndex.value = index
|
|
|
- // 将当前游戏数据复制到编辑表单
|
|
|
- Object.assign(editForm, JSON.parse(JSON.stringify(cardJson.value.game_list[index])))
|
|
|
- editModalVisible.value = true
|
|
|
-}
|
|
|
-
|
|
|
-// 处理删除游戏
|
|
|
-const handleDelete = (index: number) => {
|
|
|
- // 从游戏列表中删除指定索引的游戏
|
|
|
- cardJson.value.game_list.splice(index, 1)
|
|
|
-}
|
|
|
-
|
|
|
-// 处理编辑子项目
|
|
|
-const handleEditSubItem = (index: number) => {
|
|
|
- editingSubItemIndex.value = index
|
|
|
- // 将当前子项目数据复制到编辑表单
|
|
|
- const currentItem = cardJson.value.game_list[currentGameIndex.value].items[index]
|
|
|
- editSubItemForm.sub_subject.music_name = currentItem.sub_subject.music_name
|
|
|
- editSubItemForm.sub_subject.ok = currentItem.sub_subject.ok
|
|
|
- editSubItemForm.sub_subject.err = currentItem.sub_subject.err
|
|
|
- editSubItemModalVisible.value = true
|
|
|
- console.log(editForm)
|
|
|
-}
|
|
|
-
|
|
|
-// 处理删除子项目
|
|
|
-const handleDeleteSubItem = (index: number) => {
|
|
|
- // 从子项目列表中删除指定索引的项目
|
|
|
- cardJson.value.game_list[currentGameIndex.value].items.splice(index, 1)
|
|
|
-}
|
|
|
-
|
|
|
-// 保存子项目编辑
|
|
|
-const handleSaveSubItemEdit = () => {
|
|
|
- if (editingSubItemIndex.value >= 0) {
|
|
|
- // 将编辑表单的数据保存到子项目列表
|
|
|
- const currentItem = cardJson.value.game_list[currentGameIndex.value].items[editingSubItemIndex.value]
|
|
|
- currentItem.sub_subject.music_name = editSubItemForm.sub_subject.music_name || ''
|
|
|
- currentItem.sub_subject.ok = editSubItemForm.sub_subject.ok || ''
|
|
|
- currentItem.sub_subject.err = editSubItemForm.sub_subject.err || ''
|
|
|
- }
|
|
|
- editSubItemModalVisible.value = false
|
|
|
- editingSubItemIndex.value = -1
|
|
|
-}
|
|
|
-
|
|
|
-// 取消子项目编辑
|
|
|
-const handleCancelSubItemEdit = () => {
|
|
|
- editSubItemModalVisible.value = false
|
|
|
- editingSubItemIndex.value = -1
|
|
|
-}
|
|
|
-
|
|
|
-// 保存编辑
|
|
|
-const handleSaveEdit = () => {
|
|
|
- if (editingIndex.value >= 0) {
|
|
|
- // 将编辑表单的数据保存到游戏列表
|
|
|
- Object.assign(cardJson.value.game_list[editingIndex.value], JSON.parse(JSON.stringify(editForm)))
|
|
|
-
|
|
|
- if (!cardJson.value.game_list[editingIndex.value].touch_key) {
|
|
|
- cardJson.value.game_list[editingIndex.value].touch_key = [
|
|
|
- [{ value: 0, music_name: '', is_break: 1 }],
|
|
|
- [{ value: 1, music_name: '', is_break: 1 }],
|
|
|
- [{ value: 2, music_name: '', is_break: 1 }]
|
|
|
- ]
|
|
|
- }
|
|
|
- }
|
|
|
- editModalVisible.value = false
|
|
|
- editingIndex.value = -1
|
|
|
-}
|
|
|
-
|
|
|
-// 取消编辑
|
|
|
-const handleCancelEdit = () => {
|
|
|
- editModalVisible.value = false
|
|
|
- editingIndex.value = -1
|
|
|
-}
|
|
|
-
|
|
|
// 保存游戏配置
|
|
|
const saveGameConfig = async () => {
|
|
|
saveLoading.value = true
|
|
|
- // const defaultJson = await Car dController.getDefaultJson()
|
|
|
await CardController.add({
|
|
|
header: cardJson.value.header,
|
|
|
game_list: cardJson.value.game_list
|
|
|
@@ -746,119 +372,6 @@ const saveGameConfig = async () => {
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
- .config-game-item {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- cursor: pointer;
|
|
|
- border-radius: 8px;
|
|
|
- // transition: all 0.3s;
|
|
|
- background-color: #f5f5f5;
|
|
|
- padding: 0px !important;
|
|
|
- border: 1px solid #e9ecf1;
|
|
|
- box-sizing: border-box !important;
|
|
|
- margin-right: 16px;
|
|
|
- margin-bottom: 16px;
|
|
|
- position: relative;
|
|
|
- overflow: hidden;
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
|
-
|
|
|
- .status-icon {
|
|
|
- position: absolute;
|
|
|
- top: 8px;
|
|
|
- left: 8px;
|
|
|
- z-index: 10;
|
|
|
- font-size: 16px;
|
|
|
-
|
|
|
- .status-complete {
|
|
|
- color: #52c41a;
|
|
|
- }
|
|
|
-
|
|
|
- .status-incomplete {
|
|
|
- color: #ff4d4f;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .folder-icon {
|
|
|
- width: 86px;
|
|
|
- height: 86px;
|
|
|
- }
|
|
|
- .folder-footer {
|
|
|
- width: 100%;
|
|
|
- height: 32px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- border-top: 1px solid #e9ecf1;
|
|
|
- background-color: #fff;
|
|
|
- box-sizing: border-box;
|
|
|
- padding: 0 12px;
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
-
|
|
|
- .action-icon {
|
|
|
- cursor: pointer;
|
|
|
- opacity: 0;
|
|
|
- transition: opacity 0.3s;
|
|
|
- font-size: 16px;
|
|
|
- color: #8c8c8c;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- color: #1890ff;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .folder-info {
|
|
|
- width: 100%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- // padding: 12px 0;
|
|
|
- // margin-bottom: 32px;
|
|
|
-
|
|
|
- .folder-title {
|
|
|
- font-weight: 500;
|
|
|
- margin-bottom: 8px;
|
|
|
- font-size: 14px;
|
|
|
- color: #333;
|
|
|
- }
|
|
|
-
|
|
|
- .music-badge {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 4px;
|
|
|
- border-radius: 12px;
|
|
|
- font-size: 12px;
|
|
|
- .anticon {
|
|
|
- color: #1890ff;
|
|
|
- font-size: 12px;
|
|
|
- }
|
|
|
-
|
|
|
- .music-name {
|
|
|
- color: #1890ff;
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
- max-width: 80px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &:hover {
|
|
|
- scale: 1.02;
|
|
|
-
|
|
|
- .folder-footer .action-icon {
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- &:hover {
|
|
|
- scale: 1.02;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
.card-config-content {
|