Browse Source

1、优化软床报价配置弹窗

iggy 1 day ago
parent
commit
dead66d720

+ 71 - 121
JLHWEB/src/views/quote/softbedQuote/components/BedConfigModal.vue

@@ -7,40 +7,34 @@
     </template>
 
     <div class="checkbox-area">
-      <el-checkbox v-model="showHeadboard" label="床头" border></el-checkbox>
-      <el-checkbox v-model="showNightstand" label="床头柜" border></el-checkbox>
-      <el-checkbox v-model="showBedframe" label="床架" border></el-checkbox>
+      <el-checkbox v-model="showHeadboardModel" label="床头" border></el-checkbox>
+      <el-checkbox v-model="showNightstandModel" label="床头柜" border></el-checkbox>
+      <el-checkbox v-model="showBedframeModel" label="床架" border></el-checkbox>
     </div>
 
     <div class="config-sections config-scroll-container">
       <ConfigSection
-        v-if="showHeadboard"
+        v-if="showHeadboardModel"
         part-name="床头"
-        :config-items="headboardConfigs"
-        :config-item-options="configItemOptions"
-        :config-value-options-map="configValueOptionsMap"
-        @removeConfigItem="removeConfigItem('headboard', $event)"
-        @addConfigItem="addConfigItem('headboard')"
+        v-model:selectedConfigItems="partsConfig.headboard"
+        :configItemOptions="configItemOptions"
+        :configValueOptionsMap="configValueOptionsMap"
       />
 
       <ConfigSection
-        v-if="showNightstand"
+        v-if="showNightstandModel"
         part-name="床头柜"
-        :config-items="nightstandConfigs"
-        :config-item-options="configItemOptions"
-        :config-value-options-map="configValueOptionsMap"
-        @removeConfigItem="removeConfigItem('nightstand', $event)"
-        @addConfigItem="addConfigItem('nightstand')"
+        v-model:selectedConfigItems="partsConfig.nightstand"
+        :configItemOptions="configItemOptions"
+        :configValueOptionsMap="configValueOptionsMap"
       />
 
       <ConfigSection
-        v-if="showBedframe"
+        v-if="showBedframeModel"
         part-name="床架"
-        :config-items="bedframeConfigs"
-        :config-item-options="configItemOptions"
-        :config-value-options-map="configValueOptionsMap"
-        @removeConfigItem="removeConfigItem('bedframe', $event)"
-        @addConfigItem="addConfigItem('bedframe')"
+        v-model:selectedConfigItems="partsConfig.bedframe"
+        :configItemOptions="configItemOptions"
+        :configValueOptionsMap="configValueOptionsMap"
       />
     </div>
 
@@ -52,127 +46,83 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive } from "vue";
+import { PropType, computed } from "vue";
 import ConfigSection from "./ConfigSection.vue";
 import LjDialogNew from "@/components/LjDialog/index-new.vue";
 
-interface SelectOption {
-  label: string;
-  value: string;
-}
-
 interface ConfigValue {
-  pzid: number;
   printid: number;
   pznamemx: string;
 }
