<!--
 * @Author: qinzhenpen qzp1807@126.com
 * @Date: 2025-04-28 15:05:56
 * @LastEditors: qinzhenpen qzp1807@126.com
 * @LastEditTime: 2025-05-08 17:17:01
 * @FilePath: \e-commerce-internet\src\views\product\price.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="price app-container">
    <div class="handren">
      <div class="left">
        <el-button>PSM模型</el-button>
      </div>
      <div class="right">
        <el-button @click="dialogVisible = true" type="primary" id="brtn">任务背景与目标</el-button>
        <popModel :showModel="dialogVisible" title="任务背景:" @closePop="dialogVisible = false">
          <template v-slot:content>
            <p style="font-size: 1rem">
              电商产品定价是一个复杂而关键的过程，它涉及多个因素和策略。主要包括折扣定价、客户心理定价、人群定价、组合定价、竞争定价、成本差异化定价、市场差异化定价、数量差异化定价等，通过灵活运用各种定价策略，商家可以制定出既符合市场需求又有利于企业发展的价格策略。
              <br />
              在电商产品定价方面，PSM分析技术通过进行价格敏感度测试，基于问卷调查数据，可视化模型分析，给出合理定价区间。
              <br />
              <br />
              任务目标：
              <br />
              <br />
              使用PSM模型给一款洗面奶进行定价。
              <br />
              <br />
              ①数据源：价格区间问卷调查数据。
              <br />
              <br />
              ②根据PSM模型分析得出合理定价区间。
              <br />
            </p>
          </template>
        </popModel>
      </div>
    </div>
    <div class="caseBacktitle">
      <img src="@/assets/images/步骤.png" alt="" />
      <span>一、知识学习</span>
    </div>
    <p>
      PSM分析技术的理论基础
      <br />
      在开发新产品时，厂商对产品价格的看法和消费者对产品价格的知觉经常会不一致，因此厂商往往不愿意事先设定产品的价格，而希望能通过调查从消费者那里得到产品价格的可接受范围。
      <br />
      价格敏感度测试(Price Sensitivity Measure ment，PSM）不需要预先给定好价格，而是让每位被访者自己表示他们的可接受价格范围。
      <br />
      目的：可用于新产品开发、产品线的扩张（产品线内产品项目的增加）、产品范围的扩张（增加产品线）等情况下，确定产品价格的可接受值或范围。
      <br />
      样本的选择：对于产品的开发，必须从所有可能使用新产品的消费总体中抽取有代表性的样本。对于产品线或产品范围的扩张，样本可以从原来的品牌使用者中抽取。
      <br />
    </p>
    <div class="caseBacktitle">
      <img src="@/assets/images/步骤.png" alt="" />
      <span>二、实验实训</span>
    </div>
    <p>假如淘宝某店铺计划推出一款针对大学生群体的洗面奶，您对下列价格区间有何想法？</p>
    <el-table
      :data="priceList1"
      border
      style="width: 60%"
      :header-cell-style="{
        color: '#fff',
        fontSize: '14px',
        backgroundColor: '#6A7DE9!important',
      }"
    >
      <el-table-column label="价格区间" align="center" prop="label"></el-table-column>
      <el-table-column label="太便宜，可能有陷阱" align="center" prop="value">
        <template #default="{ row }">
          <el-radio v-model="row.value" label="1" class="hidden-label"></el-radio>
        </template>
      </el-table-column>
      <el-table-column label="很划算，肯定会购买" align="center" prop="value">
        <template #default="{ row }">
          <el-radio v-model="row.value" label="2" class="hidden-label"></el-radio>
        </template>
      </el-table-column>
      <el-table-column label="有点贵，还可以接受" align="center" prop="value">
        <template #default="{ row }">
          <el-radio v-model="row.value" label="3" class="hidden-label"></el-radio>
        </template>
      </el-table-column>
      <el-table-column label="太贵，直接放弃" align="center" prop="value">
        <template #default="{ row }">
          <el-radio v-model="row.value" label="4" class="hidden-label"></el-radio>
        </template>
      </el-table-column>
    </el-table>
    <p>洗面奶价格梯度表，累计百分比用百分数表示，保留两位小数。</p>
    <el-table
      :data="priceList2"
      border
      style="width: 80%"
      :header-cell-style="{
        color: '#fff',
        fontSize: '14px',
        backgroundColor: '#6A7DE9!important',
      }"
    >
      <el-table-column label="价格区间" align="center" prop="label"></el-table-column>
      <el-table-column label="太便宜，可能有陷阱" align="center">
        <el-table-column label="" align="center" prop="pricevalue1"></el-table-column>
        <el-table-column label="累计总和" align="center" prop="toocheapsum1">
          <template #default="{ row }">
            <el-input v-model="row.toocheapsum1" placeholder="" />
          </template>
        </el-table-column>
        <el-table-column label="累计百分比" align="center" prop="percentage1">
          <template #default="{ row }">
            <el-input v-model="row.percentage1" placeholder="">
              <template #suffix>%</template>
            </el-input>
          </template>
        </el-table-column>
      </el-table-column>
      <el-table-column label="很划算，肯定会购买" align="center">
        <el-table-column label="" align="center" prop="pricevalue2"></el-table-column>
        <el-table-column label="累计总和" align="center" prop="toocheapsum2">
          <template #default="{ row }">
            <el-input v-model="row.toocheapsum2" placeholder="" />
          </template>
        </el-table-column>
        <el-table-column label="累计百分比" align="center" prop="percentage2">
          <template #default="{ row }">
            <el-input v-model="row.percentage2" placeholder="">
              <template #suffix>%</template>
            </el-input>
          </template>
        </el-table-column>
      </el-table-column>
      <el-table-column label="有点贵，还可以接受" align="center">
        <el-table-column label="" align="center" prop="pricevalue3"></el-table-column>
        <el-table-column label="累计总和" align="center" prop="toocheapsum3">
          <template #default="{ row }">
            <el-input v-model="row.toocheapsum3" placeholder="" />
          </template>
        </el-table-column>
        <el-table-column label="累计百分比" align="center" prop="percentage3">
          <template #default="{ row }">
            <el-input v-model="row.percentage3" placeholder="">
              <template #suffix>%</template>
            </el-input>
          </template>
        </el-table-column>
      </el-table-column>
      <el-table-column label="太贵，直接放弃" align="center">
        <el-table-column label="" align="center" prop="pricevalue4"></el-table-column>
        <el-table-column label="累计总和" align="center" prop="toocheapsum4">
          <template #default="{ row }">
            <el-input v-model="row.toocheapsum4" placeholder="" />
          </template>
        </el-table-column>
        <el-table-column label="累计百分比" align="center" prop="percentage4">
          <template #default="{ row }">
            <el-input v-model="row.percentage4" placeholder="">
              <template #suffix>%</template>
            </el-input>
          </template>
        </el-table-column>
      </el-table-column>
    </el-table>
    <p>太便宜和很划算向下累积，有点贵和太贵向上累积，画出每一个价格下开始觉得太便宜、便宜划算，开始觉得贵、太贵的累积人数百分比曲线图。</p>
    <div class="cnetent">
      <div class="left">
        <el-button @click="draw" style="margin-bottom: 20px">绘制</el-button>
        <div id="main" ref="main" style="width: 100%; height: 50vh"></div>
      </div>
      <div class="right">
        <div style="display: flex">
          <div class="online">
            <span>最优价格点:</span>
            <el-input style="width: 100px" type="text" v-model="formInline.optimalPrice" />
          </div>
          <div class="online ml20">
            <span>可接受价格点:</span>
            <el-input style="width: 100px" type="text" v-model="formInline.acceptablePrice" />
          </div>
        </div>
        <div class="online mt20">
          <span>可接受价格范围:</span>
          <el-input style="width: 100px" type="text" v-model="formInline.range1" />
          <span class="p10">----------</span>
          <el-input style="width: 100px" type="text" v-model="formInline.range2" />
        </div>
        <p>PSM模型在产品定价过程中的作用以及不足：</p>
        <el-input v-model="textarea2" :autosize="{ minRows: 11, maxRows: 11 }" type="textarea" placeholder="" />
      </div>
    </div>
    <div class="taskfooter">
      <el-button @click="submitTask">提交任务</el-button>
      <el-button @click="resetTask">重新实训</el-button>
    </div>
  </div>
