自定义 表格组件来解决avue 2.8.14版本的详情样式过于难看的问题

22 篇文章 0 订阅
1 篇文章 0 订阅

1.表格组件

<template>
  <el-table
    :data="tableData"
    border
    style="width: 100%"
    :show-header="false"
    :span-method="arraySpanMethod"
  >
    <el-table-column prop="titleOne" align="center" label="1">
      <template slot-scope="scope">
        <div>
          {{ scope.row.titleOne }}
        </div>
        <div
          v-if="scope.row.subheadingOne"
          style="color: #999999; font-size: 8px"
        >
          {{ scope.row.subheadingOne }}
        </div>
      </template>
    </el-table-column>
    <el-table-column prop="contOne" label="2">
      <template slot-scope="scope">
        <div v-if="scope.row.contOne == '' || scope.row.contOne == null">
          <div v-if="scope.row.contOne == '0'">
            {{ scope.row.contOne }}
          </div>

          <div v-else style="color: red">未上报</div>
        </div>
        <div v-else>
          <div
            v-if="'img' in scope.row && scope.row.img[0]"
            style="display: flex; flex-wrap: wrap"
          >
            <div v-for="(item, index) in scope.row.contOne" :key="index">
              <div
                v-if="
                  [
                    'pdf',
                    'doc',
                    'docx',
                    'jpg',
                    'jpeg',
                    'png',
                    'xls',
                    'xlsx',
                  ].indexOf(getFileType(item.url)) != -1
                "
              >
                <!--  {{scope.row}}
                <a :href="item.url" download style="margin-left: 10px;">11{{
                      item.name
               }}</a> -->

                <span class="donnw" @click="courseDownload(item.url, item.name)">
                  {{ item.name }}
                </span>
              </div>

              <div
                v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1"
              >
                <el-image
                  :src="item"
                  fit="contain"
                  style="width: 100px; height: 120px; margin-left: 10px"
                  :preview-src-list="[item]"
                >
                  <div slot="error" class="image-slot">
                    <div
                      style="
                        width: 100px;
                        height: 120px;
                        background-color: #f6f6f6;
                        font-size: 30px;
                        text-align: center;
                        line-height: 120px;
                      "
                    >
                      <i class="el-icon-picture-outline"></i>
                    </div>
                  </div>
                </el-image>
              </div>
            </div>
          </div>
          <div v-else>
            <div v-if="scope.row.slot && scope.row.slot[0]">
              <slot :name="scope.row.contOneSlot"></slot>
            </div>
            <div v-else v-html="scope.row.contOne">
              <!-- 2222 {{ scope.row.contOne }} -->
            </div>
          </div>
        </div>
      </template>
    </el-table-column>
    <el-table-column prop="titleTwo" align="center" label="3">
      <template slot-scope="scope">
        <div>
          {{ scope.row.titleTwo }}
        </div>
        <div
          v-if="scope.row.subheadingTow"
          style="color: #999999; font-size: 8px"
        >
          {{ scope.row.subheadingTow }}
        </div>
      </template>
    </el-table-column>
    <el-table-column prop="contTow" label="4">
      <template slot-scope="scope">
        <div v-if="scope.row.contTow == '' || scope.row.contTow == null">
          <div v-if="scope.row.contTow == '0'">
            {{ scope.row.contTow }}
          </div>

          <div v-else style="color: red">未上报</div>
        </div>
        <div v-else>
          <div v-if="'img' in scope.row && scope.row.img[1]">
            <div
              v-for="(item, index) in scope.row.contTow"
              :key="index"
              style="display: flex; flex-wrap: wrap"
            >
              <div
                v-if="
                  [
                    'pdf',
                    'doc',
                    'docx',
                    'jpg',
                    'jpeg',
                    'png',
                    'xls',
                    'xlsx',
                  ].indexOf(getFileType(item.url)) != -1
                "
              >
                <!--  {{scope.row}}
                <a :href="item.url" download style="margin-left: 10px;">11{{
                      item.name
               }}</a> -->

                <span class="donnw" @click="courseDownload(item.url, item.name)">
                  {{ item.name }}
                </span>
              </div>
              <div
                v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1"
              >
                <el-image
                  :src="item"
                  fit="contain"
                  style="width: 100px; height: 120px; margin-left: 10px"
                  :preview-src-list="[item]"
                >
                  <div slot="error" class="image-slot">
                    <div
                      style="
                        width: 100px;
                        height: 120px;
                        background-color: #f6f6f6;
                        font-size: 30px;
                        text-align: center;
                        line-height: 120px;
                      "
                    >
                      <i class="el-icon-picture-outline"></i>
                    </div>
                  </div>
                </el-image>
              </div>
            </div>
          </div>
          <div v-else>
            <div v-if="scope.row.slot && scope.row.slot[1]">
              <slot :name="scope.row.contTowSlot"></slot>
            </div>
            <div v-else v-html="scope.row.contTow">
              <!-- {{ scope.row.contTow }} -->
            </div>
          </div>
        </div>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
