Explorar o código

feat(store): 实现门店标签装修功能

- 新增门店标签装修页面基础结构与样式
- 实现左侧"基础信息—顾客必看"区域表单项
- 实现右侧"门店介绍-顾客想看"区域表单项
- 添加支持场景与特色的按钮切换交互逻辑
- 集成Element Plus组件库完成表单布局和交互
- 设置表单验证规则及提交处理函数
- 页面采用左右两栏布局并优化视觉样式
- 使用响应式数据管理表单状态与用户输入
- 提供保存功能并加入加载状态提示
- 添加页面初始化钩子用于后续接口调用
- 样式适配不同屏幕尺寸提升用户体验
spy hai 4 semanas
pai
achega
efcdb968d0
Modificáronse 1 ficheiros con 438 adicións e 4 borrados
  1. 438 4
      src/views/storeDecoration/storeLabel/index.vue

+ 438 - 4
src/views/storeDecoration/storeLabel/index.vue

@@ -1,7 +1,441 @@
-<script setup lang="ts"></script>
-
 <template>
-  <div>1</div>
+  <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-left">
+          <h3 class="section-title">基础信息—顾客必看</h3>
+
+          <!-- 卫生间 -->
+          <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>
+          </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>
+        </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>
+            </div>
+          </el-form-item>
+        </div>
+      </div>
+
+      <!-- 保存按钮 -->
+      <div class="form-footer">
+        <el-button type="primary" size="large" :loading="loading" @click="handleSubmit"> 保存 </el-button>
+      </div>
+    </el-form>
+  </div>
 </template>
 
-<style scoped lang="scss"></style>
+<script setup lang="ts">
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+// TODO: 导入门店标签相关的 API 接口
+// import { getStoreLabel, saveStoreLabel } 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 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 toggleFeature = (feature: string) => {
+  const index = formData.features.indexOf(feature);
+  if (index > -1) {
+    formData.features.splice(index, 1);
+  } else {
+    formData.features.push(feature);
+  }
+};
+
+// 页面初始化
+onMounted(async () => {
+  // TODO: 调用获取门店标签接口 getStoreLabel API
+  // const res = await getStoreLabel();
+  // if (res.data) {
+  //   Object.assign(formData, res.data);
+  // }
+});
+
+// 保存
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+
+  try {
+    await formRef.value.validate();
+  } catch (error) {
+    ElMessage.warning("请完善表单信息");
+    return;
+  }
+
+  loading.value = true;
+  try {
+    // TODO: 调用保存门店标签接口 saveStoreLabel API
+    // const params = {
+    //   ...formData
+    // };
+    // await saveStoreLabel(params);
+
+    ElMessage.success("保存成功");
+  } catch (error) {
+    ElMessage.error("保存失败,请重试");
+    console.error("保存失败:", error);
+  } finally {
+    loading.value = false;
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.store-label-container {
+  min-height: 100%;
+  padding: 20px;
+  background-color: white;
+  .store-label-form {
+    .form-content {
+      display: flex;
+      gap: 40px;
+      .form-left,
+      .form-right {
+        flex: 1;
+      }
+      .section-title {
+        padding-bottom: 12px;
+        margin-bottom: 24px;
+        font-size: 16px;
+        font-weight: bold;
+        color: #000000;
+        border-bottom: 1px solid #f0f0f0;
+      }
+      :deep(.el-form-item) {
+        margin-bottom: 24px;
+        .el-form-item__label {
+          font-weight: 500;
+          color: #606266;
+        }
+        .sub-options {
+          padding-left: 20px;
+          margin-top: 12px;
+          .sub-label {
+            margin-bottom: 8px;
+            font-size: 14px;
+            color: #909399;
+          }
+          :deep(.el-checkbox-group) {
+            display: flex;
+            flex-direction: column;
+            gap: 8px;
+          }
+        }
+        .button-group {
+          display: flex;
+          flex-wrap: wrap;
+          gap: 8px;
+          .el-button {
+            margin: 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;
+      justify-content: center;
+      padding-top: 24px;
+      margin-top: 40px;
+      border-top: 1px solid #f0f0f0;
+    }
+  }
+}
+</style>