-
-interface ConfigItem {
+interface ConfigItemOption {
   pzid: number;
   pzname: string;
-  valueList: ConfigValue[];
+}
+interface SelectedConfigItem {
+  pzid: number;
   selectedValue?: string;
 }
 
-const showHeadboard = ref(true);
-const showNightstand = ref(true);
-const showBedframe = ref(false);
-
-// 下拉选项
-const configItemOptions: SelectOption[] = [
-  { label: "颜色", value: "颜色" },
-  { label: "材质", value: "材质" },
-  { label: "款式", value: "款式" },
-  { label: "尺寸", value: "尺寸" }
-];
-
-// 各配置项对应的选配值选项Map(key为配置项名)
-const configValueOptionsMap: Record<string, SelectOption[]> = {
-  颜色: [
-    { label: "白色", value: "白色" },
-    { label: "红色", value: "红色" },
-    { label: "黑色", value: "黑色" }
-  ],
-  材质: [
-    { label: "实木", value: "实木" },
-    { label: "皮质", value: "皮质" },
-    { label: "布艺", value: "布艺" }
-  ],
-  款式: [
-    { label: "现代", value: "现代" },
-    { label: "简约", value: "简约" }
-  ],
-  尺寸: [
-    { label: "90cm", value: "90cm" },
-    { label: "120cm", value: "120cm" }
-  ]
-};
-
-// 各部件配置数据
-const headboardConfigs = reactive<ConfigItem[]>([
-  {
-    pzid: 101,
-    pzname: "颜色",
-    valueList: [
-      { pzid: 101, printid: 1, pznamemx: "白色" },
-      { pzid: 101, printid: 2, pznamemx: "红色" }
-    ],
-    selectedValue: "白色"
+const props = defineProps({
+  showHeadboard: { type: Boolean, default: true },
+  showNightstand: { type: Boolean, default: true },
+  showBedframe: { type: Boolean, default: false },
+  partsConfig: {
+    type: Object as PropType<{
+      headboard: SelectedConfigItem[];
+      nightstand: SelectedConfigItem[];
+      bedframe: SelectedConfigItem[];
+    }>,
+    required: true
   },
-  {
-    pzid: 201,
-    pzname: "材质",
-    valueList: [
-      { pzid: 201, printid: 1, pznamemx: "皮质" },
-      { pzid: 201, printid: 2, pznamemx: "布艺" }
-    ],
-    selectedValue: "皮质"
-  }
+  configItemOptions: { type: Array as PropType<ConfigItemOption[]>, required: true },
+  configValueOptionsMap: { type: Object as PropType<Record<number, ConfigValue[]>>, required: true }
+});
+
+const emit = defineEmits([
+  "update:showHeadboard",
+  "update:showNightstand",
+  "update:showBedframe",
+  "update:partsConfig",
+  "cancel",
+  "submit",
+  "closed",
+  "update:modelValue"
 ]);
 
-const nightstandConfigs = reactive<ConfigItem[]>([
-  {
-    pzid: 201,
-    pzname: "材质",
-    valueList: [
-      { pzid: 201, printid: 1, pznamemx: "皮质" },
-      { pzid: 201, printid: 2, pznamemx: "布艺" }
-    ],
-    selectedValue: "皮质"
-  }
-]);
+const showHeadboardModel = computed({
+  get: () => props.showHeadboard,
+  set: (val: boolean) => emit("update:showHeadboard", val)
+});
 
-const bedframeConfigs = reactive<ConfigItem[]>([]);
+const showNightstandModel = computed({
+  get: () => props.showNightstand,
+  set: (val: boolean) => emit("update:showNightstand", val)
+});
 
-const removeConfigItem = (part: string, index: number) => {
-  if (part === "headboard") headboardConfigs.splice(index, 1);
-  else if (part === "nightstand") nightstandConfigs.splice(index, 1);
-  else if (part === "bedframe") bedframeConfigs.splice(index, 1);
-};
+const showBedframeModel = computed({
+  get: () => props.showBedframe,
+  set: (val: boolean) => emit("update:showBedframe", val)
+});
 
-const addConfigItem = (part: string) => {
-  const newItem: ConfigItem = {
-    pzid: Date.now(),
-    pzname: "",
-    valueList: [],
-    selectedValue: ""
-  };
-  if (part === "headboard") headboardConfigs.push(newItem);
-  else if (part === "nightstand") nightstandConfigs.push(newItem);
-  else if (part === "bedframe") bedframeConfigs.push(newItem);
-};
-
-const emits = defineEmits(["cancel", "submit", "closed", "update:modelValue"]);
-const onCancel = () => {
-  emits("cancel");
-};
+const onCancel = () => emit("cancel");
 
 const onConfirm = () => {
-  emits("submit", {});
-};
-const closed = () => {
-  emits("closed");
+  const newParts = { ...props.partsConfig };
+
+  if (!showHeadboardModel.value) {
+    newParts.headboard = [];
+  }
+  if (!showNightstandModel.value) {
+    newParts.nightstand = [];
+  }
+  if (!showBedframeModel.value) {
+    newParts.bedframe = [];
+  }
+  emit("submit", newParts);
 };
+
+const closed = () => emit("closed");
 </script>
 
 <style lang="scss">

+ 47 - 45
JLHWEB/src/views/quote/softbedQuote/components/ConfigSection.vue

@@ -3,83 +3,85 @@
     <div class="group-header">
       <div class="group-title">{{ partName }}</div>
     </div>
-    <div v-for="(item, index) in configItems" :key="item.pzid" class="config-row">
+
+    <div v-for="(item, index) in selectedConfigItems" :key="item.pzid" class="config-row">
       <el-select
-        v-model="item.pzname"
+        v-model="item.pzid"
         placeholder="选择选配项"
         size="small"
         class="select-config-item"
-        @change="onConfigItemChange(item, index)"
+        @change="onConfigItemChange(item)"
       >
-        <el-option v-for="option in configItemOptions" :key="option.value" :label="option.label" :value="option.label" />
+        <el-option v-for="option in configItemOptions" :key="option.pzid" :label="option.pzname" :value="option.pzid" />
       </el-select>
 
+      <!-- 配置值选择 -->
       <el-select v-model="item.selectedValue" placeholder="选择选配值" size="small" class="select-config-value">
-        <el-option
-          v-for="opt in configValueOptionsMap[item.pzname] || []"
-          :key="opt.value"
-          :label="opt.label"
-          :value="opt.label"
-        />
+        <el-option v-for="opt in valueListByPzid(item.pzid)" :key="opt.printid" :label="opt.pznamemx" :value="opt.pznamemx" />
       </el-select>
 
-      <i class="iconfont icontrash-01 delete-icon" @click="$emit('removeConfigItem', index)" title="删除选配项" />
+      <i class="iconfont icontrash-01 delete-icon" @click="removeConfigItem(index)" title="删除选配项" />
     </div>
 
     <div class="add-config-btn">
-      <el-button type="primary" icon="el-icon-plus" size="small" @click="$emit('addConfigItem')"> 添加选配项 </el-button>
+      <el-button type="primary" icon="el-icon-plus" size="small" @click="addConfigItem"> 添加选配项 </el-button>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { PropType, reactive } from "vue";
-
-interface SelectOption {
-  label: string;
-  value: string;
-}
+import { ref, PropType, watch } from "vue";
 
 interface ConfigValue {
-  pzid: number;
   printid: number;
   pznamemx: string;
 }
-
-interface ConfigItem {
+interface ConfigItemOption {
   pzid: number;
   pzname: string;
-  valueList: ConfigValue[];
-  selectedValue?: string; // 选中的配置值字符串(方便双向绑定)
+}
+interface SelectedConfigItem {
+  pzid: number;
+  selectedValue?: string;
 }
 
 const props = defineProps({
   partName: { type: String, required: true },
-  configItems: {
-    type: Array as PropType<ConfigItem[]>,
-    required: true
-  },
-  configItemOptions: {
-    type: Array as PropType<SelectOption[]>,
-    default: () => []
-  },
-  configValueOptionsMap: {
-    type: Object as PropType<Record<string, SelectOption[]>>,
-    default: () => ({})
-  }
+  selectedConfigItems: { type: Array as PropType<SelectedConfigItem[]>, required: true },
+  configItemOptions: { type: Array as PropType<ConfigItemOption[]>, required: true },
+  configValueOptionsMap: { type: Object as PropType<Record<number, ConfigValue[]>>, required: true }
 });
 
-const emit = defineEmits(["removeConfigItem", "addConfigItem"]);
+const emit = defineEmits(["update:selectedConfigItems"]);
 
-// 监听配置项名变化时,如果该配置项有对应valueList,自动选中第一个值
-function onConfigItemChange(item: ConfigItem, index: number) {
-  const options = props.configValueOptionsMap[item.pzname];
-  if (options && options.length > 0) {
-    item.selectedValue = options[0].label;
-  } else {
-    item.selectedValue = "";
-  }
-}
+const valueListByPzid = (pzid: number) => {
+  return props.configValueOptionsMap[pzid] || [];
+};
+
+const onConfigItemChange = (item: SelectedConfigItem) => {
+  const options = valueListByPzid(item.pzid);
+  item.selectedValue = options.length > 0 ? options[0].pznamemx : "";
+};
+
+const removeConfigItem = (index: number) => {
+  const newList = [...props.selectedConfigItems];
+  newList.splice(index, 1);
+  emit("update:selectedConfigItems", newList);
+};
+
+const addConfigItem = () => {
+  if (props.configItemOptions.length === 0) return;
+
+  const defaultPzid = props.configItemOptions[0].pzid;
+  const defaultValues = props.configValueOptionsMap[defaultPzid] || [];
+
+  const newItem: SelectedConfigItem = {
+    pzid: defaultPzid,
+    selectedValue: defaultValues.length > 0 ? defaultValues[0].pznamemx : ""
+  };
+
+  emit("update:selectedConfigItems", [...props.selectedConfigItems, newItem]);
+};
 </script>
 
 <style scoped lang="scss">

+ 65 - 9
JLHWEB/src/views/quote/softbedQuote/index.vue

@@ -20,10 +20,21 @@
       </template>
     </LjVxeTable>
   </div>
+
+  <BedConfigModal
+    v-model="isModalVisible"
+    v-model:showHeadboard="showHeadboard"
+    v-model:showNightstand="showNightstand"
+    v-model:showBedframe="showBedframe"
+    v-model:partsConfig="partsConfig"
+    :configItemOptions="allConfigItemOptions"
+    :configValueOptionsMap="configValueOptionsMap"
+    @submit="handleConfirm"
+  />
 </template>
 
 <script setup lang="ts" name="softbedQuote">
-import { ref } from "vue";
+import { ref, reactive } from "vue";
 import { useRouter } from "vue-router";
 import { AuditSoftBedQuote, DeleteSoftBedQuote } from "@/api/modules/quote";
 import { CommonDynamicSelect } from "@/api/modules/common";
@@ -53,15 +64,52 @@ const { userInfo } = useUserStore();
 
 const initParams = ref({});
 
+const allConfigItemOptions = reactive([
+  { pzid: 101, pzname: "颜色" },
+  { pzid: 201, pzname: "材质" },
+  { pzid: 301, pzname: "款式" },
+  { pzid: 401, pzname: "尺寸" },
+  { pzid: 501, pzname: "填充物" },
+  { pzid: 601, pzname: "靠背调节" }
+]);
+
+const configValueOptionsMap = reactive({
+  101: [
+    { printid: 1, pznamemx: "白色" },
+    { printid: 2, pznamemx: "红色" }
+  ],
+  201: [
+    { printid: 1, pznamemx: "皮质" },
+    { printid: 2, pznamemx: "布艺" }
+  ],
+  301: [{ printid: 1, pznamemx: "简约款" }],
+  401: [{ printid: 1, pznamemx: "1.8米" }],
+  501: [{ printid: 1, pznamemx: "记忆棉" }],
+  601: [{ printid: 1, pznamemx: "不可调节" }]
+});
+
+// 父组件维护 partsConfig,Modal 每次打开都会使用同一个对象(记忆性)
+const partsConfig = reactive({
+  headboard: [
+    { pzid: 101, selectedValue: "白色" },
+    { pzid: 201, selectedValue: "皮质" }
+  ],
+  nightstand: [
+    { pzid: 101, selectedValue: "白色" },
+    { pzid: 301, selectedValue: "欧式款" }
+  ],
+  bedframe: [
+    { pzid: 101, selectedValue: "灰色" },
+    { pzid: 401, selectedValue: "1.8米" }
+  ]
+});
+
+const showHeadboard = ref(true);
+const showNightstand = ref(true);
+const showBedframe = ref(true);
+
 // 控制弹窗的显示状态
 const isModalVisible = ref(false);
-// 存储从弹窗返回的配置数据
-const finalConfiguration = ref(null);
-// 监听弹窗的confirm事件
-const onConfigConfirm = data => {
-  console.log("从弹窗收到的配置数据:", data);
-  finalConfiguration.value = data;
-};
 
 const getData = (params: any) => {
   let newParams: any = {};
@@ -312,11 +360,19 @@ const action: detailAction[] = [
   buttonDefault({
     label: "测试弹窗",
     clickFunc: item => {
-      dialog(BedConfigModal, {}).then((data: any) => {});
+      isModalVisible.value = true;
     }
   })
 ];
 
+const handleConfirm = data => {
+  isModalVisible.value = false;
+  console.log("showHeadboard :>>", showHeadboard);
+  console.log("showNightstand :>>", showNightstand);
+  console.log("showBedframe :>>", showBedframe);
+  console.log("partsConfig :>>", data);
+};
+
 /**
  * @description 监听框架属性变化
  */