import axios from "axios";
export default {
  props: {
    data: {
      type: Array,
      default: function () {
        return [];
      },
    },
  },
  data() {
    return {
      tableData: this.data,
    };
  },
  watch: {
    data: {
      handler(newName, oldName) {
        console.log("obj.a changed");
        this.tableData = newName;
      },
      immediate: true,
      deep: true,
    },
  },
  methods: {
    courseDownload(url, filename) {
      this.getBlob(url, (blob) => {
        this.saveAs(blob, filename);
      });
    },
    getBlob(url, cb) {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "blob";
      xhr.onload = function () {
        if (xhr.status === 200) {
          cb(xhr.response);
        }
      };
      xhr.send();
    },
    saveAs(blob, filename) {
      if (window.navigator.msSaveOrOpenBlob) {
        navigator.msSaveBlob(blob, filename);
      } else {
        var link = document.createElement("a");
        var body = document.querySelector("body");

        link.href = window.URL.createObjectURL(blob);
        link.download = filename;
        // fix Firefox
        link.style.display = "none";
        body.appendChild(link);
        link.click();
        body.removeChild(link);
        window.URL.revokeObjectURL(link.href);
      }
    },
    down(url, name) {
      const blob = new Blob([url], {
        //this.detailinfo是后台返回给前台的文档下载链接
        type: "application/msword",
      });
      const objectUrl = URL.createObjectURL(blob);
      const link = document.createElement("a"); //我们用模拟q标签点击事件
      const fname = name; //下载文件的名字
      link.setAttribute("download", fname);
      link.href = url;
      link.target = "_blank";

      link.click(); //点击
      // document.body.removeChild(link); // 下载完成移除元素
      // window.URL.revokeObjectURL(URL); // 释放掉blob对象
      // 针对移动端对于blob兼容不友好,华为手机无反应另外解决  pc端一切正常

      // axios.get(url, {
      //     responseType: 'blob',
      //   })
      //   .then((res) => {
      //     const blob = new Blob([res.data], {
      //       type: 'application/vnd.ms-excel'
      //     }) // 构造一个blob对象来处理数据,并设置文件类型
      //     if (window.navigator.msSaveOrOpenBlob) {
      //       // 兼容IE10
      //       navigator.msSaveBlob(blob, name)
      //     } else {
      //       const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
      //       const a = document.createElement('a')
      //       a.style.display = 'none'
      //       a.href = href // 指定下载链接
      //       a.download = name // 指定下载文件名
      //       a.click()
      //       URL.revokeObjectURL(a.href) // 释放URL对象
      //     }

      //   })
    },
    getFileType(fileName) {
      // 后缀获取
      let suffix = "";
      // 获取类型结果
      let result = "";
      try {
        const flieArr = fileName.split("."); //根据.分割数组
        suffix = flieArr[flieArr.length - 1]; //取最后一个
      } catch (err) {
        //如果fileName为空等.split方法会报错,就走下面的逻辑
        suffix = "";
      }
      // fileName无后缀返回 false
      if (!suffix) {
        //走catch后返回false
        return false;
      }
      suffix = suffix.toLocaleLowerCase(); //将后缀所有字母改为小写方便操作
      /*  这里开始写入需要判断的逻辑体  */
      return suffix; //以上的判断逻辑都没return时反馈当前后缀是其他类型文件后缀
    },
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      // console.log("222")
      if (row.maxRows) {
        if (rowIndex >= 0) {
          if (columnIndex === 1) {
            return [1, 4];
          } else if (columnIndex === 1) {
            return [0, 4];
          }
        }
      }
    },
  },
};
</script>

