Vue实现动态数据透视表(交叉表)

需求:需要根据前端选择的横维度、竖维度、值去生成一个动态的表格,然后把交叉的值放入到对应的横维度和竖维度之下,其实就是excel里面的数据透视表功能,查询交叉语句为sql语句。

实现页面:

选择一下横维度、竖维度、值之后点击查询即可出现交叉结果

其余的条件都是过滤条件

后端实现:后端是用Hutool工具包连接数据库拼的sql查出来的entityList在转化成前端所需要的Map集合生成动态表头,代码如下:

获取动态表头方法:通过前端传过来的数据库字段的值,distinct查出这个字段有什么值,然后转化成对应的map集合发给前端实现动态表格

getDropdownItemForOne:

java 复制代码
@RequestMapping("/getDropdownItemForOne")
    public ResultData getDropdownItemForOne(@Param("columnName") String columnName) {
        Map<String, List<String>> dropdownItems = new HashMap<>();

        List<Map<String,String>> items = new ArrayList<>();
        //线上
        String dbUrl = DatsSourceUrl;
        String user = DataSourceUser;
        String password = DataSourcePassword;
        try (Connection conn = DriverManager.getConnection(dbUrl, user, password);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM report_changjingku_list WHERE 1=2")) { // 只查询字段,不查询数据

            ResultSetMetaData metaData = rs.getMetaData();

                String query = "SELECT DISTINCT " + columnName + " FROM report_changjingku_list";
                try (ResultSet columnResultSet = stmt.executeQuery(query)) {


                    int keyValue = 1; // 初始化键值,从1开始
                    while (columnResultSet.next()) {
                        String value = columnResultSet.getString(1); // 获取查询结果的值
                        Map<String,String> itemMap = new HashMap<>();
                        itemMap.put("name", value);
                        itemMap.put("key", "key" + keyValue);
                        items.add(itemMap);
                        keyValue++; // 键值加1
                    }

                }

        } catch (SQLException e) {
            e.printStackTrace();
        }


        return ResultData.success("ok",items);
    }

查询交叉表拼Sql方法:

test:

