elemnt和antv和ng动态表格的自定义列

elemnt和antv和ng动态表格的自定义列

帮助

ng:NG-ZORRO

antv:Ant Design Vue

elemnt:element

elment效果图

echarts

HTML
<el-card>
      <div class="flex">
        <el-table :data="tableData" border>
          <el-table-column prop="name" label="筛查信息" align="center"> </el-table-column>
          <el-table-column v-for="(item, index) in header" :key="index" :prop="item.prop" :label="item.label" align="center">
            <template slot="header" slot-scope="scope">
              <div class="close">
                <el-popconfirm icon="el-icon-info" :ref="`popover-${scope.$index}`" @onConfirm="close(item)" icon-color="red" title="确定删除吗?"
                  ><el-button type="text" slot="reference">
                    <i class="el-icon-close" />
                  </el-button>
                </el-popconfirm>
              </div>
              <el-select size="mini" v-model="item.schId" @change="schChange(item)" style="width: 100%; margin-bottom: 10px" clearable placeholder="请选择学校">
                <el-option v-for="(i, key) in schArr" :key="key" :label="i.schName" :value="i.schId"></el-option>
              </el-select>
              <el-select size="mini" v-model="item.batchId" @change="batchChange(item)" style="width: 100%; margin-bottom: 10px" clearable placeholder="请选择批次">
                <el-option v-for="(i, key) in batchArr" v-if="i.checkSchId == item.schId ? true : false" :key="key" :label="i.batchName" :value="i.batchId"></el-option>
              </el-select>
              <el-select size="mini" v-model="item.gradeId" @change="gradeChange(item)" style="width: 100%; margin-bottom: 10px" clearable placeholder="请选择年级">
                <el-option v-for="(i, key) in item.gradeArr" :key="key" :label="i.gradeName" :value="i.gradeId"></el-option>
              </el-select>
              <el-select size="mini" v-model="item.classId" @change="classChange(item)" style="width: 100%" clearable placeholder="请选择班级">
                <el-option v-for="(i, key) in item.classArr" :key="key" :label="i.className" :value="i.classId"></el-option>
              </el-select>
            </template>
          </el-table-column>
        </el-table>
        <div class="btn" @click="add">添加对比报表</div>
      </div>
    </el-card>
CSS
.el-table {
  margin-top: 0;
  font-size: 12px;
}
.flex {
  display: flex;
  align-items: flex-start;
}
.btn {
  width: 30px;
  height: 130px;
  text-align: center;
  background: #409efe;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  cursor: pointer;
}
.close {
  display: flex;
  justify-content: flex-end;
  margin-top: -10px;
}
JS
created() {
    this.add()
    this.add()
    this.schlist()
    this.batchlist()
},
methods: {
    add() {
      this.header.push({
        prop: `index + ${this.index}`,
        schId: '',
        batchId: '',
        classId: '',
        gradeId: '',
        gradeArr: [],
        classArr: [],
      })
      this.index += 1
      this.schStatistics()
    },
    async schStatistics() {
      let a = []
      for (const key in this.header) {
        a.push({
          str: this.header[key].prop,
          schId: this.header[key].schId,
          gradeId: this.header[key].gradeId,
          classId: this.header[key].classId,
          batchId: this.header[key].batchId,
        })
      }
      const res = await this.$http.post('/***/****', a)
      if (res.data.code == 0) {
        let data = res.data.data
        for (const i in data) {
          let j = data[i].str
          this.tableData[0][j] = data[i].toScreenedPeopleNum + '/' + data[i].screenedPeopleNum
          this.tableData[1][j] = data[i].normalVisionPeopleNum + '/' + data[i].normalVisionPeopleRate + '%'
          this.tableData[2][j] = data[i].abnormalVisionPeopleNum + '/' + data[i].abnormalVisionPeopleRate + '%'
          this.tableData[3][j] = data[i].myopiaPeopleNum + '/' + data[i].myopiaPeopleRate + '%'
          this.tableData[4][j] = data[i].mildPeopleNum + '/' + data[i].mildPeopleRate + '%'
          this.tableData[5][j] = data[i].moderatePeopleNum + '/' + data[i].moderatePeopleRate + '%'
          this.tableData[6][j] = data[i].severePeopleNum + '/' + data[i].severePeopleRate + '%'
        }
      }
    },
}

ng效果图

echarts