</template>
<script setup>
import * as echarts from "echarts";
import * as analysisAPI from "@/api/market-demand-mining.js";
const { proxy } = getCurrentInstance();
import useUserStore from "@/store/modules/user";
import popModel from "@/views/components/popModal.vue";
const userStore = useUserStore();
const formInline = ref({
  optimalPrice: "",
  acceptablePrice: "",
  range1: "",
  range2: "",
});
const textarea2 = ref("");
const dialogVisible = ref(false);
const reTraining = () => {
  proxy.$message.success("重新实训");
};
onMounted(() => {});
const main = ref(null);
const priceList1 = ref([
  {
    label: "15元以内",
    value: "",
  },
  {
    label: "15-20元",
    value: "",
  },
  {
    label: "20-30元",
    value: "",
  },
  {
    label: "30-50元",
    value: "",
  },
  {
    label: "50-70元",
    value: "",
  },
  {
    label: "70-100元",
    value: "",
  },
  {
    label: "100-200元",
    value: "",
  },
  {
    label: "200元以上",
    value: "",
  },
]);
const priceList2 = ref([
  {
    label: "15元以内",
    pricevalue1: "126",
    pricevalue2: "56",
    pricevalue3: "0",
    pricevalue4: "0",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "15-20元",
    pricevalue1: "85",
    pricevalue2: "102",
    pricevalue3: "0",
    pricevalue4: "0",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "20-30元",
    pricevalue1: "36",
    pricevalue2: "198",
    pricevalue3: "5",
    pricevalue4: "0",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "30-50元",
    pricevalue1: "2",
    pricevalue2: "85",
    pricevalue3: "30",
    pricevalue4: "0",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "50-70元",
    pricevalue1: "0",
    pricevalue2: "25",
    pricevalue3: "98",
    pricevalue4: "8",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "70-100元",
    pricevalue1: "0",
    pricevalue2: "2",
    pricevalue3: "126",
    pricevalue4: "35",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "100-200元",
    pricevalue1: "0",
    pricevalue2: "0",
    pricevalue3: "159",
    pricevalue4: "89",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
  {
    label: "200元以上",
    pricevalue1: "0",
    pricevalue2: "0",
    pricevalue3: "109",
    pricevalue4: "192",
    toocheapsum1: "",
    toocheapsum2: "",
    toocheapsum3: "",
    toocheapsum4: "",
    percentage1: "",
    percentage2: "",
    percentage3: "",
    percentage4: "",
  },
]);
// 校验空值并只提示一次
function validateAndAlertOnce() {
  let hasEmptyValue = false; // 标记是否发现空值
  // 遍历数组检查空值
  priceList2.value.forEach((item) => {
    Object.keys(item).forEach((key) => {
      if (item[key] === "") {
        hasEmptyValue = true; // 发现空值，标记为 true
        // 可选择替换空值（如果需要）
        item[key] = ""; // 替换为空值时的默认值
      }
    });
  });

  // 只在发现空值时提示一次
  if (hasEmptyValue) {
    // alert("数据中存在空值，已自动替换为默认值 0。");
    proxy.$modal.msgWarning("请填写完整数据!");
    return false; // 返回 false，表示存在空值
  }
  return true; // 没有空值，返回 true
}
const draw = () => {
  const isValid = validateAndAlertOnce();
  if (!isValid) return;
  const minPicture = priceList2.value.map((item) => item.percentage1);
  const calculatePrice = priceList2.value.map((item) => item.percentage2);
  const minexpensive = priceList2.value.map((item) => item.percentage3);
  const expensive = priceList2.value.map((item) => item.percentage4);
  const priceRanges = ['15元以内',"15-20元", "20-30元", "30-50元", "50-70元", "70-100元", "100-200元", "200元以上"];
  var myChart = echarts.init(main.value);
  myChart.setOption({
    title: {
      text: "PSM价格数据分析",
      left: "center",
    },
    tooltip: {
      trigger: "axis",
    },
    legend: {
      data: ["太便宜", "很划算", "有点贵", "太贵了"],
      top: 30,
    },
    xAxis: {
      type: "category",
      name: "价格区间",
      data: priceRanges,
    },
    yAxis: {
      type: "value",
      name: "销售数量 (件)",
      min: 0,
      max: 100,
    },
    series: [
      {
        name: "太便宜",
        type: "line",
        data: minPicture,
        color: "#1f77b4",
        symbol: "circle",
        symbolSize: 8,
      },
      {
        name: "太贵了",
        type: "line",
        data: expensive,
        color: "#d62728",
        symbol: "circle",
        symbolSize: 8,
      },
      {
        name: "有点贵",
        type: "line",
        data: minexpensive,
        color: "#2ca02c",
        symbol: "circle",
        symbolSize: 8,
      },
      {
        name: "很划算",
        type: "line",
        data: calculatePrice,
        color: "#ff7f0e",
        symbol: "circle",
        symbolSize: 8,
      },
    ],
    grid: {
      left: "2%",
      right: "15%",
      bottom: "10%",
      containLabel: true,
    },
    graphic: [
      {
        type: "text",
        left: 391, // 或 "60%" 等
        top: 334,
        z: 100, // 设置更高的图层层级
        style: {
          text: "P4",
          font: "bold 14px sans-serif",
          fill: "#2ca02c",
          // 显示在线条墙上面
          distance: 10,
        },
      },
      {
        type: "text",
        left: 300, // 或 "60%" 等
        top: 380,
        z: 100, // 设置更高的图层层级
        symbol: "circle",
        style: {
          text: "P1",
          font: "bold 14px sans-serif",
          fill: "#1f77b4",
          // 显示在线条墙上面
          distance: 10,
        },
      },
      {
        type: "text",
        left: 350, // 或 "60%" 等
        top: 388,
        z: 100, // 设置更高的图层层级
        symbol: "circle",
        style: {
          text: "P2",
          font: "bold 14px sans-serif",
          fill: "#d62728",
          // 显示在线条墙上面
          distance: 10,
        },
      },
      {
        type: "text",
        left: 430, // 或 "60%" 等
        top: 380,
        z: 100, // 设置更高的图层层级
        symbol: "circle",
        style: {
          text: "P3",
          font: "bold 14px sans-serif",
          fill: "#ff7f0e",
          // 显示在线条墙上面
          distance: 10,
        },
      },
    ],
  });
};
const submitTask = () => {
  const minPicture = priceList2.value.map((item) => item.percentage1);
  const minPriceValue = priceList2.value.map((item) => item.toocheapsum1);
  const calculatePrice = priceList2.value.map((item) => item.percentage2);
  const calculatevalue = priceList2.value.map((item) => item.toocheapsum2);
  const minexpensive = priceList2.value.map((item) => item.percentage3);
  const minexpensivevalue = priceList2.value.map((item) => item.toocheapsum3);
  const expensive = priceList2.value.map((item) => item.percentage4);
  const tooSum = priceList2.value.map((item) => item.toocheapsum4);
  //   判断数组是否为空
  if (minPicture.includes("") || minPriceValue.includes("") || calculatePrice.includes("") || calculatevalue.includes("") || minexpensive.includes("") || minexpensivevalue.includes("") || expensive.includes("") || priceList1.value.some((item) => !item.value)) {
    return proxy.$modal.msgWarning("请填写完整数据");
  }
  //   判断formInline的值是否为空
  if (formInline.value.optimalPrice == "" || formInline.value.acceptablePrice == "" || formInline.value.range1 == "" || formInline.value.range2 == "") {
    return proxy.$modal.msgWarning("请填写完整数据");
  }
  const params = {
    acceptablePrice: formInline.value.acceptablePrice,
    acceptablePriceRange: formInline.value.range1 + "," + formInline.value.range2,
    optimalPrice: formInline.value.optimalPrice,
    cheapPercentage: minPicture.join(","),
    cheapSum: minPriceValue.join(","),
    context: textarea2.value,
    costEffectivePercentage: calculatePrice.join(","),
    costEffectiveSum: calculatevalue.join(","),
    expensivePercentage: minexpensive.join(","),
    expensiveSum: minexpensivevalue.join(","),
    tooExpensivePercentage: expensive.join(","),
    tooSum: tooSum.join(","),
    priceRange: JSON.stringify(priceList1.value),
    displayStatus: 1,
  };
  analysisAPI.productPricingSubmit({ stuAnswer: params, userId: userStore.userInfo.userId }).then((res) => {
    proxy.$modal.msgSuccess("提交成功");
  });
};
// 回显接口
const loadTaskInfo = () => {
  analysisAPI.productPricingEcho({ userId: userStore.userInfo.userId }).then((res) => {
    if (!res.data) return;
    formInline.value.optimalPrice = res.data.optimalPrice;
    formInline.value.acceptablePrice = res.data.acceptablePrice;
    formInline.value.range1 = res.data.acceptablePriceRange.split(",")[0];
    formInline.value.range2 = res.data.acceptablePriceRange.split(",")[1];
    textarea2.value = res.data.context;
    priceList1.value = JSON.parse(res.data.priceRange !== "" ? res.data.priceRange : priceList1.value);
    priceList2.value.forEach((item, index) => {
      item.toocheapsum1 = res.data.cheapSum.split(",")[index];
      item.toocheapsum2 = res.data.costEffectiveSum.split(",")[index];
      item.toocheapsum3 = res.data.expensiveSum.split(",")[index];
      item.percentage1 = res.data.cheapPercentage.split(",")[index];
      item.percentage2 = res.data.costEffectivePercentage.split(",")[index];
      item.percentage3 = res.data.expensivePercentage.split(",")[index];
      item.percentage4 = res.data.tooExpensivePercentage.split(",")[index];
      item.toocheapsum4 = res.data.tooSum.split(",")[index];
    });
    draw();
  });
};
// 重新实训
const resetTask = () => {
  analysisAPI.productPricingReTrain({ userId: userStore.userInfo.userId, module: "产品定价" }).then((res) => {
    proxy.$modal.msgSuccess("重新实训成功");
    // 清楚数据
    formInline.value.optimalPrice = "";
    formInline.value.acceptablePrice = "";
    formInline.value.range1 = "";
    formInline.value.range2 = "";
    textarea2.value = "";
    // 清除数据
    priceList1.value.forEach((item) => {
      item.value = "";
    });
    priceList2.value.forEach((item) => {
      item.toocheapsum1 = "";
      item.toocheapsum2 = "";
      item.toocheapsum3 = "";
      item.toocheapsum4 = "";
      item.percentage1 = "";
      item.percentage2 = "";
      item.percentage3 = "";
      item.percentage4 = "";
    });
    // loadTaskInfo();
  });
};
onMounted(() => {
  loadTaskInfo();
});
</script>
<style lang='scss'  scoped>
.app-container {
  background-color: #f5f5f5;
  :deep(.hidden-label) {
    .el-radio__label {
      display: none;
    }
  }
  .cnetent {
    display: flex;
    .left {
      width: 50%;
      height: 100%;
    }
    .right {
      width: 50%;
      height: 100%;
    }
  }
}
</style>