java 复制代码
@PostMapping("/test")
    public ResultData test(@RequestAttribute Long _userId,  @RequestBody MixTable mixTable) throws SQLException {
        //引入hutool工具包创建数据源对象
        DruidDataSource ds = new DruidDataSource();
        String verticalDimension = "";
        String horizontalDimension = "";
        String value = "";
        if (mixTable.getVerticalDimension() != null){
            verticalDimension = mixTable.getVerticalDimension();
        }
        if (mixTable.getHorizontalDimension() != null){
            horizontalDimension = mixTable.getHorizontalDimension();
        }
        if (mixTable.getPrice() != null){
            value = mixTable.getPrice().toString();
        }
        ds.setUrl(DatsSourceUrl);
        ds.setUsername(DataSourceUser);
        ds.setPassword(DataSourcePassword);
        StringBuilder sqlSelect = new StringBuilder();
        sqlSelect.append("select tc.shuweidu, tc.hengweidu, group_concat(tc.xqsl order by tc.xh) as xqhb from (");
        sqlSelect.append("select @pnum:=case when ta.hengweidu=@pejcj then @pnum+1 else 1 end as xh, @pejcj:=ta.hengweidu, ta.shuweidu, ta.hengweidu, concat(ta.zhi,'(', ta.tnum, ')') as xqsl from (");
        sqlSelect.append("select ").append(verticalDimension).append(" as shuweidu, ").append(horizontalDimension).append(" as hengweidu, ").append(value).append(" as zhi, count(*) as tnum from report_changjingku_list where 1=1 and ").append(value).append("!=''");

        // 动态添加条件
        //年龄
        if (mixTable.getAge() != null) {
            sqlSelect.append(" and r_nl=").append("'").append(mixTable.getAge()).append("'");
        }
        //行业
        if (mixTable.getIndustry() != null && !mixTable.getIndustry().isEmpty() ){
            sqlSelect.append(" and r_hy=").append("'").append(mixTable.getIndustry()).append("'");
        }
        //性别
        if (mixTable.getSex() != null && !mixTable.getSex().isEmpty() ){
            sqlSelect.append(" and r_xb=").append("'").append(mixTable.getSex()).append("'");
        }
        //婚姻状况
        if (mixTable.getMaritalStatus() != null && !mixTable.getMaritalStatus().isEmpty() ){
            sqlSelect.append(" and r_hyzk=").append("'").append(mixTable.getMaritalStatus()).append("'");
        }
        //小孩数量
        if (mixTable.getChildNum() != null && !mixTable.getChildNum().isEmpty() ){
            sqlSelect.append(" and r_xhsl=").append("'").append(mixTable.getChildNum()).append("'");
        }
        //小孩年龄段
        if (mixTable.getChildAgeScope() != null && !mixTable.getChildAgeScope().isEmpty() ){
            sqlSelect.append(" and r_xhnld=").append("'").append(mixTable.getChildAgeScope()).append("'");
        }
        //职业属性
        if (mixTable.getOccupationAttribute() != null && !mixTable.getOccupationAttribute().isEmpty() ){
            sqlSelect.append(" and r_zysx=").append("'").append(mixTable.getOccupationAttribute()).append("'");
        }
        //家庭年收入情况(万)
        if (mixTable.getHomeIncome() != null && !mixTable.getHomeIncome().isEmpty() ){
            sqlSelect.append(" and r_jtnsrqk=").append("'").append(mixTable.getHomeIncome()).append("'");
        }
        //学历情况
        if (mixTable.getEducationalBack() != null && !mixTable.getEducationalBack().isEmpty() ){
            sqlSelect.append(" and r_xlqk=").append("'").append(mixTable.getEducationalBack()).append("'");
        }
        //车系
        if (mixTable.getCarSeries() != null && !mixTable.getCarSeries().isEmpty() ){
            sqlSelect.append(" and r_cx=").append("'").append(mixTable.getCarSeries()).append("'");
        }
        //级别
        if (mixTable.getCarLevel() != null && !mixTable.getCarLevel().isEmpty() ){
            sqlSelect.append(" and r_jb=").append("'").append(mixTable.getCarLevel()).append("'");
        }
        //车身类别
        if (mixTable.getCarBody() != null && !mixTable.getCarBody().isEmpty() ){
            sqlSelect.append(" and r_cslb=").append("'").append(mixTable.getCarBody()).append("'");
        }
        //车型级别
        if (mixTable.getCarModelLevel() != null && !mixTable.getCarModelLevel().isEmpty() ){
            sqlSelect.append(" and r_cxjl=").append("'").append(mixTable.getCarModelLevel()).append("'");
        }
        //TP价格段(万)
        if (mixTable.getTpPrice() != null && !mixTable.getTpPrice().isEmpty() ){
            sqlSelect.append(" and r_tpjgd=").append("'").append(mixTable.getTpPrice()).append("'");
        }
        //能源类型
        if (mixTable.getEnergyType() != null && !mixTable.getEnergyType().isEmpty() ){
            sqlSelect.append(" and r_nylx=").append("'").append(mixTable.getEnergyType()).append("'");
        }
        //一级场景
        if (mixTable.getOneScene() != null && !mixTable.getOneScene().isEmpty() ){
            sqlSelect.append(" and r_yjcj=").append("'").append(mixTable.getOneScene()).append("'");
        }
        //二级场景描述
        if (mixTable.getTwoSceneDescription() != null && !mixTable.getTwoSceneDescription().isEmpty() ){
            sqlSelect.append(" and r_ejcjms=").append("'").append(mixTable.getTwoSceneDescription()).append("'");
        }
        //出行阶段
        if (mixTable.getTravelStage() != null && !mixTable.getTravelStage().isEmpty() ){
            sqlSelect.append(" and r_cxjd=").append("'").append(mixTable.getTravelStage()).append("'");
        }
        //出行人数
        if (mixTable.getTravelNum() != null && !mixTable.getTravelNum().isEmpty() ){
            sqlSelect.append(" and r_cxrs=").append(mixTable.getTravelNum());
        }
        //用户角色
        if (mixTable.getUserRole() != null && !mixTable.getUserRole().isEmpty() ){
            sqlSelect.append(" and r_yhjs=").append("'").append(mixTable.getUserRole()).append("'");
        }
        //用户特征
        if (mixTable.getUserFeature() != null && !mixTable.getUserFeature().isEmpty() ){
            sqlSelect.append(" and r_yhtz=").append("'").append(mixTable.getUserFeature()).append("'");
        }
        //驾驶状态
        if (mixTable.getDriveStatus() != null && !mixTable.getDriveStatus().isEmpty() ){
            sqlSelect.append(" and r_jszt=").append("'").append(mixTable.getDriveStatus()).append("'");
        }
        //驾驶道路
        if (mixTable.getDriveRoad() != null && !mixTable.getDriveRoad().isEmpty() ){
            sqlSelect.append(" and r_jsdl=").append("'").append(mixTable.getDriveRoad()).append("'");
        }
        //驾驶区域
        if (mixTable.getDriveArea() != null && !mixTable.getDriveArea().isEmpty() ){
            sqlSelect.append(" and r_jsqy=").append("'").append(mixTable.getDriveArea()).append("'");
        }
        //天气环境
        if (mixTable.getWeather() != null && !mixTable.getWeather().isEmpty() ){
            sqlSelect.append(" and r_tqhj=").append("'").append(mixTable.getWeather()).append("'");
        }
        //时间
        if (mixTable.getTime() != null && !mixTable.getTime().isEmpty() ){
            sqlSelect.append(" and r_sj=").append("'").append(mixTable.getTime()).append("'");
        }
        //季节
        if (mixTable.getSeason() != null && !mixTable.getSeason().isEmpty() ){
            sqlSelect.append(" and r_jj=").append("'").append(mixTable.getSeason()).append("'");
        }
        //数据采集地点
        if (mixTable.getDataLocality() != null && !mixTable.getDataLocality().isEmpty() ){
            sqlSelect.append(" and r_sjcjdd=").append("'").append(mixTable.getDataLocality()).append("'");
        }
        //城市等级
        if (mixTable.getCityLevel() != null && !mixTable.getCityLevel().isEmpty() ){
            sqlSelect.append(" and r_csdj=").append("'").append(mixTable.getCityLevel()).append("'");
        }
        //隶属省份
        if (mixTable.getProvince() != null && !mixTable.getProvince().isEmpty() ){
            sqlSelect.append(" and r_lssf=").append("'").append(mixTable.getProvince()).append("'");
        }
        //一级指标
        if (mixTable.getOneIndex() != null && !mixTable.getOneIndex().isEmpty() ){
            sqlSelect.append(" and r_yjzb=").append("'").append(mixTable.getOneIndex()).append("'");
        }
        //二级指标
        if (mixTable.getTwoIndex() != null && !mixTable.getTwoIndex().isEmpty() ){
            sqlSelect.append(" and r_ejzb=").append("'").append(mixTable.getTwoIndex()).append("'");
        }
        //三级指标
        if (mixTable.getThreeIndex() != null && !mixTable.getThreeIndex().isEmpty() ){
            sqlSelect.append(" and r_sjzb=").append("'").append(mixTable.getThreeIndex()).append("'");
        }
        //感知价值
        if (mixTable.getFeelPrice() != null && !mixTable.getFeelPrice().isEmpty() ){
            sqlSelect.append(" and r_gzjz=").append("'").append(mixTable.getFeelPrice()).append("'");
        }
        //感知时刻
        if (mixTable.getFeelTime() != null && !mixTable.getFeelTime().isEmpty() ){
            sqlSelect.append(" and r_gzsk=").append("'").append(mixTable.getFeelTime()).append("'");
        }
        //当前解决方案
        if (mixTable.getWorkOutScheme() != null && !mixTable.getWorkOutScheme().isEmpty() ){
            sqlSelect.append(" and r_dqjjfa=").append("'").append(mixTable.getWorkOutScheme()).append("'");
        }
        //数据来源
        if (mixTable.getDataResource() != null && !mixTable.getDataResource().isEmpty() ){
            sqlSelect.append(" and r_sjly=").append("'").append(mixTable.getDataResource()).append("'");
        }
        sqlSelect.append(" group by ").append(verticalDimension).append(",").append(horizontalDimension).append(",").append(value).append(" order by ").append(verticalDimension).append(",").append(horizontalDimension).append(", tnum desc ) ta inner join (select @pejcj:='', @pnum:=0) tb ) tc where tc.xh<=10 group by tc.shuweidu, tc.hengweidu order by tc.shuweidu, tc.hengweidu");
        Connection conn = ds.getConnection();
        List<Entity> entityList = SqlExecutor.query(conn, sqlSelect.toString(), new EntityListHandler());


        // 处理查询结果
        Map<String, Map<String, String>> groupedResult = new HashMap<>();
        for (Entity entity : entityList) {
            String shuweidu = entity.getStr("shuweidu");
            String xqhb = entity.getStr("xqhb");

            // 如果 shuweidu 不存在于结果中,初始化一个新对象
            if (!groupedResult.containsKey(shuweidu)) {
                groupedResult.put(shuweidu, new HashMap<>());
                groupedResult.get(shuweidu).put("name", shuweidu);
            }

            // 获取当前对象
            Map<String, String> itemMap = groupedResult.get(shuweidu);

            // 动态生成 key
            int keyIndex = itemMap.size() - 1; // 已有的键数量
            String key = "key" + (keyIndex + 1);
            itemMap.put(key, xqhb);
        }

        // 将结果转换为列表
        List<Map<String, String>> resultList = new ArrayList<>(groupedResult.values());

        // 打印结果
        System.out.println(resultList);

        return ResultData.success("ok", resultList);
    }