<style type="text/css" scoped="scoped">
.donnw {
  color: #0055ff;
  margin-right: 10px;
}
</style>


数据转换js文件

contOne:eval(“row.$”+item.prop),

export const formSafetyTabel = (row,tableOption, myexcel = "myexcel") => {
  /**
   * 方法使用办法
   * 
   * img:true 代表图片文件
   * rowViewDisplay:true 表示 不显示在表格
   * zdyslot:true 表示 表格需要自定义
   * slotName:'name' name 表示自定义的slot name
   * maxRows:true 表示换行
   * zdyimg:true自定义图片
   * 
   * 注意 :对应dicURL 和 dicdata  图片 无法进行自定义 slot
   * 
   * ***/



  let rDate = [];

  tableOption.column.map(item => {
    // console.log(item)
    //  1 先判断 viewDisplay 是否为false 如果是false 就可以在上面显示     如果是都不想显示则加上  rowViewDisplay 为true  在column中加
    // console.log(item.zdyViewDisplay)
    if (item.prop != myexcel) {
      if (!item.viewDisplay && !item.rowViewDisplay) {
        //判断是否需要换行
        if ((item.span == 24 || item.maxRows)) {
          // 换行
          //1. 判断是否使用dicurl 或者dicDate
          if (item.dicUrl != undefined || item.dicData != undefined) {
            //使用
            rDate.push({
              titleOne: item.label,
              contOne: row. ['$' + item.prop],
              maxRows: true
            })
          } else if (item.type == 'upload' || item.zdyimg) {
            //  是 图片 文件上传 的内容部分 zdyimg 自定义的为return true;
            // 先判断是字符串还是数组
            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop].constructor == Array ? row. [item.prop] : [row. [item.prop]],
              img: true,
              maxRows: true
            })
          } else if (item.zdyslot) {

            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop],
              slot: true,
              slotName: item.slotName,
              maxRows: true
            })

          } else {
            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop],
              maxRows: true
            })

          }
        } else {
          //不换行
          if (item.dicUrl != undefined || item.dicData != undefined) {
            //使用 dicUrl  或者 dicData
            rDate.push({
              titleOne: item.label,
              contOne: row.['$' + item.prop],
              slot: true,
              slotName: item.slotName,
            })

          } else if (item.type == 'upload' || item.zdyimg) {
            //  是 图片 文件上传 的内容部分 zdyimg 自定义的为return true;
            // 先判断是字符串还是数组
            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop].constructor == Array ? row. [item.prop] : [row. [item.prop]],
              img: true,
              
            })

          } else if (item.zdyslot) {

            // alert(item.label)

            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop],
              slot: true,
              slotName: item.slotName,

            })

          } else {

            rDate.push({
              titleOne: item.label,
              contOne: row.[item.prop],
            })
          }
        }
      }
    }
  })



  /****
   * 
   * 下面是为了将不是 maxRows 的数据结合再一起
  */

  console.log(rDate, 'rDate')

  let data = [];//最后提交数据
  let dataCount = 0;// true表示可以添加到上一个元素 
  rDate.map((item, index) => {
    if (index == 0) {

      if (item.img) {
        item.img = [true, false];
      }

      if (item.slot) {
        item.slot = [true, false];
        item.contOneSlot = item.slotName;
      }

      data.push(item);
      dataCount++;
    } else {
      if (item.maxRows != undefined && item.maxRows) {

        if (item.img) {
          data.push({
            ...item,
            img: [true, false],

          });
          dataCount++;

        } else if (item.slot) {
          data.push({
            ...item,
            slot: [true, false],
            contOneSlot: item.slotName
          });
          dataCount++;
        } else {
          data.push(item);
          dataCount++;
        }


      } else {

        if (data[dataCount - 1].maxRows != undefined && data[dataCount - 1].maxRows) {




          if (item.img) {
            data.push({
              ...item,
              img: [true, false],

            });
            dataCount++;

          } else if (item.slot) {
            data.push({
              ...item,
              slot: [true, false],
              contOneSlot: item.slotName
            });
            dataCount++;
          } else {
            data.push(item);
            dataCount++;
          }

        } else {
          if (data[dataCount - 1].titleTwo != undefined) {

            if (item.img) {
              data.push({
                ...item,
                img: [true, false],

              });
              dataCount++;

            } else if (item.slot) {
              data.push({
                ...item,
                slot: [true, false],
                contOneSlot: item.slotName
              });
              dataCount++;
            } else {
              data.push(item);
              dataCount++;
            }


          } else {



            if (item.img) {

              // item.img = [data[dataCount - 1].img[0], true];
              data[dataCount - 1] = {
                ...data[dataCount - 1],
                titleTwo: item.titleOne,
                contTow: item.contOne,
                img:[data[dataCount - 1].img[0], true]
              }
            } else if (item.slot) {

              // item.slot = [data[dataCount - 1].slot[0], true];
              // item.contTowSlot = item.slotName;
              data[dataCount - 1] = {
                ...data[dataCount - 1],
                titleTwo: item.titleOne,
                contTow: item.contOne,
                slot:[data[dataCount - 1].slot[0], true],
                contTowSlot: item.contTowSlot
              }
            } else {
              data[dataCount - 1] = {
                ...data[dataCount - 1],
                titleTwo: item.titleOne,
                contTow: item.contOne,
              }
            }


          }
        }

      }
    }



  })





  console.log(data, 'data')


  return data;

}