HTML
<nz-card>
      <div class="flex">
        <st
          #st
          (ngModelChange)="st.resetColumns({ emitReload: true })"
          [responsive]
          resizable
          [data]="listOfData"
          [columns]="header"
          style="width: 100%"
        >
          <ng-template st-row="select" type="title" let-item let-index="index">
            <div style="display: flex; justify-content: flex-end; margin-bottom: 10px">
              <a
                nz-popconfirm
                nzPopconfirmTitle="是否删除?"
                nzPopconfirmPlacement="bottom"
                (nzOnConfirm)="confirm(item)"
                (nzOnCancel)="cancel()"
                ><i nz-icon nzType="close" nzTheme="outline"></i
              ></a>
            </div>
            <nz-select
              style="width: 100%; margin-bottom: 10px"
              [(ngModel)]="item.batchId"
              nzAllowClear
              name="chosedBatch"
              nzPlaceHolder="请选择检查批次"
              (ngModelChange)="choseBatchChange(item, index)"
            >
              <nz-option *ngFor="let i of batchList" [nzLabel]="i.batchName" [nzValue]="i.batchId"> </nz-option>
            </nz-select>
            <nz-select
              style="width: 100%; margin-bottom: 10px"
              [(ngModel)]="item.gradeId"
              name="chosedGrade"
              nzPlaceHolder="请选择年级"
              (ngModelChange)="choseGradeChange(item, index)"
              nzAllowClear
            >
              <nz-option *ngFor="let i of gradeList" [nzLabel]="i.gradeName" [nzValue]="i.gradeId"> </nz-option>
            </nz-select>
            <nz-select
              style="width: 100%"
              [(ngModel)]="item.classId"
              name="chosedClass"
              nzPlaceHolder="请选择班级"
              (ngModelChange)="choseClassChange(item, index)"
              nzAllowClear
            >
              <nz-option *ngFor="let i of item.classArr" [nzLabel]="i.className" [nzValue]="i.classId"> </nz-option>
            </nz-select>
          </ng-template>
        </st>
        <div class="btn" (click)="addRow()">添加对比报表</div>
      </div>
    </nz-card>
CSS
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 150px;
  padding: 15px;
  color: white;
  text-align: center;
  background: #409efe;
  cursor: pointer;
}

.select {
  width: 100%;
  margin-bottom: 10px;
}

.flex {
  display: flex;
  align-items: flex-start;
  width: 100%;
}

TS
@ViewChild('st', { static: false }) private st: STComponent;
header: any[] = [
    {
      title: '筛查信息',
      index: 'name',
    },
  ];
  listOfData: any[] = [
    {
      name: '待筛查/已筛查人数',
    },
    {
      name: '视力正常人数/比例',
    },
    {
      name: '视力异常人数/比例',
    },
    {
      name: '近视人数/比例',
    },
    {
      name: '轻度异常人数/比例',
    },
    {
      name: '中度异常人数/比例',
    },
    {
      name: '重度异常人数/比例',
    },
  ];
addRow(): void {
    this.header.push({
      index: `index${this.i}`,
      batchId: null,
      classId: null,
      gradeId: null,
      gradeArr: [],
      classArr: [],
      renderTitle: `select`,
    });
    this.i++;
    this.sch();
  }

ngOnInit(): void {
    this.addRow();
    this.addRow();
    this.gradeService.getAllGrades(1, 0, 1).subscribe((res) => {
      this.gradeListUploading = false;
      if (res && res.code != '0') {
        return;
      }
      this.gradeList = res.data;
    });
    this.reportService.getSelfSchBatchs().subscribe((res) => {
      if (res && res.code != '0') {
        return;
      }
      this.batchList = res.data;
    });
    this.schoolService.getSelfSchoolInfo().subscribe((res) => {
      if (res && res.code != '0') {
        return;
      }
      this.schId = res.data.schId;
    });
  }
  sch() {
    let a = [];
    for (let key = 1; key < this.header.length; key++) {
      a.push({
        str: this.header[key].index,
        schId: this.schId,
        gradeId: this.header[key].gradeId,
        classId: this.header[key].classId,
        batchId: this.header[key].batchId,
      });
    }

    this.schService.getSchStatistics(a).subscribe((res) => {
      if (res && res.code != '0') {
        return;
      }
      let data = res.data;
      for (let i = 0; i < data.length; i++) {
        let j = res.data[i].str;
        this.listOfData[0][j] = data[i].toScreenedPeopleNum + '/' + data[i].screenedPeopleNum;
        this.listOfData[1][j] = data[i].normalVisionPeopleNum + '/' + data[i].normalVisionPeopleRate + '%';
        this.listOfData[2][j] = data[i].abnormalVisionPeopleNum + '/' + data[i].abnormalVisionPeopleRate + '%';
        this.listOfData[3][j] = data[i].myopiaPeopleNum + '/' + data[i].myopiaPeopleRate + '%';
        this.listOfData[4][j] = data[i].mildPeopleNum + '/' + data[i].mildPeopleRate + '%';
        this.listOfData[5][j] = data[i].moderatePeopleNum + '/' + data[i].moderatePeopleRate + '%';
        this.listOfData[6][j] = data[i].severePeopleNum + '/' + data[i].severePeopleRate + '%';
      }
      this.st.resetColumns({ emitReload: true });
      this.st.reset();
      // console.log(this.header);
      console.log(this.listOfData);
    });
  }