前端:

html 复制代码
<!--  -->
<template>
  <div>
    <el-form
      ref="formRef"
      :model="reqUser"
      label-width="180px"
      v-loading="formLoading"
      style="background: #f3f3f3;"
    >
      <el-row>
        <el-col>
          <ContenWrap>
            <el-row style="margin-top: 0">
              <div style="background: #fff;">
                <h1 style="margin-left: 30px; padding-top: 10px;">布局</h1>
                <el-form >
                  <el-row :gutter="24">
                    <el-col :span="12">
                      <el-form-item
                        prop="verticalDimension"
                        label-width="80px"
                      >
                      <div slot="label">竖维度<font color="red">*</font></div>
                        <el-select
                          v-model="reqUser.verticalDimension"
                          class="filter-item"
                          placeholder="请选择竖维度"
                          clearable
                          style="width: 230%;"
                          @change="changeVerticalDimension"
                        >
                          <el-option
                            v-for="item in peopleList2"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="12">
                      <el-form-item
                        prop="horizontalDimension"
                        label-width="80px"
                      >
                      <div slot="label">横维度<font color="red">*</font></div>
                        <el-select
                          v-model="reqUser.horizontalDimension"
                          class="filter-item"
                          placeholder="请选择横维度"
                          clearable
                          style="width: 230%;"
                          @change="changeHorizontalDimension"
                        >
                          <el-option
                            v-for="item in sceneList2"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                  </el-row>
                  <el-row :gutter="24">
                    <el-col :span="6">
                      <el-form-item
                        label="数据来源"
                        prop="dataResource"
                        label-width="80px"
                      >
                        <el-select
                          v-model="reqUser.dataResource"
                          class="filter-item"
                          placeholder="请选择数据来源"
                          clearable
                          style="width: 260%;"
                        >
                          <el-option
                            v-for="item in selectSource.r_sjly"
                            :key="item"
                            :label="item"
                            :value="item"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="值" prop="price" label-width="80px">
                        <div slot="label">值<font color="red">*</font></div>
                        <el-select
                          v-model="reqUser.price"
                          class="filter-item"
                          placeholder="请选择值"
                          clearable
                          style="width: 260%;"
                        >
                        
                          <el-option
                            v-for="item in statusValueList"
                            :key="item.name"
                            :label="item.comment"
                            :value="item.name"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="12">
                      <el-form-item label="时间" prop="time" label-width="80px">
                        <el-date-picker
                          v-model.trim="reqUser.time"
                          type="datetime"
                          style="width: 230%;"
                          placeholder="选择时间"
                        />
                      </el-form-item>
                    </el-col>
                  </el-row>
                </el-form>
              </div>
            </el-row>
          </ContenWrap>
          <ContenWrap>
            <el-row :gutter="24" class="downThree">
              <el-col :span="8">
                <h1 style="margin-left: 30px;">人群筛选</h1>
                <el-table :data="tableData" border style="width: 100%">
                  <el-table-column prop="label" label="项" width="180" />
                  <el-table-column label="值">
                    <template #default="scope">
                      <el-select
                        v-model="scope.row.tag"
                        class="filter-item"
                        placeholder="请选择值"
                        clearable
                        style="width: 100%;"
                        @change="addValue(scope.row)"
                      >
                        <el-option
                          v-for="item in scope.row.list"
                          :key="item"
                          :label="item"
                          :value="item"
                        />
                      </el-select>
                    </template>
                  </el-table-column>
                </el-table>
                <el-select
                  v-model="value1"
                  @change="addForm1(value1)"
                  placeholder="选择项"
                  style="width: 240px;margin-left: 20px;"
                >
                  <el-option
                    v-for="dict in peopleList"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  />
                </el-select>
              </el-col>
              <el-col :span="8">
                <div>
                  <h1 style="margin-left: 30px;">车型筛选</h1>
                  <el-table
                    :data="tableData2"
                    border
                    style="width: 100%; margin-right: 20px"
                  >
                    <el-table-column prop="label" label="项" width="180" />
                    <el-table-column label="值">
                      <template #default="scope">
                        <el-select
                          v-model="scope.row.tag"
                          class="filter-item"
                          placeholder="请选择值"
                          clearable
                          style="width: 100%;"
                          @change="addValue2(scope.row)"
                        >
                          <el-option
                            v-for="item in scope.row.list"
                            :key="item"
                            :label="item"
                            :value="item"
                          />
                        </el-select>
                      </template>
                    </el-table-column>
                  </el-table>
                  <el-select
                    v-model="value2"
                    @change="addForm2(value2)"
                    placeholder="选择项"
                    style="width: 240px;margin-left: 20px;"
                  >
                    <el-option
                      v-for="dict in carList"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                    />
                  </el-select>
                </div>
              </el-col>
              <el-col :span="8">
                <div>
                  <h1 style="margin-left: 30px;">场景筛选</h1>
                  <el-table :data="tableData3" border style="width: 100%">
                    <el-table-column prop="label" label="项" width="180px" />
                    <el-table-column label="值">
                      <template #default="scope">
                        <el-select
                          v-model="scope.row.tag"
                          class="filter-item"
                          placeholder="请选择值"
                          clearable
                          style="width: 100%;"
                          @change="addValue3(scope.row)"
                        >
                          <el-option
                            v-for="item in scope.row.list"
                            :key="item"
                            :label="item"
                            :value="item"
                          />
                        </el-select>
                      </template>
                    </el-table-column>
                  </el-table>
                  <el-select
                    v-model="value3"
                    @change="addForm3(value3)"
                    placeholder="选择项"
                    style="width: 240px;margin-left: 20px;"
                  >
                    <el-option
                      v-for="dict in sceneList"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                    />
                  </el-select>
                </div>
              </el-col>
            </el-row>
          </ContenWrap>
        </el-col>
      </el-row>

      <el-button
        type="primary"
        @click="save"
        style="margin-left: 47%;margin-bottom: 0.5%;"
        >查询</el-button
      >
    </el-form>
    <el-table :data="tableDataList" border height="550px" v-loading="loading">
      <el-table-column
        v-for="(item, index) in headerList"
        align="center"
        :label="item.mon"
        :key="index"
        :prop="item.key_str"
      >
        <!-- 自定义第一个表头 -->
        <template v-if="index === 0" #header>
        <div class="header-div">
          <div class="header-col1">{{ tableVertial }}</div>
          <div class="header-col2">{{ tableHorizontal }}</div>
          <div class="header-line1"></div>
        </div>
      </template>
      </el-table-column>
      <el-table-column
        align="center"
        :label="item1.name"
        v-for="(item1, index1) in headerList2"
        :key="index1"
      >
        <template #default="scope">
          <div>{{scope.row[`${item1.key}`]}}</div>
        </template>
      </el-table-column>
    </el-table>

  </div>