使用步骤

1 导入对应的组件和js文件

import excelTable from '@/components/exce-table/index.vue';
 import {
   formSafetyTabel
 } from '@/components/exce-table/table.js';

2 修改对应avue 表格的js column 第一个插入对应数据

{
      labelWidth: 0,
      prop: "myexcel",
      formslot: true,
      span: 24,
      hide: true,
      editDisplay: false,
      addDisplay: false,
    }

3 调用方法

getExcelData(row) {
        return formSafetyTabel(row,this.tableOption)
      },
      
<template slot-scope="{row,index}" slot="myexcelForm">
              <excel-table :data="getExcelData(row)">
              </excel-table>
            </template>

4 合并

<template>
	<el-table :data="tableData" border style="width: 100%" :show-header="false" :span-method="arraySpanMethod">
		<el-table-column prop="titleOne" align="center" label="1">
			<template slot-scope="scope">
				<div>
					{{ scope.row.titleOne }}
				</div>
				<div v-if="scope.row.subheadingOne" style="color: #999999; font-size: 8px">
					{{ scope.row.subheadingOne }}
				</div>
			</template>
		</el-table-column>
		<el-table-column prop="contOne" label="2">
			<template slot-scope="scope">
				<div v-if="scope.row.contOne == '' || scope.row.contOne == null">
					<div v-if="scope.row.contOne == '0'">
						{{ scope.row.contOne }}
					</div>

					<div v-else style="color: red">未上报</div>
				</div>
				<div v-else>
					<div v-if="'img' in scope.row && scope.row.img[0]" style="display: flex; flex-wrap: wrap">
						<div v-for="(item, index) in scope.row.contOne" :key="index">
							<div v-if="
                  [
                    'pdf',
                    'doc',
                    'docx',
                    'jpg',
                    'jpeg',
                    'png',
                    'xls',
                    'xlsx',
                  ].indexOf(getFileType(item.url)) != -1
                ">
								<!--  {{scope.row}}
                <a :href="item.url" download style="margin-left: 10px;">11{{
                      item.name
               }}</a> -->

								<span class="donnw" @click="courseDownload(item.url, item.name)">
									{{ item.name }}
								</span>
							</div>

							<div v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1">
								<el-image :src="item" fit="contain"
									style="width: 100px; height: 120px; margin-left: 10px" :preview-src-list="[item]">
									<div slot="error" class="image-slot">
										<div style="
                        width: 100px;
                        height: 120px;
                        background-color: #f6f6f6;
                        font-size: 30px;
                        text-align: center;
                        line-height: 120px;
                      ">
											<i class="el-icon-picture-outline"></i>
										</div>
									</div>
								</el-image>
							</div>
						</div>
					</div>
					<div v-else>
						<div v-if="scope.row.slot && scope.row.slot[0]">
							<slot :name="scope.row.contOneSlot"></slot>
						</div>
						<div v-else v-html="scope.row.contOne">
							<!-- 2222 {{ scope.row.contOne }} -->
						</div>
					</div>
				</div>
			</template>
		</el-table-column>
		<el-table-column prop="titleTwo" align="center" label="3">
			<template slot-scope="scope">
				<div>
					{{ scope.row.titleTwo }}
				</div>
				<div v-if="scope.row.subheadingTow" style="color: #999999; font-size: 8px">
					{{ scope.row.subheadingTow }}
				</div>
			</template>
		</el-table-column>
		<el-table-column prop="contTow" label="4">
			<template slot-scope="scope">
				<div v-if="scope.row.contTow == '' || scope.row.contTow == null">
					<div v-if="scope.row.contTow == '0'">
						{{ scope.row.contTow }}
					</div>

					<div v-else style="color: red">未上报</div>
				</div>
				<div v-else>
					<div v-if="'img' in scope.row && scope.row.img[1]">
						<div v-for="(item, index) in scope.row.contTow" :key="index"
							style="display: flex; flex-wrap: wrap">
							<div v-if="
                  [
                    'pdf',
                    'doc',
                    'docx',
                    'jpg',
                    'jpeg',
                    'png',
                    'xls',
                    'xlsx',
                  ].indexOf(getFileType(item.url)) != -1
                ">
								<!--  {{scope.row}}
                <a :href="item.url" download style="margin-left: 10px;">11{{
                      item.name
               }}</a> -->

								<span class="donnw" @click="courseDownload(item.url, item.name)">
									{{ item.name }}
								</span>
							</div>
							<div v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1">
								<el-image :src="item" fit="contain"
									style="width: 100px; height: 120px; margin-left: 10px" :preview-src-list="[item]">
									<div slot="error" class="image-slot">
										<div style="
                        width: 100px;
                        height: 120px;
                        background-color: #f6f6f6;
                        font-size: 30px;
                        text-align: center;
                        line-height: 120px;
                      ">
											<i class="el-icon-picture-outline"></i>
										</div>
									</div>
								</el-image>
							</div>
						</div>
					</div>
					<div v-else>
						<div v-if="scope.row.slot && scope.row.slot[1]">
							<slot :name="scope.row.contTowSlot"></slot>
						</div>
						<div v-else v-html="scope.row.contTow">
							<!-- {{ scope.row.contTow }} -->
						</div>
					</div>
				</div>
			</template>
		</el-table-column>
	</el-table>
