|
|
@@ -1,9 +1,278 @@
|
|
|
<template>
|
|
|
-vue3
|
|
|
+ <div class="game-stage-3">
|
|
|
+ <div class="header">
|
|
|
+ <a-button type="primary" size="small" @click="showAddStepModal">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增步骤
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+<!-- -->
|
|
|
+
|
|
|
+ <VueDraggableNext
|
|
|
+ :list="steps"
|
|
|
+ group="people"
|
|
|
+ item-key="id"
|
|
|
+ :animation="300"
|
|
|
+ @end="onDragEnd"
|
|
|
+ >
|
|
|
+ <div v-for="(element, index) in steps" :key="element.id" class="step-item-wrapper">
|
|
|
+ <div
|
|
|
+ class="step-item"
|
|
|
+ :class="{ 'step-item-active': activeStepIndex === index }"
|
|
|
+ @click="selectStep(index)"
|
|
|
+ >
|
|
|
+ <div class="step-info">
|
|
|
+ <span class="step-number">步骤 {{ index + 1 }}</span>
|
|
|
+ <div class="step-details">
|
|
|
+ <span>按钮: <strong>{{ element.button_key }}</strong></span>
|
|
|
+ <span>音频: <strong>{{ element.audio_name }}</strong></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="step-actions">
|
|
|
+ <a-popconfirm
|
|
|
+ title="确定要删除这个步骤吗?"
|
|
|
+ ok-text="确定"
|
|
|
+ cancel-text="取消"
|
|
|
+ @confirm.stop="deleteGameStep(index)"
|
|
|
+ @cancel.stop
|
|
|
+ >
|
|
|
+ <delete-outlined @click.stop />
|
|
|
+ </a-popconfirm>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </VueDraggableNext>
|
|
|
+ <!-- <a-empty v-else description="暂无步骤,请点击新增步骤" /> -->
|
|
|
+
|
|
|
+ <a-modal
|
|
|
+ v-model:open="addStepModalVisible"
|
|
|
+ title="新增步骤"
|
|
|
+ width="600px"
|
|
|
+ @ok="handleAddStep"
|
|
|
+ @cancel="cancelAddStep"
|
|
|
+ wrap-class-name="game-stage-3-modal"
|
|
|
+ >
|
|
|
+ <a-form :model="newStepForm" layout="vertical">
|
|
|
+ <a-form-item label="选择按钮">
|
|
|
+ <div class="button-grid">
|
|
|
+ <a-button
|
|
|
+ v-for="btn in buttonOptions"
|
|
|
+ :key="btn"
|
|
|
+ :type="newStepForm.button_key === btn ? 'primary' : 'default'"
|
|
|
+ @click="selectButton(btn)"
|
|
|
+ >
|
|
|
+ {{ btn }}
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="选择语音">
|
|
|
+ <SelectAudioNew
|
|
|
+ v-model="newStepForm.audio_name"
|
|
|
+ placeholder="请选择步骤语音"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </a-modal>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
-<script lang='ts' setup >
|
|
|
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, computed, reactive } from 'vue'
|
|
|
+import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue'
|
|
|
+import { VueDraggableNext } from 'vue-draggable-next'
|
|
|
+import SelectAudioNew from './select-audio-new.vue'
|
|
|
+import { message } from 'ant-design-vue'
|
|
|
+
|
|
|
+interface Step {
|
|
|
+ id: number;
|
|
|
+ button_key: string;
|
|
|
+ audio_name: string;
|
|
|
+}
|
|
|
+
|
|
|
+interface Props {
|
|
|
+ item: API.CardJson21['game_list']['0']['items']['0'];
|
|
|
+}
|
|
|
+
|
|
|
+interface Person {
|
|
|
+ id: number
|
|
|
+ name: string
|
|
|
+}
|
|
|
+
|
|
|
+const list = ref<Person[]>([
|
|
|
+ { id: 1, name: 'John' },
|
|
|
+ { id: 2, name: 'Jane' },
|
|
|
+ { id: 3, name: 'Bob' }
|
|
|
+])
|
|
|
+
|
|
|
+// const props = defineProps<Props>()
|
|
|
+const emits = defineEmits(['update:modelValue'])
|
|
|
+
|
|
|
+const steps = ref<Step[]>([])
|
|
|
+
|
|
|
+// const steps = computed({
|
|
|
+// get: () => props.modelValue,
|
|
|
+// set: (value) => emits('update:modelValue', value)
|
|
|
+// })
|
|
|
+
|
|
|
+const addStepModalVisible = ref(false)
|
|
|
+const activeStepIndex = ref<number | null>(null)
|
|
|
+
|
|
|
+const newStepForm = reactive({
|
|
|
+ button_key: '',
|
|
|
+ audio_name: ''
|
|
|
+})
|
|
|
+
|
|
|
+const buttonOptions = Array.from({ length: 6 }, (_, i) => String.fromCharCode(65 + i))
|
|
|
+ .flatMap(row => Array.from({ length: 6 }, (_, j) => `${row}${j + 1}`))
|
|
|
+
|
|
|
+const showAddStepModal = () => {
|
|
|
+ resetNewStepForm()
|
|
|
+ addStepModalVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const selectButton = (btn: string) => {
|
|
|
+ newStepForm.button_key = btn
|
|
|
+}
|
|
|
+
|
|
|
+const handleAddStep = () => {
|
|
|
+ if (!newStepForm.button_key) {
|
|
|
+ message.error('请选择一个按钮')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!newStepForm.audio_name) {
|
|
|
+ message.error('请选择一个语音')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const newStep: Step = {
|
|
|
+ id: Date.now(),
|
|
|
+ button_key: newStepForm.button_key,
|
|
|
+ audio_name: newStepForm.audio_name
|
|
|
+ }
|
|
|
+
|
|
|
+ // const newSteps = [...(steps.value || []), newStep]
|
|
|
+
|
|
|
+ steps.value.push(newStep)
|
|
|
+ console.log(' steps.value:', steps.value)
|
|
|
+
|
|
|
+ // emits('update:modelValue', newSteps)
|
|
|
+ addStepModalVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const cancelAddStep = () => {
|
|
|
+ addStepModalVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const resetNewStepForm = () => {
|
|
|
+ newStepForm.button_key = ''
|
|
|
+ newStepForm.audio_name = ''
|
|
|
+}
|
|
|
+
|
|
|
+const deleteGameStep = (index: number) => {
|
|
|
+ if (steps.value) {
|
|
|
+ steps.value.splice(index, 1)
|
|
|
+ emits('update:modelValue', steps.value)
|
|
|
+ if (activeStepIndex.value === index) {
|
|
|
+ activeStepIndex.value = null
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const selectStep = (index: number) => {
|
|
|
+ activeStepIndex.value = index
|
|
|
+}
|
|
|
+
|
|
|
+const onDragEnd = () => {
|
|
|
+ // draggable already updated the model
|
|
|
+ emits('update:modelValue', steps.value)
|
|
|
+}
|
|
|
</script>
|
|
|
-<style lang='less' scoped >
|
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
+.game-stage-3 {
|
|
|
+ .header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-item-wrapper {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 16px;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ border-radius: 8px;
|
|
|
+ cursor: grab;
|
|
|
+ background-color: #fafafa;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ border-color: #40a9ff;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-item-active {
|
|
|
+ border-color: #1890ff;
|
|
|
+ background-color: #e6f7ff;
|
|
|
+ box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-info {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 24px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-number {
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-details {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #555;
|
|
|
+
|
|
|
+ span > strong {
|
|
|
+ color: #333;
|
|
|
+ margin-left: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-actions {
|
|
|
+ cursor: pointer;
|
|
|
+ color: #ff4d4f;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="less">
|
|
|
+.game-stage-3-modal .button-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(6, 1fr);
|
|
|
+ gap: 10px;
|
|
|
+ padding: 16px;
|
|
|
+ border-radius: 6px;
|
|
|
+ background-color: #f7f7f7;
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+}
|
|
|
+
|
|
|
+.game-stage-3-modal .button-grid .ant-btn {
|
|
|
+ padding: 0;
|
|
|
+ height: 40px;
|
|
|
+ font-weight: 500;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
</style>
|