|
|
@@ -1,346 +1,310 @@
|
|
|
<template>
|
|
|
<div class="store-label-container">
|
|
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="140px" class="store-label-form">
|
|
|
- <div class="form-content">
|
|
|
- <!-- 左侧:基础信息—顾客必看 -->
|
|
|
+ <!-- 头部:固定标题 -->
|
|
|
+ <div class="form-header">
|
|
|
<div class="form-left">
|
|
|
<h3 class="section-title">基础信息—顾客必看</h3>
|
|
|
+ </div>
|
|
|
+ <div class="form-right">
|
|
|
+ <h3 class="section-title">门店介绍-顾客想看</h3>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <!-- 卫生间 -->
|
|
|
- <el-form-item label="卫生间">
|
|
|
- <el-radio-group v-model="formData.restroom.has">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- <div v-if="formData.restroom.has" class="sub-options">
|
|
|
- <div class="sub-label">请选择卫生间类型</div>
|
|
|
- <el-checkbox-group v-model="formData.restroom.types">
|
|
|
- <el-checkbox label="商场卫生间"> 商场卫生间 </el-checkbox>
|
|
|
- <el-checkbox label="室内卫生间"> 室内卫生间 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 免费WIFI -->
|
|
|
- <el-form-item label="免费WIFI">
|
|
|
- <el-radio-group v-model="formData.freeWifi">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 室内空调 -->
|
|
|
- <el-form-item label="室内空调">
|
|
|
- <el-radio-group v-model="formData.airConditioning">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 停车场 -->
|
|
|
- <el-form-item label="停车场">
|
|
|
- <el-radio-group v-model="formData.parking.has">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- <div v-if="formData.parking.has" class="sub-options">
|
|
|
- <div class="sub-label">请选择停车场类型</div>
|
|
|
- <el-checkbox-group v-model="formData.parking.types">
|
|
|
- <el-checkbox label="免费停车场"> 免费停车场 </el-checkbox>
|
|
|
- <el-checkbox label="收费停车场"> 收费停车场 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 大桌 -->
|
|
|
- <el-form-item label="大桌">
|
|
|
- <el-radio-group v-model="formData.largeTable.has">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- <div v-if="formData.largeTable.has" class="sub-options">
|
|
|
- <div class="sub-label">请选择大桌类型</div>
|
|
|
- <el-checkbox-group v-model="formData.largeTable.types">
|
|
|
- <el-checkbox label="10人以上大桌"> 10人以上大桌 </el-checkbox>
|
|
|
- <el-checkbox label="10人以下大桌"> 10人以下大桌 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 儿童服务 -->
|
|
|
- <el-form-item label="儿童服务">
|
|
|
- <el-radio-group v-model="formData.childrenService">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 宠物政策 -->
|
|
|
- <el-form-item label="宠物政策">
|
|
|
- <el-radio-group v-model="formData.petPolicy">
|
|
|
- <el-radio value="可携带宠物"> 可携带宠物 </el-radio>
|
|
|
- <el-radio value="不可携带宠物"> 不可携带宠物 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 包厢 -->
|
|
|
- <el-form-item label="包厢">
|
|
|
- <el-radio-group v-model="formData.privateRoom.has">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- <div v-if="formData.privateRoom.has" class="sub-options">
|
|
|
- <div class="sub-label">请选择包厢类型</div>
|
|
|
- <el-checkbox-group v-model="formData.privateRoom.types">
|
|
|
- <el-checkbox label="10人以上包厢"> 10人以上包厢 </el-checkbox>
|
|
|
- <el-checkbox label="10人以下包厢"> 10人以下包厢 </el-checkbox>
|
|
|
- <el-checkbox label="双人包厢"> 双人包厢 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 支持场景 -->
|
|
|
- <el-form-item label="支持场景">
|
|
|
- <div class="button-group">
|
|
|
- <el-button
|
|
|
- v-for="scene in sceneOptions"
|
|
|
- :key="scene.value"
|
|
|
- :type="formData.supportedScenes.includes(scene.value) ? 'primary' : 'default'"
|
|
|
- @click="toggleScene(scene.value)"
|
|
|
- >
|
|
|
- {{ scene.label }}
|
|
|
- </el-button>
|
|
|
+ <!-- 中间:可滚动的内容区域 -->
|
|
|
+ <div class="form-content">
|
|
|
+ <!-- 左侧:基础信息 -->
|
|
|
+ <div class="form-left">
|
|
|
+ <!-- 动态渲染标签卡片 -->
|
|
|
+ <template v-for="(tagGroup, groupIndex) in leftTagGroups" :key="groupIndex">
|
|
|
+ <div class="tag-card">
|
|
|
+ <div class="card-header">
|
|
|
+ <span class="header-icon" />
|
|
|
+ <span class="header-title">{{ tagGroup.labelName }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <template v-for="(item, itemIndex) in tagGroup.list" :key="itemIndex">
|
|
|
+ <!-- radioDouble类型:组合按钮(例如:卫生间、停车场、大桌、包厢) -->
|
|
|
+ <div v-if="item.labelButtonType === 'radioDouble'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <div class="radio-double-wrapper">
|
|
|
+ <div class="first-option">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <!-- 判断卫生间、停车场、大桌、包厢,这几项只有选择"有"的时候才显示下方的选项 -->
|
|
|
+ <div
|
|
|
+ v-if="
|
|
|
+ (item.field_1 && formData[item.field_1] == 1) ||
|
|
|
+ (item.field_5 && formData[item.field_5] == 1) ||
|
|
|
+ (item.field_7 && formData[item.field_7] == 1) ||
|
|
|
+ (item.field_11 && formData[item.field_11] == 1)
|
|
|
+ "
|
|
|
+ class="second-option"
|
|
|
+ >
|
|
|
+ <div class="sub-label">
|
|
|
+ {{ item.tips }}
|
|
|
+ </div>
|
|
|
+ <el-radio-group v-if="item.field_2" v-model="formData[item.field_2]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_2"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- radio类型:单选有无(例如:wifi、室内空调等) -->
|
|
|
+ <div v-if="item.labelButtonType === 'radio'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label" :class="{ 'vertical-layout': item.label === '吸烟' }">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- radios类型:单选(例如:位置类型、装修风格等) -->
|
|
|
+ <div v-if="item.labelButtonType === 'radios'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- checkbox类型:多选(多列显示) -->
|
|
|
+ <div v-if="item.labelButtonType === 'checkbox'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <div class="checkbox-grid">
|
|
|
+ <el-checkbox-group v-model="formData[item.field_1]" @change="handleCheckboxChange(item.field_1, $event)">
|
|
|
+ <el-checkbox
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 分隔线 -->
|
|
|
+ <el-divider v-if="itemIndex !== tagGroup.list.length - 1 && item.label" />
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 等位区 -->
|
|
|
- <el-form-item label="等位区">
|
|
|
- <el-radio-group v-model="formData.waitingArea">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 吸烟 -->
|
|
|
- <el-form-item label="吸烟">
|
|
|
- <el-radio-group v-model="formData.smoking">
|
|
|
- <el-radio value="可吸烟"> 可吸烟 </el-radio>
|
|
|
- <el-radio value="不可吸烟"> 不可吸烟 </el-radio>
|
|
|
- <el-radio value="专属吸烟区"> 专属吸烟区 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 门店服务 -->
|
|
|
- <el-form-item label="门店服务">
|
|
|
- <el-checkbox-group v-model="formData.storeServices">
|
|
|
- <el-checkbox label="在线订座"> 在线订座 </el-checkbox>
|
|
|
- <el-checkbox label="在线排队"> 在线排队 </el-checkbox>
|
|
|
- <el-checkbox label="线下取号"> 线下取号 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </el-form-item>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 右侧:门店介绍-顾客想看 -->
|
|
|
+ <!-- 右侧:门店介绍 -->
|
|
|
<div class="form-right">
|
|
|
- <h3 class="section-title">门店介绍-顾客想看</h3>
|
|
|
-
|
|
|
- <!-- 位置类型 -->
|
|
|
- <el-form-item label="位置类型">
|
|
|
- <el-radio-group v-model="formData.locationType">
|
|
|
- <el-radio value="深巷小店"> 深巷小店 </el-radio>
|
|
|
- <el-radio value="沿街"> 沿街 </el-radio>
|
|
|
- <el-radio value="商场餐厅"> 商场餐厅 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 交通 -->
|
|
|
- <el-form-item label="交通">
|
|
|
- <el-checkbox-group v-model="formData.transportation">
|
|
|
- <el-checkbox label="近地铁/地铁直达"> 近地铁/地铁直达 </el-checkbox>
|
|
|
- <el-checkbox label="近机场"> 近机场 </el-checkbox>
|
|
|
- <el-checkbox label="近商场"> 近商场 </el-checkbox>
|
|
|
- <el-checkbox label="近公交"> 近公交 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 景观特色 -->
|
|
|
- <el-form-item label="景观特色">
|
|
|
- <el-checkbox-group v-model="formData.scenicFeatures">
|
|
|
- <el-checkbox label="江景"> 江景 </el-checkbox>
|
|
|
- <el-checkbox label="湖景"> 湖景 </el-checkbox>
|
|
|
- <el-checkbox label="海景"> 海景 </el-checkbox>
|
|
|
- <el-checkbox label="山景"> 山景 </el-checkbox>
|
|
|
- <el-checkbox label="高空城景"> 高空城景 </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 室内景观 -->
|
|
|
- <el-form-item label="室内景观">
|
|
|
- <el-radio-group v-model="formData.indoorScenery">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 露台 -->
|
|
|
- <el-form-item label="露台">
|
|
|
- <el-radio-group v-model="formData.terrace">
|
|
|
- <el-radio :value="true"> 有 </el-radio>
|
|
|
- <el-radio :value="false"> 无 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 装修风格 -->
|
|
|
- <el-form-item label="装修风格">
|
|
|
- <el-radio-group v-model="formData.decorationStyle">
|
|
|
- <el-radio value="禅意餐厅"> 禅意餐厅 </el-radio>
|
|
|
- <el-radio value="异国风情"> 异国风情 </el-radio>
|
|
|
- <el-radio value="复古风格"> 复古风格 </el-radio>
|
|
|
- <el-radio value="现代"> 现代 </el-radio>
|
|
|
- <el-radio value="小清新风格"> 小清新风格 </el-radio>
|
|
|
- <el-radio value="二次元风"> 二次元风 </el-radio>
|
|
|
- <el-radio value="工业风"> 工业风 </el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
-
|
|
|
- <!-- 特色 -->
|
|
|
- <el-form-item label="特色">
|
|
|
- <div class="button-group">
|
|
|
- <el-button
|
|
|
- v-for="feature in featureOptions"
|
|
|
- :key="feature.value"
|
|
|
- :type="formData.features.includes(feature.value) ? 'primary' : 'default'"
|
|
|
- @click="toggleFeature(feature.value)"
|
|
|
- >
|
|
|
- {{ feature.label }}
|
|
|
- </el-button>
|
|
|
+ <!-- 动态渲染标签卡片 -->
|
|
|
+ <template v-for="(tagGroup, groupIndex) in rightTagGroups" :key="groupIndex">
|
|
|
+ <div class="tag-card">
|
|
|
+ <div class="card-header">
|
|
|
+ <span class="header-icon" />
|
|
|
+ <span class="header-title">{{ tagGroup.labelName }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <template v-for="(item, itemIndex) in tagGroup.list" :key="itemIndex">
|
|
|
+ <!-- radioDouble类型:组合按钮 -->
|
|
|
+ <div v-if="item.labelButtonType === 'radioDouble'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <div class="radio-double-wrapper">
|
|
|
+ <div class="first-option">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="
|
|
|
+ (item.field_1 && formData[item.field_1] == 1) ||
|
|
|
+ (item.field_5 && formData[item.field_5] == 1) ||
|
|
|
+ (item.field_7 && formData[item.field_7] == 1) ||
|
|
|
+ (item.field_11 && formData[item.field_11] == 1)
|
|
|
+ "
|
|
|
+ class="second-option"
|
|
|
+ >
|
|
|
+ <div class="sub-label">
|
|
|
+ {{ item.tips }}
|
|
|
+ </div>
|
|
|
+ <el-radio-group v-if="item.field_2" v-model="formData[item.field_2]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_2"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- radio类型:单选有无 -->
|
|
|
+ <div v-if="item.labelButtonType === 'radio'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label" :class="{ 'vertical-layout': item.label === '吸烟' }">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- radios类型:单选 -->
|
|
|
+ <div v-if="item.labelButtonType === 'radios'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <el-radio-group v-model="formData[item.field_1]" @change="handleFormChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- checkbox类型:多选(多列显示) -->
|
|
|
+ <div v-if="item.labelButtonType === 'checkbox'" class="form-item-wrapper">
|
|
|
+ <el-form-item :label="item.label">
|
|
|
+ <div class="checkbox-grid">
|
|
|
+ <el-checkbox-group v-model="formData[item.field_1]" @change="handleCheckboxChange(item.field_1, $event)">
|
|
|
+ <el-checkbox
|
|
|
+ v-for="(option, optIndex) in item.labelButtonOption_1"
|
|
|
+ :key="optIndex"
|
|
|
+ :label="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ >
|
|
|
+ {{ option.name }}
|
|
|
+ </el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 分隔线 -->
|
|
|
+ <el-divider v-if="itemIndex !== tagGroup.list.length - 1 && item.label" />
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </el-form-item>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 保存按钮 -->
|
|
|
<div class="form-footer">
|
|
|
- <el-button type="primary" size="large" :loading="loading" @click="handleSubmit"> 保存 </el-button>
|
|
|
+ <el-button type="primary" size="large" :loading="loading" @click="handleSave"> 保存 </el-button>
|
|
|
</div>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, reactive, onMounted } from "vue";
|
|
|
+import { ref, reactive, computed, onMounted } from "vue";
|
|
|
import { ElMessage } from "element-plus";
|
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
|
-// TODO: 导入门店标签相关的 API 接口
|
|
|
-// import { getStoreLabel, saveStoreLabel } from "@/api/modules/storeDecoration";
|
|
|
+import { localGet } from "@/utils";
|
|
|
+import { getAllTagType, getAllTag, saveTag } from "@/api/modules/storeDecoration";
|
|
|
|
|
|
const loading = ref(false);
|
|
|
const formRef = ref<FormInstance>();
|
|
|
|
|
|
-// 支持场景选项
|
|
|
-const sceneOptions = [
|
|
|
- { label: "多人聚餐", value: "多人聚餐" },
|
|
|
- { label: "生日聚会", value: "生日聚会" },
|
|
|
- { label: "商务宴请", value: "商务宴请" },
|
|
|
- { label: "情侣约会", value: "情侣约会" },
|
|
|
- { label: "带娃吃饭", value: "带娃吃饭" },
|
|
|
- { label: "闺蜜小聚", value: "闺蜜小聚" }
|
|
|
-];
|
|
|
-
|
|
|
-// 特色选项
|
|
|
-const featureOptions = [
|
|
|
- { label: "充电宝", value: "充电宝" },
|
|
|
- { label: "充电线", value: "充电线" }
|
|
|
-];
|
|
|
-
|
|
|
-// 表单数据
|
|
|
-const formData = reactive({
|
|
|
- // 卫生间
|
|
|
- restroom: {
|
|
|
- has: true,
|
|
|
- types: ["商场卫生间"] as string[]
|
|
|
- },
|
|
|
- // 免费WIFI
|
|
|
- freeWifi: true,
|
|
|
- // 室内空调
|
|
|
- airConditioning: true,
|
|
|
- // 停车场
|
|
|
- parking: {
|
|
|
- has: true,
|
|
|
- types: ["免费停车场"] as string[]
|
|
|
- },
|
|
|
- // 大桌
|
|
|
- largeTable: {
|
|
|
- has: true,
|
|
|
- types: ["10人以上大桌"] as string[]
|
|
|
- },
|
|
|
- // 儿童服务
|
|
|
- childrenService: true,
|
|
|
- // 宠物政策
|
|
|
- petPolicy: "可携带宠物",
|
|
|
- // 包厢
|
|
|
- privateRoom: {
|
|
|
- has: true,
|
|
|
- types: ["10人以上包厢"] as string[]
|
|
|
- },
|
|
|
- // 支持场景
|
|
|
- supportedScenes: ["多人聚餐", "生日聚会", "商务宴请", "情侣约会", "带娃吃饭", "闺蜜小聚"] as string[],
|
|
|
- // 等位区
|
|
|
- waitingArea: true,
|
|
|
- // 吸烟
|
|
|
- smoking: "可吸烟",
|
|
|
- // 门店服务
|
|
|
- storeServices: ["在线订座"] as string[],
|
|
|
- // 位置类型
|
|
|
- locationType: "深巷小店",
|
|
|
- // 交通
|
|
|
- transportation: ["近地铁/地铁直达"] as string[],
|
|
|
- // 景观特色
|
|
|
- scenicFeatures: ["江景"] as string[],
|
|
|
- // 室内景观
|
|
|
- indoorScenery: true,
|
|
|
- // 露台
|
|
|
- terrace: true,
|
|
|
- // 装修风格
|
|
|
- decorationStyle: "禅意餐厅",
|
|
|
- // 特色
|
|
|
- features: ["充电宝", "充电线"] as string[]
|
|
|
+// 标签分组数据
|
|
|
+const tagGroups = ref<
|
|
|
+ Array<{
|
|
|
+ labelName: string;
|
|
|
+ list: Array<{
|
|
|
+ label: string;
|
|
|
+ labelButtonType: "radioDouble" | "radio" | "radios" | "checkbox";
|
|
|
+ field_1: string;
|
|
|
+ field_2?: string;
|
|
|
+ field_5?: string;
|
|
|
+ field_7?: string;
|
|
|
+ field_11?: string;
|
|
|
+ tips?: string;
|
|
|
+ labelButtonOption_1: Array<{ name: string; value: string | number }>;
|
|
|
+ labelButtonOption_2?: Array<{ name: string; value: string | number }>;
|
|
|
+ }>;
|
|
|
+ }>
|
|
|
+>([]);
|
|
|
+
|
|
|
+// 左侧标签组(基础信息)
|
|
|
+const leftTagGroups = computed(() => {
|
|
|
+ return tagGroups.value.filter(group => group.labelName === "基础设施");
|
|
|
});
|
|
|
|
|
|
-// 表单校验规则(根据实际需求添加)
|
|
|
+// 右侧标签组(门店介绍)
|
|
|
+const rightTagGroups = computed(() => {
|
|
|
+ return tagGroups.value.filter(group => group.labelName === "门店介绍");
|
|
|
+});
|
|
|
+
|
|
|
+// 表单数据(动态字段)
|
|
|
+const formData = reactive<Record<string, any>>({});
|
|
|
+
|
|
|
+// 表单校验规则
|
|
|
const rules = reactive<FormRules>({});
|
|
|
|
|
|
-// 切换支持场景
|
|
|
-const toggleScene = (scene: string) => {
|
|
|
- const index = formData.supportedScenes.indexOf(scene);
|
|
|
- if (index > -1) {
|
|
|
- formData.supportedScenes.splice(index, 1);
|
|
|
- } else {
|
|
|
- formData.supportedScenes.push(scene);
|
|
|
- }
|
|
|
+// 处理表单变化
|
|
|
+const handleFormChange = () => {
|
|
|
+ // 表单数据变化时的处理逻辑
|
|
|
};
|
|
|
|
|
|
-// 切换特色
|
|
|
-const toggleFeature = (feature: string) => {
|
|
|
- const index = formData.features.indexOf(feature);
|
|
|
- if (index > -1) {
|
|
|
- formData.features.splice(index, 1);
|
|
|
- } else {
|
|
|
- formData.features.push(feature);
|
|
|
- }
|
|
|
+// 处理多选框变化(保持为数组)
|
|
|
+const handleCheckboxChange = (fieldName: string, value: any[]) => {
|
|
|
+ formData[fieldName] = value;
|
|
|
+ handleFormChange();
|
|
|
};
|
|
|
|
|
|
-// 页面初始化
|
|
|
-onMounted(async () => {
|
|
|
- // TODO: 调用获取门店标签接口 getStoreLabel API
|
|
|
- // const res = await getStoreLabel();
|
|
|
- // if (res.data) {
|
|
|
- // Object.assign(formData, res.data);
|
|
|
- // }
|
|
|
-});
|
|
|
-
|
|
|
-// 保存
|
|
|
-const handleSubmit = async () => {
|
|
|
+// 保存数据
|
|
|
+const handleSave = async () => {
|
|
|
if (!formRef.value) return;
|
|
|
|
|
|
try {
|
|
|
@@ -352,90 +316,327 @@ const handleSubmit = async () => {
|
|
|
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
- // TODO: 调用保存门店标签接口 saveStoreLabel API
|
|
|
- // const params = {
|
|
|
- // ...formData
|
|
|
- // };
|
|
|
- // await saveStoreLabel(params);
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
+ if (!storeId) {
|
|
|
+ ElMessage.error("未找到店铺ID");
|
|
|
+ loading.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- ElMessage.success("保存成功");
|
|
|
- } catch (error) {
|
|
|
- ElMessage.error("保存失败,请重试");
|
|
|
+ // 调用保存门店标签接口 saveTag API
|
|
|
+ // 在保存前,将checkbox类型的数组字段转换为字符串
|
|
|
+ const params: any = {
|
|
|
+ ...formData,
|
|
|
+ storeId: Number(storeId)
|
|
|
+ };
|
|
|
+
|
|
|
+ // 遍历所有checkbox字段,将数组转换为逗号分隔的字符串
|
|
|
+ tagGroups.value.forEach(group => {
|
|
|
+ group.list.forEach(item => {
|
|
|
+ if (item.labelButtonType === "checkbox" && item.field_1) {
|
|
|
+ const fieldName = item.field_1;
|
|
|
+ if (Array.isArray(params[fieldName])) {
|
|
|
+ params[fieldName] = params[fieldName].join(",");
|
|
|
+ } else if (!params[fieldName]) {
|
|
|
+ params[fieldName] = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const res: any = await saveTag(params);
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
+ ElMessage.success("保存成功");
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res?.msg || "保存失败");
|
|
|
+ }
|
|
|
+ } catch (error: any) {
|
|
|
console.error("保存失败:", error);
|
|
|
+ ElMessage.error(error?.msg || "保存失败,请重试");
|
|
|
} finally {
|
|
|
loading.value = false;
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+// 初始化表单数据(从接口获取已保存的数据)
|
|
|
+const initFormData = async () => {
|
|
|
+ try {
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
+ if (!storeId) {
|
|
|
+ console.warn("未找到店铺ID");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用获取门店标签数据接口 getAllTag API
|
|
|
+ const res: any = await getAllTag({ storeId: Number(storeId) });
|
|
|
+ if (res && (res.code === 200 || res.code === "200") && res.data) {
|
|
|
+ // 将接口返回的数据合并到formData中
|
|
|
+ Object.assign(formData, res.data);
|
|
|
+ // 处理checkbox类型的数据(如果是字符串,需要转换为数组)
|
|
|
+ tagGroups.value.forEach(group => {
|
|
|
+ group.list.forEach(item => {
|
|
|
+ if (item.labelButtonType === "checkbox" && item.field_1) {
|
|
|
+ const fieldName = item.field_1;
|
|
|
+ const value = formData[fieldName];
|
|
|
+ if (value && typeof value === "string") {
|
|
|
+ formData[fieldName] = value.split(",").filter(Boolean);
|
|
|
+ } else if (!value) {
|
|
|
+ // 如果字段不存在,初始化为空数组
|
|
|
+ formData[fieldName] = [];
|
|
|
+ }
|
|
|
+ } else if (item.field_1 && formData[item.field_1] === undefined) {
|
|
|
+ // 其他类型字段如果不存在,初始化为空值
|
|
|
+ formData[item.field_1] = "";
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取门店标签数据失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 初始化标签选项(从接口获取标签列表)
|
|
|
+const initTagOptions = async () => {
|
|
|
+ try {
|
|
|
+ // 从userInfo中获取businessSection
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
+ const businessSection = userInfo.businessSection || localGet("businessSection") || "";
|
|
|
+
|
|
|
+ if (!businessSection) {
|
|
|
+ console.warn("未找到businessSection参数");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用获取标签列表接口 getAllTagType API
|
|
|
+ const res: any = await getAllTagType({ businessSection });
|
|
|
+ if (res && (res.code === 200 || res.code === "200") && res.data) {
|
|
|
+ const dataList = Array.isArray(res.data) ? res.data : [];
|
|
|
+
|
|
|
+ // 处理checkbox类型的已选状态
|
|
|
+ dataList.forEach((item: any) => {
|
|
|
+ if (item.labelButtonType === "checkbox") {
|
|
|
+ item.labelButtonOption_1.forEach((option: any) => {
|
|
|
+ if (formData[item.field_1] && formData[item.field_1].indexOf(option.value) !== -1) {
|
|
|
+ option.isChecked = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 按labelName分组
|
|
|
+ const grouped = dataList.reduce((acc: any[], current: any) => {
|
|
|
+ const existing = acc.find(item => item.labelName === current.labelName);
|
|
|
+ if (existing) {
|
|
|
+ existing.list.push(current);
|
|
|
+ } else {
|
|
|
+ acc.push({
|
|
|
+ labelName: current.labelName,
|
|
|
+ list: [current]
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return acc;
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ tagGroups.value = grouped;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取标签列表失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 页面初始化
|
|
|
+onMounted(async () => {
|
|
|
+ // 先初始化标签选项
|
|
|
+ await initTagOptions();
|
|
|
+ // 再初始化表单数据(需要先有标签选项,才能正确处理checkbox数据)
|
|
|
+ await initFormData();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.store-label-container {
|
|
|
- min-height: 100%;
|
|
|
+ box-sizing: border-box;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 85vh;
|
|
|
padding: 20px;
|
|
|
+ overflow: hidden;
|
|
|
background-color: white;
|
|
|
.store-label-form {
|
|
|
- .form-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ // 头部:固定标题
|
|
|
+ .form-header {
|
|
|
+ z-index: 10;
|
|
|
display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
gap: 40px;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ background-color: white;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
.form-left,
|
|
|
.form-right {
|
|
|
flex: 1;
|
|
|
+ .section-title {
|
|
|
+ padding-bottom: 12px;
|
|
|
+ margin-bottom: 0;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #000000;
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
}
|
|
|
- .section-title {
|
|
|
- padding-bottom: 12px;
|
|
|
- margin-bottom: 24px;
|
|
|
- font-size: 16px;
|
|
|
- font-weight: bold;
|
|
|
- color: #000000;
|
|
|
- border-bottom: 1px solid #f0f0f0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 中间:可滚动的内容区域
|
|
|
+ .form-content {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ gap: 40px;
|
|
|
+ min-height: 0;
|
|
|
+ padding-top: 20px;
|
|
|
+ padding-right: 10px;
|
|
|
+ margin-right: -10px;
|
|
|
+ overflow: hidden auto;
|
|
|
+
|
|
|
+ // 自定义滚动条样式
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 8px;
|
|
|
}
|
|
|
- :deep(.el-form-item) {
|
|
|
- margin-bottom: 24px;
|
|
|
- .el-form-item__label {
|
|
|
- font-weight: 500;
|
|
|
- color: #606266;
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: #c1c1c1;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ background: #a8a8a8;
|
|
|
}
|
|
|
- .sub-options {
|
|
|
- padding-left: 20px;
|
|
|
- margin-top: 12px;
|
|
|
- .sub-label {
|
|
|
- margin-bottom: 8px;
|
|
|
- font-size: 14px;
|
|
|
- color: #909399;
|
|
|
- }
|
|
|
- :deep(.el-checkbox-group) {
|
|
|
+ }
|
|
|
+ .form-left,
|
|
|
+ .form-right {
|
|
|
+ flex: 1;
|
|
|
+ .tag-card {
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 6%);
|
|
|
+ .card-header {
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #334154;
|
|
|
+ .header-icon {
|
|
|
+ display: inline-block;
|
|
|
+ width: 4px;
|
|
|
+ height: 18px;
|
|
|
+ margin-right: 12px;
|
|
|
+ background-color: #6c8ff8;
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
+ .header-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #334154;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- .button-group {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 8px;
|
|
|
- .el-button {
|
|
|
- margin: 0;
|
|
|
+ .card-content {
|
|
|
+ padding: 20px 10px;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 -2px 12px 0 rgb(86 125 244 / 5%);
|
|
|
+ .form-item-wrapper {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- :deep(.el-radio-group) {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 12px;
|
|
|
- }
|
|
|
- :deep(.el-checkbox-group) {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 8px;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
.form-footer {
|
|
|
display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
justify-content: center;
|
|
|
- padding-top: 24px;
|
|
|
- margin-top: 40px;
|
|
|
+ padding: 24px 0;
|
|
|
+ margin-top: 20px;
|
|
|
+ background-color: white;
|
|
|
border-top: 1px solid #f0f0f0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// 表单样式
|
|
|
+:deep(.el-form-item) {
|
|
|
+ margin-bottom: 24px;
|
|
|
+ .el-form-item__label {
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ &.vertical-layout {
|
|
|
+ .el-form-item__content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.radio-double-wrapper {
|
|
|
+ .first-option {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+ .second-option {
|
|
|
+ padding: 20px;
|
|
|
+ margin-top: 12px;
|
|
|
+ background: #f8f9ff;
|
|
|
+ border-radius: 8px;
|
|
|
+ .sub-label {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #666666;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.el-radio-group) {
|
|
|
+ display: flex;
|
|
|
+ flex-flow: row wrap;
|
|
|
+ gap: 12px;
|
|
|
+ width: 100%;
|
|
|
+ .el-radio {
|
|
|
+ margin-right: 0;
|
|
|
+ margin-bottom: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ .el-radio__label {
|
|
|
+ padding-left: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.el-checkbox-group) {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+.checkbox-grid {
|
|
|
+ :deep(.el-checkbox-group) {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
+ gap: 12px 20px;
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.el-divider) {
|
|
|
+ margin: 20px 0;
|
|
|
+}
|
|
|
</style>
|