</template>

<script>
import { tableHeight5 } from "@/utils/tableHeight";
import {
  addMixTable,
  getDictLabel,
  getDropdownItems,
  getValueDropdownItems,
  getDictLabelValue,
  test,
  getDropdownItemForOne
} from "@/api/mixTableAdd";
import Pagination from "@/components/Pagination";
import { Message, MessageBox } from "element-ui";
import { getToken } from "@/utils/auth";
import { getPage, deleteData } from "@/api/mixTableAdd";
export default {
  components: { Pagination },
  mixins: [tableHeight5],
  data() {
    return {
      listLoading: false,
      total: 0,
      queryPage: {
        page: 1,
        limit: 20,
        createTime: undefined
      },
      reqUser: {
        verticalDimension: "",
        horizontalDimension: "",
        price: "",
        age: null,
        industry: "",
        sex: "",
        maritalStatus: "",
        childNum: "",
        childAgeScope: "",
        occupationAttribute: "",
        homeIncome: null,
        educationalBack: "",
        carSeries: "",
        carLevel: "",
        carBody: "",
        carModelLevel: "",
        oneScene: "",
        twoSceneDescription: "",
        tpPrice: "",
        energyType: "",
        travelStage: "",
        travelNum: "",
        userRole: "",
        userFeature: "",
        driveStatus: "",
        driveRoad: "",
        driveArea: "",
        time: undefined,
        weather: "",
        season: "",
        dataLocality: "",
        cityLevel: "",
        province: "",
        oneIndex: "",
        twoIndex: "",
        threeIndex: "",
        feelPrice: "",
        feelTime: undefined,
        workOutScheme: "",
        dataResource: ""
      },
      exportData: {},
      tableVertial:"",
      tableHorizontal:"",
      tableVertial2:"",
      tableHorizontal2:"",
      multipleSelection: [],
      uploadPath: "http://pbm.langtaosoft.com/questDeal/importData", // 上传url
      uploadHeaders: "", // 上传头
      tableData: [], // 列表数据
      statusList: [], // 状态列表
      statusValueList: [], // 状态列表
      dataResource: [], // 数据来源
      selectSource: {
        r_nl: []
      },
      selectValueSource: {},
      batchNoList: [], // 数据批次号
      carList: [], // 车型名称
      urlOptions: [], // url列表
      dialogVisibleImport: false, // 导入显示
      dialogVisibleDeal: false, // 处理弹出
      peopleList: [
        {
          label: "年龄",
          value: "0",
          list: [],
          tag: ""
        },
        {
          label: "TP价格段(万)",
          value: "1",
          list: [],
          tag: ""
        },
        {
          label: "职业属性",
          value: "2"
        },
        {
          label: "婚姻状况",
          value: "3"
        },
        {
          label: "小孩数量",
          value: "4"
        },
        {
          label: "小孩年龄段",
          value: "5"
        },
        {
          label: "性别",
          value: "6",
          list: [],
          tag: ""
        },
        {
          label: "家庭年收入(万)",
          value: "7"
        },
        {
          label: "学历情况",
          value: "8"
        },
        {
          label: "行业",
          value: "9",
          list: [],
          tag: ""
        },
        {
          label: "隶属省份",
          value: "10",
          list: [],
          tag: ""
        },
        {
          label: "城市等级",
          value: "11",
          list: [],
          tag: ""
        },
        {
          label: "用户特征",
          value: "12",
          list: [],
          tag: ""
        }
      ],
      peopleList2: [
        {
          label: "年龄",
          value: "r_nl",
          list: [],
          tag: ""
        },
        {
          label: "TP价格段(万)",
          value: "r_tpjgd",
          list: [],
          tag: ""
        },
        {
          label: "职业属性",
          value: "r_zysx"
        },
        {
          label: "婚姻状况",
          value: "r_hyzk"
        },
        {
          label: "小孩数量",
          value: "r_xhsl"
        },
        {
          label: "小孩年龄段",
          value: "r_xhnld"
        },
        {
          label: "性别",
          value: "r_xb",
          list: [],
          tag: ""
        },
        {
          label: "家庭年收入(万)",
          value: "r_jtnsrqk"
        },
        {
          label: "学历情况",
          value: "r_xlqk"
        },
        {
          label: "行业",
          value: "r_hy",
          list: [],
          tag: ""
        },
        {
          label: "隶属省份",
          value: "r_lssf",
          list: [],
          tag: ""
        },
        {
          label: "城市等级",
          value: "r_csdj",
          list: [],
          tag: ""
        },
        {
          label: "用户特征",
          value: "r_yhtz",
          list: [],
          tag: ""
        }
      ],
      carList: [
        {
          label: "能源类型",
          value: "0",
          list: [],
          tag: ""
        },
        {
          label: "级别",
          value: "1",
          list: [],
          tag: ""
        },
        {
          label: "车身类别",
          value: "2",
          list: [],
          tag: ""
        },
        {
          label: "一级指标",
          value: "3",
          list: [],
          tag: ""
        },
        {
          label: "二级指标",
          value: "4",
          list: [],
          tag: ""
        },
        {
          label: "三级指标",
          value: "5",
          list: [],
          tag: ""
        }
      ],
      sceneList: [
        {
          label: "一级场景",
          value: "0",
          list: [],
          tag: ""
        },
        {
          label: "二级场景描述",
          value: "1"
        },
        {
          label: "用车阶段",
          value: "2"
        },
        {
          label: "出行人数",
          value: "3"
        },
        {
          label: "用户角色",
          value: "4"
        },
        {
          label: "用户特征",
          value: "5"
        },
        {
          label: "驾驶状态",
          value: "6"
        },
        {
          label: "驾驶道路",
          value: "7"
        },
        {
          label: "驾驶区域",
          value: "8"
        },
        {
          label: "天气环境",
          value: "9"
        },
        {
          label: "季节",
          value: "10"
        },
        {
          label: "出行阶段",
          value: "11"
        }
      ],
      sceneList2: [
        {
          label: "一级场景",
          value: "r_yjcj",
          list: [],
          tag: ""
        },
        {
          label: "二级场景描述",
          value: "r_ejcjms"
        },
        {
          label: "出行阶段",
          value: "r_cxjd"
        },
        {
          label: "出行人数",
          value: "r_cxrs"
        },
        {
          label: "用户角色",
          value: "r_yhjs"
        },
        {
          label: "用户特征",
          value: "r_yhtz"
        },
        {
          label: "驾驶状态",
          value: "r_jszt"
        },
        {
          label: "驾驶道路",
          value: "r_jsdl"
        },
        {
          label: "驾驶区域",
          value: "r_jsqy"
        },
        {
          label: "天气环境",
          value: "r_tqhj"
        },
        {
          label: "季节",
          value: "r_jj"
        }
      ],
      painList: [
        {
          label: "痛点描述",
          value: "0",
          list: [],
          tag: ""
        },
        {
          label: "痛点备注",
          value: "1"
        },
        {
          label: "痛点频次",
          value: "2"
        },
        {
          label: "痛点程度",
          value: "3"
        }
      ],
      indexList: [
        {
          label: "一级指标",
          value: "0",
          list: [],
          tag: ""
        },
        {
          label: "二级指标",
          value: "1"
        },
        {
          label: "三级指标",
          value: "2"
        },
        {
          label: "感知价值",
          value: "3"
        }
      ],
      solveList: [
        {
          label: "当前解决方案",
          value: "0",
          list: [],
          tag: ""
        }
      ],
      tableData: [],
      tableData2: [],
      tableData3: [],
      tableData4: [],
      tableData5: [],
      tableData6: [],
      headerList2: [],
      headercopy: [],
      headerList: [
        {
          mon: '',
          key_str: 'name'
        }
      ],
      tableDataList: [],


    };

  },

  created() {
    this.getDictLabel();
    this.getDictLabelValue();
    this.getDropdownItems();
    this.loadList();
    this.tableData = this.peopleList.splice(0, 3);
    this.tableData2 = this.carList.splice(0, 3);
    this.tableData3 = this.sceneList.splice(0, 3);
    this.tableData4 = this.painList.splice(0, 3);
    this.tableData5 = this.indexList.splice(0, 3);
    this.tableData6 = this.solveList.splice(0, 3);
  },
  methods: {
    reload() {
      this.queryPage = { page: 1, limit: 20 };
      this.loadList();
    },
    save() {
      var data = this.reqUser;
      // const url =
      //   "p_shuweidu="+
      //   data.verticalDimension +
      //   "&p_hengweidu=" +
      //   data.horizontalDimension +
      //   "&p_zhi=" +
      //   data.price +
      //   "&p_nl=" +
      //   data.age +
      //   "&p_hy=" +
      //   data.industry +
      //   "&p_xb=" +
      //   data.sex +
      //   "&p_hyzk=" +
      //   data.maritalStatus +
      //   "&p_xhsl=" +
      //   data.childNum +
      //   "&p_xhnld=" +
      //   data.childAgeScope +
      //   "&p_zysx=" +
      //   data.occupationAttribute +
      //   "&p_jtnsrqk=" +
      //   data.homeIncome +
      //   "&p_xlqk=" +
      //   data.educationalBack +
      //   "&p_cx=" +
      //   data.carSeries +
      //   "&p_jb=" +
      //   data.carLevel +
      //   "&p_cslb=" +
      //   data.carBody +
      //   "&p_cxjl=" +
      //   data.carModelLevel +
      //   "&p_tpjgd=" +
      //   data.tpPrice +
      //   "&p_nylx=" +
      //   data.energyType +
      //   "&p_yjcj=" +
      //   data.oneScene +
      //   "&p_ejcjms=" +
      //   data.twoSceneDescription +
      //   "&p_cxjd=" +
      //   data.travelStage +
      //   "&p_cxrs=" +
      //   data.travelNum +
      //   "&p_yhjs=" +
      //   data.userRole +
      //   "&p_yhtz=" +
      //   data.userFeature +
      //   "&p_jszt=" +
      //   data.driveStatus +
      //   "&p_jsdl=" +
      //   data.driveRoad +
      //   "&p_jsqy=" +
      //   data.driveArea +
      //   "&p_tqhj=" +
      //   data.weather +
      //   "&p_sj=" +
      //   data.time +
      //   "&p_jj=" +
      //   data.season +
      //   "&p_sjcjdd=" +
      //   data.dataLocality +
      //   "&p_csdj=" +
      //   data.cityLevel +
      //   "&p_lssf=" +
      //   data.province +
      //   "&p_yjzb=" +
      //   data.oneIndex +
      //   "&p_ejzb=" +
      //   data.twoIndex +
      //   "&p_sjzb=" +
      //   data.threeIndex +
      //   "&p_gzjz=" +
      //   data.feelPrice +
      //   "&p_gzsk=" +
      //   data.feelTime +
      //   "&p_dqjjfa=" +
      //   data.workOutScheme +
      //   "&p_sjly=" +
      //   data.dataResource;
      console.log(data.verticalDimension, "123123");
      if (data.verticalDimension == "") {
        Message({
          message: "请选择竖维度",
          type: "error",
          duration: 5 * 1000
        });
        return;
      }
      else if (data.horizontalDimension == "") {
        Message({
          message: "请选择横维度",
          type: "error",
          duration: 5 * 1000
        });
        return;
      }
      else if (data.price == "") {
        Message({
          message: "请选择值",
          type: "error",
          duration: 5 * 1000
        });
        return;
      }
      else{
        test(data).then(response => {
        this.tableDataList = response.data
        this.headerList2 = this.headercopy
        this.tableVertial = this.tableVertial2
        this.tableHorizontal = this.tableHorizontal2
        Message({
          message: "查询成功",
          type: "success",
          duration: 5 * 1000
        });
        this.dialogVisible = false;
        // 重新加载表格
        this.loadList();
      });
      }
      
    },
    changeHorizontalDimension(e) {
      getDropdownItemForOne(e).then(response => {
        this.headercopy = response.data
        this.sceneList2.forEach(item => {
          if (e === item.value) {
            console.log(item.label, "123122222223");
            this.tableHorizontal2 = item.label
          }
        })
      })
    },
    changeVerticalDimension(e) {
      getDropdownItemForOne(e).then(response => {
        this.peopleList2.forEach(item => {
          if (e === item.value) {
            this.tableVertial2 = item.label
          }
        })
      })
    },
    // 加载列表
    loadList() {
      this.listLoading = true;
      getPage(this.queryPage)
        .then(response => {
          const { data } = response;
          this.exportData = data;
          this.tableDataValue = data.records;
          this.total = parseInt(data.total);
          this.listLoading = false;
        })
        .catch(response => {
          this.listLoading = false;
        });
    },
    handleDelete(row) {
      console.log(row, "asdsa");
      MessageBox.confirm("确认删除", "确定", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        const loading = this.$loading({
          lock: true,
          text: "Loading",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)"
        });
        // 确保 id 是一个数字
        deleteData(row)
          .then(response => {
            Message({
              message: "删除成功",
              type: "success",
              duration: 5 * 1000
            });
            // 重新加载表格
            this.loadList();
            loading.close();
          })
          .catch(response => {
            loading.close();
          });
      });
    },
    openReport() {
      const url =
        "http://192.168.1.176:8084/report//share/share.html?_key=17e534f26cc79add3a2feb14396267b8ad3ade52725c22939e733c79b23835878741bcbe62826c703f60c349fc327322b09ac10474a43b53f1a3f9bd460f2283&p_shuweidu=" +
        this.reqUser.verticalDimension +
        "&p_hengweidu=" +
        this.reqUser.horizontalDimension +
        "&p_zhi=" +
        this.reqUser.price +
        "&p_nl=" +
        this.reqUser.age +
        "&p_hy=" +
        this.reqUser.industry +
        "&p_xb=" +
        this.reqUser.sex +
        "&p_hyzk=" +
        this.reqUser.maritalStatus +
        "&p_xhsl=" +
        this.reqUser.childNum +
        "&p_xhnld=" +
        this.reqUser.childAgeScope +
        "&p_zysx=" +
        this.reqUser.occupationAttribute +
        "&p_jtnsrqk=" +
        this.reqUser.homeIncome +
        "&p_xlqk=" +
        this.reqUser.educationalBack +
        "&p_cx=" +
        this.reqUser.carSeries +
        "&p_jb=" +
        this.reqUser.carLevel +
        "&p_cslb=" +
        this.reqUser.carBody +
        "&p_cxjl=" +
        this.reqUser.carModelLevel +
        "&p_tpjgd=" +
        this.reqUser.tpPrice +
        "&p_nylx=" +
        this.reqUser.energyType +
        "&p_yjcj=" +
        this.reqUser.oneScene +
        "&p_ejcjms=" +
        this.reqUser.twoSceneDescription +
        "&p_cxjd=" +
        this.reqUser.travelStage +
        "&p_cxrs=" +
        this.reqUser.travelNum +
        "&p_yhjs=" +
        this.reqUser.userRole +
        "&p_yhtz=" +
        this.reqUser.userFeature +
        "&p_jszt=" +
        this.reqUser.driveStatus +
        "&p_jsdl=" +
        this.reqUser.driveRoad +
        "&p_jsqy=" +
        this.reqUser.driveArea +
        "&p_tqhj=" +
        this.reqUser.weather +
        "&p_sj=" +
        this.reqUser.time +
        "&p_jj=" +
        this.reqUser.season +
        "&p_sjcjdd=" +
        this.reqUser.dataLocality +
        "&p_csdj=" +
        this.reqUser.cityLevel +
        "&p_lssf=" +
        this.reqUser.province +
        "&p_yjzb=" +
        this.reqUser.oneIndex +
        "&p_ejzb=" +
        this.reqUser.twoIndex +
        "&p_sjzb=" +
        this.reqUser.threeIndex +
        "&p_gzjz=" +
        this.reqUser.feelPrice +
        "&p_gzsk=" +
        this.reqUser.feelTime +
        "&p_dqjjfa=" +
        this.reqUser.workOutScheme +
        "&p_sjly=" +
        this.reqUser.dataResource;
    },
    getDicName(code, flag) {
      var dict = [];
      if (flag === "YW_DEAL_STATUS") {
        dict = this.statusList;
      }
      for (var i in dict) {
        if (dict[i].code === code) {
          return dict[i].name;
        }
      }
    },
    // 查询
    search() {
      this.loadList();
    },
    addForm1(value1) {
      this.peopleList.forEach(item1 => {
        if (value1 == item1.value) {
          this.tableData.push(item1);
          this.peopleList.splice(this.peopleList.indexOf(item1), 1);
          this.tableDataCompare();
        }
      });
    },
    addForm2(value2) {
      this.carList.forEach(item1 => {
        if (value2 == item1.value) {
          this.tableData2.push(item1);
          this.carList.splice(this.carList.indexOf(item1), 1);
          this.tableData2Compare();
        } else {
        }
      });
    },
    addForm3(value3) {
      this.sceneList.forEach(item1 => {
        if (value3 == item1.value) {
          this.tableData3.push(item1);
          this.sceneList.splice(this.sceneList.indexOf(item1), 1);
          this.tableData3Compare();
        } else {
        }
      });
    },
    addForm4(value4) {
      this.painList.forEach(item1 => {
        if (value4 == item1.value) {
          this.tableData4.push(item1);
          this.painList.splice(this.painList.indexOf(item1), 1);
        } else {
        }
      });
    },
    addForm5(value5) {
      this.indexList.forEach(item1 => {
        if (value5 == item1.value) {
          this.tableData5.push(item1);
          this.indexList.splice(this.indexList.indexOf(item1), 1);
          this.tableData5Compare();
        } else {
        }
      });
    },
    addForm6(value6) {
      this.solveList.forEach(item1 => {
        if (value6 == item1.value) {
          this.tableData6.push(item1);
          this.solveList.splice(this.solveList.indexOf(item1), 1);
          this.tableData6Compare();
        } else {
        }
      });
    },

    getDictLabel() {
      getDictLabel().then(response => {
        this.statusList = response.data;
      });
    },
    getDictLabelValue() {
      getDictLabelValue().then(response => {
        this.statusValueList = response.data;
      });
    },
    tableDataCompare() {
      this.tableData.forEach(item => {
        if (item.value === "0") {
          item.list = this.selectSource.r_nl;
        } else if (item.value === "1") {
          item.list = this.selectSource.r_tpjgd;
        } else if (item.value === "2") {
          item.list = this.selectSource.r_zysx;
        } else if (item.value === "3") {
          item.list = this.selectSource.r_hyzk;
        } else if (item.value === "4") {
          item.list = this.selectSource.r_xhsl;
        } else if (item.value === "5") {
          item.list = this.selectSource.r_xhnld;
        } else if (item.value === "6") {
          item.list = this.selectSource.r_xb;
        } else if (item.value === "7") {
          item.list = this.selectSource.r_jtnsrqk;
        } else if (item.value === "8") {
          item.list = this.selectSource.r_xlqk;
        } else if (item.value === "9") {
          item.list = this.selectSource.r_hy;
        } else if (item.value === "10") {
          item.list = this.selectSource.r_lssf;
        } else if (item.value === "11") {
          item.list = this.selectSource.r_csdj;
        } else if (item.value === "12") {
          item.list = this.selectSource.r_yhtz;
        }
      });
    },

    tableData2Compare() {
      this.tableData2.forEach(item => {
        if (item.value === "0") {
          item.list = this.selectSource.r_nylx;
        } else if (item.value === "1") {
          item.list = this.selectSource.r_jb;
        } else if (item.value === "2") {
          item.list = this.selectSource.r_cslb;
        } else if (item.value === "3") {
          item.list = this.selectSource.r_yjzb;
        } else if (item.value === "4") {
          item.list = this.selectSource.r_ejzb;
        } else if (item.value === "5") {
          item.list = this.selectSource.r_sjzb;
        }
      });
    },

    tableData3Compare() {
      this.tableData3.forEach(item => {
        if (item.value === "0") {
          item.list = this.selectSource.r_yjcj;
        } else if (item.value === "1") {
          item.list = this.selectSource.r_ejcjms;
        } else if (item.value === "2") {
          item.list = this.selectSource.r_ycjd;
        } else if (item.value === "3") {
          item.list = this.selectSource.r_cxrs;
        } else if (item.value === "4") {
          item.list = this.selectSource.r_yhjs;
        } else if (item.value === "5") {
          item.list = this.selectSource.r_yhtz;
        } else if (item.value === "6") {
          item.list = this.selectSource.r_jszt;
        } else if (item.value === "7") {
          item.list = this.selectSource.r_jsdl;
        } else if (item.value === "8") {
          item.list = this.selectSource.r_jsqy;
        } else if (item.value === "9") {
          item.list = this.selectSource.r_tqhj;
        } else if (item.value === "10") {
          item.list = this.selectSource.r_jj;
        } else if (item.value === "11") {
          item.list = this.selectSource.r_cxjd;
        }
      });
    },

    tableData5Compare() {
      this.tableData5.forEach(item => {
        if (item.value === "0") {
          item.list = this.selectSource.r_yjzb;
        } else if (item.value === "1") {
          item.list = this.selectSource.r_ejzb;
        } else if (item.value === "2") {
          item.list = this.selectSource.r_sjzb;
        } else if (item.value === "3") {
          item.list = this.selectSource.r_gzjz;
        }
      });
    },

    tableData6Compare() {
      this.tableData6.forEach(item => {
        if (item.value === "0") {
          item.list = this.selectSource.r_dqjjfa;
        }
      });
    },
    getDropdownItems() {
      getDropdownItems().then(response => {
        this.selectSource = response.data;
        this.tableDataCompare();
        this.tableData2Compare();
        this.tableData3Compare();
        this.tableData5Compare();
        this.tableData6Compare();
      });
    },
    getValueDropdownItems() {
      getValueDropdownItems().then(response => {
        this.selectValueSource = response.data;
      });
    },
    addValue(e) {
      if (e.value === "0") {
        this.reqUser.age = e.tag;
      } else if (e.value === "1") {
        this.reqUser.industry = e.tag;
      } else if (e.value === "2") {
        this.reqUser.sex = e.tag;
      } else if (e.value === "3") {
        this.reqUser.maritalStatus = e.tag;
      } else if (e.value === "4") {
        this.reqUser.childNum = e.tag;
      } else if (e.value === "5") {
        this.reqUser.childAgeScope = e.tag;
      } else if (e.value === "6") {
        this.reqUser.occupationAttribute = e.tag;
      } else if (e.value === "7") {
        this.reqUser.homeIncome = e.tag;
      } else if (e.value === "8") {
        this.reqUser.educationalBack = e.tag;
      }
    },

    addValue2(e) {
      if (e.value === "0") {
        this.reqUser.carSeries = e.tag;
      } else if (e.value === "1") {
        this.reqUser.carLevel = e.tag;
      } else if (e.value === "2") {
        this.reqUser.carBody = e.tag;
      } else if (e.value === "3") {
        this.reqUser.tpPrice = e.tag;
      } else if (e.value === "4") {
        this.reqUser.energyType = e.tag;
      }
    },

    addValue3(e) {
      if (e.value === "0") {
        this.reqUser.oneScene = e.tag;
      } else if (e.value === "1") {
        this.reqUser.twoSceneDescription = e.tag;
      } else if (e.value === "2") {
        this.reqUser.travelStage = e.tag;
      } else if (e.value === "3") {
        this.reqUser.travelNum = e.tag;
      } else if (e.value === "4") {
        this.reqUser.userRole = e.tag;
      } else if (e.value === "5") {
        this.reqUser.userFeature = e.tag;
      } else if (e.value === "6") {
        this.reqUser.driveStatus = e.tag;
      } else if (e.value === "7") {
        this.reqUser.driveRoad = e.tag;
      } else if (e.value === "8") {
        this.reqUser.driveArea = e.tag;
      } else if (e.value === "9") {
        this.reqUser.weather = e.tag;
      } else if (e.value === "10") {
        this.reqUser.season = e.tag;
      } else if (e.value === "11") {
        this.reqUser.dataLocality = e.tag;
      } else if (e.value === "12") {
        this.reqUser.cityLevel = e.tag;
      } else if (e.value === "13") {
        this.reqUser.province = e.tag;
      }
    },

    addValue5(e) {
      if (e.value === "0") {
        this.reqUser.oneIndex = e.tag;
      } else if (e.value === "1") {
        this.reqUser.twoIndex = e.tag;
      } else if (e.value === "2") {
        this.reqUser.threeIndex = e.tag;
      } else if (e.value === "3") {
        this.reqUser.feelPrice = e.tag;
      }
    },
    // 重置
    reload() {
      this.queryPage = { page: 1, limit: 20 };
      this.loadList();
    },
    addValue6(e) {
      if (e.value === "0") {
        this.reqUser.workOutScheme = e.tag;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
:deep(.input-textarea) {
  width: 94% !important;
}
:deep(.phone) {
  width: 60px;
}
.time {
  margin-top: 1%;
}
.relation1 {
  margin-left: 0;
  margin-right: 100px;
}
.el-row {
  margin-left: 0;
  margin-right: 0;
}
.el-table {
  margin: 0 30px;
}
.el-form-item {
  width: 50%;
}
:deep(.el-select) {
  --el-select-width: 80%;
}
.el-form-item {
  width: 47%;
}
:deep(.el-form-item__label) {
  width: 130px !important;
}
.bold {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #85afd5;
  text-align: center;
  margin-top: 5px;
  margin-left: -10px;
  color: #fff;
}
.btitle {
  line-height: 30px;
  margin-left: 10px;
  color: #84b0d5;
}
.tip {
  border: 1px solid #84b0d5;
  border-radius: 0 20px 20px 0;
  width: 140px;
  height: 30px;
  display: flex;
  margin-left: 30px;
  margin-bottom: 20px;
}
.form-container {
  display: flex;
  align-items: center;
}
.m-2 {
  margin-left: 0;
  margin-right: 0;
}

:deep(.relation .el-form-item__label) {
  line-height: 48px;
}
:deep(.relation .el-input) {
  line-height: 48px;
  display: initial;
}
:deep(.el-input) {
  width: 100%;
}
:deep(.el-select) {
  width: 100%;
}
:deep(.el-input-number) {
  width: 100%;
}
.follow {
  margin-left: 30px;
  border: 1px solid #84b0d5;
  padding: 10px 15px;
  width: 85px;
  color: #84b0d5;
  border-radius: 10px;
}
.foow {
  background: azure;
  margin: 0 20px;
  width: calc(100% - 40px);
  padding: 21px 0;
}
.el-row {
  padding: 0 0 10px 0;
  margin: 0 10px;
}
.el-col-8 {
  background: #fff;
  padding-bottom: 10px;
  margin: 0 10px;
}
.el-table {
  margin: 5px 20px;
  width: calc(100% - 40px) !important;
}
.downThree {
  display: flex;
  justify-content: space-around;
}
/* 全局标题样式 */
h1 {
  color: #29c5ab;
  font-size: 24px;
  text-align: left;
  margin-bottom: 20px;
}
::v-deep .el-table thead.is-group th {
  background: none;
}
::v-deep .el-table thead.is-group tr:first-of-type th:first-of-type {
  border-bottom: none;
}
::v-deep .el-table thead.is-group tr:first-of-type th:first-of-type div.cell {
  padding: 0;
}
.header-div {
  height: 80px;
  position: relative;
}
.header-col1 {
  position: absolute;
  left: 10px;
  bottom: 10px;
}
.header-col2 {
  position: absolute;
  right: 10px;
  top: 10px;
}
.header-col3 {
  position: absolute;
  right: 0;
  bottom: 0;
}
.header-line1 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(to top right, transparent 49%, #b3b1b1 50%, transparent 52%);
}
.header-line2 {
  width: 1px;
  height: 150px;
  transform: rotate(-41deg);
  transform-origin: top;
  background-color: blue;
  position: absolute;
  top: 0;
  left: 0;
}
::v-deep.el-table--default .el-table__cell {
  padding: 0 !important;
}
::v-deep.el-table .cell {
  padding: 0 !important;
}
</style>
相关推荐
zhangxiao几秒前
Vite项目打包生成dist.zip方法
前端
Enti7c1 分钟前
定时器的定义
javascript
Version6 分钟前
深入理解JavaScript 中的 this
前端
李鸿耀18 分钟前
前端包管理工具:npm/Yarn/pnpm 特性解析与实战指南
前端
Enti7c26 分钟前
页面重构过程中如何保证良好的跨浏览器一致性?
前端·其他
海狸鼠32 分钟前
几行代码实现MCP服务端/客户端(接入DeepSeek)
前端·后端
木木黄木木38 分钟前
基于HTML5的拖拽排序功能实现详解
前端·html·html5
Stupid42 分钟前
[学习笔记] 工程化的浅入了解
前端
阿航hang43 分钟前
Reactivity 模块
前端
PineSongCN1 小时前
nginx 反向代理后SSE连接无效的问题
前端