confirm(e): void {
    this.header = this.header.filter((item) => item.index != e.index);
    this.sch();
  }

antV效果图

echarts

HTML
<a-button
        class="editable-add-btn"
        @click="Visible = true"
        style="margin-bottom: 20px"
      >
        添加规格
      </a-button>
      <a-table
        :columns="columns"
        :data-source="dataSource"
        bordered
        :row-key="(dataSource) => dataSource.key"
        :pagination="false"
      >
        <!-- 动态 -->
        <template slot="1" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['0'].propertyValue"
          />
        </template>
        <template slot="2" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['1'].propertyValue"
          />
        </template>
        <template slot="3" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['2'].propertyValue"
          />
        </template>
        <template slot="4" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['3'].propertyValue"
          />
        </template>

        <template slot="5" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['4'].propertyValue"
          />
        </template>
        <template slot="7" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['6'].propertyValue"
          />
        </template>
        <template slot="8" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['7'].propertyValue"
          />
        </template>
        <template slot="9" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.dataVOS['8'].propertyValue"
          />
        </template>

        <template slot="skuCode" slot-scope="text, record">
          <a-input allow-clear style="width: 100px" v-model="record.skuCode" />
        </template>
        <!-- 单位 -->
        <template slot="unit" slot-scope="text, record">
          <!-- <a-input allow-clear style="width: 100px" v-model="record.unit" /> -->
          <a-select
            allow-clear
            v-model="record.unit"
            style="width: 100px"
            show-search
            :filter-option="filterOption"
          >
            <a-select-option value="次">次</a-select-option>
            <a-select-option value="件">件</a-select-option>
            <a-select-option value="瓶">瓶</a-select-option>
            <a-select-option value="片">片</a-select-option>
            <a-select-option value="罐">罐</a-select-option>
            <a-select-option value="支">支</a-select-option>
            <a-select-option value="个">个</a-select-option>
            <a-select-option value="cm">cm</a-select-option>
            <a-select-option value="m">m</a-select-option>
            <a-select-option value="g">g</a-select-option>
            <a-select-option value="kg">kg</a-select-option>
            <a-select-option value="人">人</a-select-option>
          </a-select>
        </template>
        <!-- 成本价 -->
        <template slot="costPrice" slot-scope="text, record"
          ><a-input
            allow-clear
            style="width: 100px"
            v-model="record.costPrice"
          />
        </template>
        <!-- 零售价 -->
        <template slot="retailPrice" slot-scope="text, record">
          <a-input
            allow-clear
            style="width: 100px"
            v-model="record.retailPrice"
          />
        </template>
        <!-- 状态 -->
        <template slot="isDel" slot-scope="text, record">
          <a-switch
            checked-children="正常"
            un-checked-children="停用"
            v-model="record.isDels"
          />
        </template>
        <!-- 允许折扣 -->
        <template slot="isDiscount" slot-scope="text, record">
          <a-switch
            checked-children="是"
            un-checked-children="否"
            v-model="record.isDiscount"
          />
        </template>
        <!-- 允许积分 -->
        <template slot="isUsePoint" slot-scope="text, record">
          <a-switch
            checked-children="是"
            un-checked-children="否"
            v-model="record.isUsePoint"
          />
        </template>
        <!-- 图片 -->
        <template slot="image" slot-scope="text, record, index">
          <div>
            <a-upload
              :action="url"
              :headers="headers"
              list-type="picture-card"
              method="post"
              :file-list="record.imgArr"
              @preview="handlePreview"
              @change="
                (fileList) => {
                  return handleChange(fileList, index);
                }
              "
            >
              <div v-if="record.imgArr.length < 1">
                <a-icon type="plus" />
                <div class="ant-upload-text">上传</div>
              </div>
            </a-upload>
            <a-modal
              :visible="previewVisible"
              :footer="null"
              @cancel="handleCancel"
            >
              <img alt="example" style="width: 100%" :src="previewImage" />
            </a-modal>
          </div>
        </template>
        <!-- 操作 -->
        <template slot="operation" slot-scope="text, record">
          <a-popconfirm
            v-if="dataSource.length > 1"
            title="是否删除?"
            @confirm="() => onDelete(record)"
          >
            <a href="javascript:;">删除</a>
          </a-popconfirm>
        </template>
      </a-table>
      <a-button
        class="editable-add-btn"
        @click="TdAdd"
        style="margin-top: 20px"
      >
        添加参数
      </a-button>