</template>

<script>
	import axios from "axios";
	import {
		formSafetyTabel
	} from './table.js'
	export default {
		props: {
			// avue 的 tableOption
			tableOption: {
				type: Object,
				default: function() {
					return {}
				}
			},
			// 传过来的参数
			rowData: {
				type: Object,
				default: function() {
					return {}
				}
			},
			// 自定义名称的名称
			tabName:{
				type: String,
				default:'myexcel'
			}


		},
		data() {
			return {
				tableData:[],
			};
		},
		watch: {
			rowData: {
				handler(newName, oldName) {
					// row,tableOption, myexcel = "myexcel"
					this.tableData = formSafetyTabel(newName,this.tableOption,this.tabName);
				},
				immediate: true,
				deep: true,
			},
		},
		methods: {
			courseDownload(url, filename) {
				this.getBlob(url, (blob) => {
					this.saveAs(blob, filename);
				});
			},
			getBlob(url, cb) {
				var xhr = new XMLHttpRequest();
				xhr.open("GET", url, true);
				xhr.responseType = "blob";
				xhr.onload = function() {
					if (xhr.status === 200) {
						cb(xhr.response);
					}
				};
				xhr.send();
			},
			saveAs(blob, filename) {
				if (window.navigator.msSaveOrOpenBlob) {
					navigator.msSaveBlob(blob, filename);
				} else {
					var link = document.createElement("a");
					var body = document.querySelector("body");

					link.href = window.URL.createObjectURL(blob);
					link.download = filename;
					// fix Firefox
					link.style.display = "none";
					body.appendChild(link);
					link.click();
					body.removeChild(link);
					window.URL.revokeObjectURL(link.href);
				}
			},
			down(url, name) {
				const blob = new Blob([url], {
					//this.detailinfo是后台返回给前台的文档下载链接
					type: "application/msword",
				});
				const objectUrl = URL.createObjectURL(blob);
				const link = document.createElement("a"); //我们用模拟q标签点击事件
				const fname = name; //下载文件的名字
				link.setAttribute("download", fname);
				link.href = url;
				link.target = "_blank";

				link.click(); //点击
				// document.body.removeChild(link); // 下载完成移除元素
				// window.URL.revokeObjectURL(URL); // 释放掉blob对象
				// 针对移动端对于blob兼容不友好,华为手机无反应另外解决  pc端一切正常

				// axios.get(url, {
				//     responseType: 'blob',
				//   })
				//   .then((res) => {
				//     const blob = new Blob([res.data], {
				//       type: 'application/vnd.ms-excel'
				//     }) // 构造一个blob对象来处理数据,并设置文件类型
				//     if (window.navigator.msSaveOrOpenBlob) {
				//       // 兼容IE10
				//       navigator.msSaveBlob(blob, name)
				//     } else {
				//       const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
				//       const a = document.createElement('a')
				//       a.style.display = 'none'
				//       a.href = href // 指定下载链接
				//       a.download = name // 指定下载文件名
				//       a.click()
				//       URL.revokeObjectURL(a.href) // 释放URL对象
				//     }

				//   })
			},
			getFileType(fileName) {
				// 后缀获取
				let suffix = "";
				// 获取类型结果
				let result = "";
				try {
					const flieArr = fileName.split("."); //根据.分割数组
					suffix = flieArr[flieArr.length - 1]; //取最后一个
				} catch (err) {
					//如果fileName为空等.split方法会报错,就走下面的逻辑
					suffix = "";
				}
				// fileName无后缀返回 false
				if (!suffix) {
					//走catch后返回false
					return false;
				}
				suffix = suffix.toLocaleLowerCase(); //将后缀所有字母改为小写方便操作
				/*  这里开始写入需要判断的逻辑体  */
				return suffix; //以上的判断逻辑都没return时反馈当前后缀是其他类型文件后缀
			},
			arraySpanMethod({
				row,
				column,
				rowIndex,
				columnIndex
			}) {
				// console.log("222")
				if (row.maxRows) {
					if (rowIndex >= 0) {
						if (columnIndex === 1) {
							return [1, 4];
						} else if (columnIndex === 1) {
							return [0, 4];
						}
					}
				}
			},
		},
	};
</script>

<style type="text/css" scoped="scoped">
	.donnw {
		color: #0055ff;
		margin-right: 10px;
	}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圣京都

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值