JS
data(){
    return{
        // 表格
      dataSource: [
        {
          key: 0,
          costPrice: "",
          dataVOS: [],
          imgArr: [],
          image: "",
          isDels: true,
          isDiscount: true,
          isUsePoint: true,
          map: {},
          productId: "",
          propertyId: "",
          propertyName: "",
          propertyValue: "",
          propertyValueId: "",
          retailPrice: "",
          salesNum: "",
          skuCode: "",
          stockNum: "",
          unit: "",
        },
      ],
      size: [
        "颜色",
        "度数",
        "材质",
        "重量",
        "尺寸",
        "规格",
        "型号",
        "设计",
        "容量",
        "疗程",
        "近视度数",
        "散光度数",
        "轴位",
        "功能",
      ],
      Visible: false,
      Loading: false,
      count: 1,
      counts: 1,
      columns: [
        {
          title: "单位",
          dataIndex: "unit",
          scopedSlots: { customRender: "unit" },
          align: "center",
        },
        {
          title: "成本价",
          dataIndex: "costPrice",
          scopedSlots: { customRender: "costPrice" },
          align: "center",
        },
        {
          title: "零售价",
          dataIndex: "retailPrice",
          scopedSlots: { customRender: "retailPrice" },
          align: "center",
        },
        {
          title: "状态",
          scopedSlots: { customRender: "isDel" },
          align: "center",
        },
        {
          title: "允许折扣",
          scopedSlots: { customRender: "isDiscount" },
          align: "center",
        },
        {
          title: "允许积分",
          scopedSlots: { customRender: "isUsePoint" },
          align: "center",
        },
        {
          title: "条形码(skucode)",
          dataIndex: "skuCode",
          scopedSlots: { customRender: "skuCode" },
          align: "center",
        },
        {
          title: "图片",
          dataIndex: "image",
          scopedSlots: { customRender: "image" },
          align: "center",
        },
        {
          title: "操作",
          dataIndex: "operation",
          scopedSlots: { customRender: "operation" },
          align: "center",
        },
      ],
      // 图片
      previewVisible: false,
      previewImage: "",
      headers: {
        Authorization: localStorage.getItem("***"),
      },
      url: process.env.VUE_APP_BASEURL + "/****/****",  
    }
}
created() {
    this.baseProductDetail();
},
methods: {
    // 详情
    async baseProductDetail() {
      let res = await this.$http.get("/***/***", {
        params: {
          id: this.$props.row.id,
        },
      });
      if (res.data.success == true) {
        this.$nextTick(() => {
          this.form.setFieldsValue({
            brandId: res.data.data.baseProduct.brandId,
            categoryId: res.data.data.baseProduct.categoryId,
            englishName: res.data.data.baseProduct.englishName,
            manufacturer: res.data.data.baseProduct.manufacturer,
            name: res.data.data.baseProduct.name,
            productCode: res.data.data.baseProduct.productCode,
            pyCode: res.data.data.baseProduct.pyCode,
            remark: res.data.data.baseProduct.remark,
            supplierId: res.data.data.baseProduct.supplierId,
            warnNum: res.data.data.baseProduct.warnNum,
            warnDay: res.data.data.baseProduct.warnDay,
          });
        });
        if (res.data.data.productSkuList != null) {
          let arr = [];
          for (const key in res.data.data.productSkuList) {
            res.data.data.productSkuList[key].isDels =
              res.data.data.productSkuList[key].isDel == 0 ? true : false;
          }
          this.dataSource = res.data.data.productSkuList;
          for (const key in this.dataSource) {
            this.dataSource[key].key = this.dataSource[key].id;
            arr.push(this.dataSource[key].id);
            this.dataSource[key].imgArr = [];
            if (this.dataSource[key].image != "") {
              this.dataSource[key].imgArr.push({
                uid: "-1",
                name: "image.png",
                status: "done",
                response: {
                  data: this.dataSource[key].image,
                },
                url: process.env.VUE_APP_BASEURL + this.dataSource[key].image,
              });
            }
            if (this.dataSource[key].dataVOS == null) {
              this.dataSource[key].dataVOS = [];
            }
          }
          let max = Math.max(...arr);
          this.count = max + 1;
          this.dataSource[0].nameArr =
            this.dataSource[0].propertyName.split(",");
          if (this.dataSource[0].dataVOS.length > 0) {
            let Arr = [];
            for (const i in this.dataSource[0].dataVOS) {
              Arr.push(this.dataSource[0].dataVOS[i].propertyId);
              let newData = {
                title: (
                  <div>
                    {this.dataSource[0].dataVOS[i].propertyName}
                    <a
                      onClick={() =>
                        this.onDel(this.dataSource[0].dataVOS[i].propertyName)
                      }
                    >
                      <a-icon type="close" style="margin-left:5px" />
                    </a>
                  </div>
                ),
                key: this.dataSource[0].dataVOS[i].propertyName,
                scopedSlots: {
                  customRender: this.dataSource[0].dataVOS[i].propertyId,
                },
                align: "center",
              };
              this.columns.unshift(newData);
            }

            let Max = Math.max(...Arr);
            this.thIndex = Max + 1;
          } else {
            this.thIndex = 1;
          }
        }
      }
    },
    // 删除参数
    onDelete(key) {
      const dataSource = [...this.dataSource];
      this.dataSource = dataSource.filter((item) => item.key !== key.key);
      this.removeIds.push(key.id);
    },
    // 删除规格
    onDel(key) {
      console.log(key);
      const columns = [...this.columns];
      this.columns = columns.filter((item) => item.key !== key);
      console.log(this.dataSource);
      if (this.dataSource.length > 0) {
        for (const key in this.dataSource) {
          for (const i in this.dataSource[key].dataVOS) {
            if (this.dataSource[key].dataVOS[i].propertyName == key) {
              this.dataSource[key].dataVOS[i].split(i, 1);
            }
          }
        }
      }
    },
    ThAdd() {
      const { checkedList } = this;
      for (let key = 0; key < checkedList.length; key++) {
        for (let i = 0; i < this.columns.length; i++) {
          if (this.columns[i].key == checkedList[key]) {
            this.$message.error(checkedList[key] + "重复");
            this.Visible = false;
            return;
          }
        }
        let newData = {
          title: (
            <div>
              {checkedList[key]}
              <a onClick={() => this.onDel(checkedList[key])}>
                <a-icon type="close" style="margin-left:5px" />
              </a>{" "}
            </div>
          ),
          key: checkedList[key],
          scopedSlots: { customRender: this.thIndex },
          align: "center",
        };
        this.columns.unshift(newData);
        for (let i = 0; i < this.dataSource.length; i++) {
          if (this.dataSource[i].dataVOS) {
            this.dataSource[i].dataVOS.push({
              propertyId: this.thIndex,
              propertyName: checkedList[key],
              propertyValue: "",
              propertyValueId: this.thIndex,
            });
          }
        }
        this.thIndex += 1;
      }

      this.Visible = false;
      this.checkedList = [];
    },
    TdAdd() {
      const { count } = this;
      const newData = {
        imgArr: [],
        key: this.count,
        costPrice: "",
        dataVOS: [],
        image: "",
        isDels: true,
        isDiscount: true,
        isUsePoint: true,
        productId: "",
        propertyId: "",
        propertyName: "",
        propertyValue: "",
        propertyValueId: "",
        retailPrice: "",
        salesNum: "",
        skuCode: "",
        stockNum: "",
        unit: "",
      };
      if (this.dataSource.length > 0) {
        for (const key in this.dataSource[0].dataVOS) {
          newData.dataVOS.push({
            propertyName: this.dataSource[0].dataVOS[key].propertyName,
            propertyId: this.dataSource[0].dataVOS[key].propertyId,
            propertyValueId: this.dataSource[0].dataVOS[key].propertyValueId,
          });
        }
      }

      this.dataSource.push(newData);
      this.count = count + 1;
    },
}

问题:ng遇到的问题比较多,可能是我属性用的还不是很熟练,表格的话我是在NG-ALAIN里找到的普通版本的表头和表格是分开的动态列渲染不了(可能是单纯的我菜)

posted @ 2021-06-24 16:56  孤常一人  阅读(420)  评论(0编辑  收藏  举报