能源党建后台项目总结

1.引入

本次框架是Ruoyi-plus+vue2+element组合。

2.样式

由于是后台项目,样式要求统一,不可以有的输入框长有的短。着重几点:

1.关于form表单应该如何水平布局

在element中,form有个属性叫::inline="true"时候就会水平。但是有问题有的输入框比较长,像日期选择器和普通输入框大小就不一致。此时就不应该使用这个属性。应该用el-row,el-col。因为输入框默认是独占一行的就像div

代码如下

 <el-form :model="queryParams" ref="queryForm" label-width="80px"><el-row :gutter="20"><el-col :span="8"><el-form-item label="考核年度" prop="appraisalYear"><el-date-pickerv-model="queryParams.appraisalYear"type="year"placeholder="选择年"value-format="yyyy-MM-dd"></el-date-picker></el-form-item></el-col><el-col :span="8"><el-form-item label="负责人" prop="userId"><el-select v-model="queryParams.userId" placeholder="请选择"><el-optionv-for="(item, index) in userList":key="index":label="item.nickName":value="item.userId"></el-option></el-select></el-form-item></el-col><el-col :span="8"><el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button><el-button icon="el-icon-refresh-right" @click="resetQuery">重置</el-button></el-col></el-row></el-form>

2.当form表单过多时,如何布局

添加一个模板  <template v-if="advanced">利用advanced去控制遮住还是隐藏

    <el-form :model="queryParams" ref="queryForm" label-width="80px"><el-row :gutter="20"><el-col :span="8"><el-form-item label="时间" prop="date"><el-date-pickerv-model="queryParams.date"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"></el-date-picker></el-form-item></el-col><el-col :span="8"><el-form-item label="名称" prop="taskName"><el-inputv-model="queryParams.taskName"placeholder="请输入"clearable/></el-form-item></el-col><template v-if="advanced"><el-col :span="8"><el-form-item label="紧急程度" prop="level"><el-select v-model="queryParams.level" placeholder="请选择"><el-option label="一般" value="0"></el-option><el-option label="急" value="1"></el-option><el-option label="紧急" value="2"></el-option></el-select></el-form-item></el-col><el-col :span="8"><el-form-item label="阅读状态" prop="isRead"><el-select v-model="queryParams.isRead" placeholder="请选择"><el-option label="未读" value="0"></el-option><el-option label="已读" value="1"></el-option></el-select></el-form-item></el-col><el-col :span="8"><el-form-item label="任务状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择"><el-option label="未开始" value="0"></el-option><el-option label="进行中" value="1"></el-option><el-option label="已提交" value="2"></el-option><el-option label="已完成" value="3"></el-option></el-select></el-form-item></el-col></template><el-col :span="8"><div style="margin-left: 30px"><el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button><el-button icon="el-icon-refresh-right" @click="resetQuery">重置</el-button><a @click="toggleAdvanced" style="margin-left: 16px">{{ advanced ? "收起" : "展开" }}<i:class="advanced ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i></a></div></el-col></el-row></el-form>

3.业务逻辑

重点!!!先说说详情,编辑,行复制,删除,导入,导出,多选框的表格,单选框的表格,时间搜索,vue2数组和表单数据的渲染,文件的回显,图片的回显,还有es6语法,js逻辑。

1.详情

详情的话可以取决于你的页面是否和新增长的一样,如果长的一样,可以表单控制一个disabled属性来控制禁止输入

例子

 <el-form-item label="考核年度" prop="fulfillYear"><el-date-pickerv-model="form.fulfillYear"type="year"placeholder="选择年度"value-format="yyyy":disabled="disabled"></el-date-picker></el-form-item>

2.新增

外层的新增和编辑我会使用一个页面,没啥好说的。重点是内层新增她还可以编辑这个重点。如何编辑完可以拿到回调的值,这个难。

在编辑的页面增加一个标识符判断编辑还是新增

 save() {console.log("this.form", this.form);// this.$emit("getList", this.form);this.$emit("getList", {...this.form,addType: this.title === "新增考评指标" ? "add" : "edit",time: new Date().getTime(),});this.innerVisible = false;},

在新增的页面判断是新增还是编辑

    getList(value) {let newAddData = [];console.log("我收到了子组件新增标准的值", value);if (value.addType === "edit") {// 创建一个与this.tableData相同结构和内容的新数组// 使用JSON.parse(JSON.stringify(object))来深拷贝对象,避免直接修改原对象let marr = JSON.parse(JSON.stringify(this.tableData));// marr.forEach((item, index) => {//   if (index == value.index) {//     item = value;//   }// });marr[value.index] = value;console.log(marr);this.tableData = marr;console.log(marr);} else {if (Array.isArray(value)) {newAddData = [...this.tableData, ...value];} else {// 若 res.data 不是数组,将其包装成数组再进行合并newAddData = [...this.tableData, value];}// const newList = [...this.tableData, value];this.tableData = newAddData;// this.tableData.sort((a, b) => {//   // 先按照sort字段降序排序//   if (a.sort !== b.sort) {//     return a.sort - b.sort;//   } // 如果sort相同,则按照time字段升序排序(转换为毫秒)//   else {//     return b.time - a.time;//   }// });}// const newList = [...this.tableData, value];// this.tableData = newList;console.log("this.tableData", this.tableData);console.log("this.deptOptions", this.deptOptions);// 遍历tableData数组,根据deptId查找对应的labelthis.tableData = this.tableData.map((item) => {const deptName = this.findLabelById(item.deptId, this.deptOptions);const userIds = item.userIds?.split(",");if (userIds) {const userNames = userIds.map((item2) => {const user = this.userList.find((item3) => item3.userId === item2);// console.log("userNames", userNames);return user ? user.nickName : null;}).join(",");return { ...item, deptName, userNames };} else {return { ...item, deptName };}});console.log("this.tableData", this.tableData);},

这边要注意什么是浅拷贝和深拷贝,我之前都是浅拷贝,这边要改成深拷贝,深拷贝的话避免直接修改原对象。

3.编辑

编辑的话,通常后台需要传当前行的数据进去,后端会提供一个id,去查找数据,数据回显就好了。主要是文件和图片的回显看下面

4.行复制

代码如下 深拷贝一个对象这样不会影响原对象, delete copy.createTime;删除对象属性 es6语法,这边的逻辑就是复制一个和原对象无关的对象,然后用接口新增。 这边重点是es6语法和深浅拷贝的了解与引用

1.深拷贝

const copy = JSON.parse(JSON.stringify(row));

2. 浅拷贝

 const copy = Object.assign({}, row);
  • 如果修改的是第一层(直接)属性且它们是原始类型,row 不受影响;
  • 如果修改的是第一层(直接)属性且它们是引用类型(如其他对象或数组),实际上是在修改共享的嵌套对象,此时 row 会相应地发生改变。
  • 例子如下
  • const row = {name: 'John',address: {street: 'Main St.',number: 123,},
    };const copy = Object.assign({}, row);// 修改第一层属性(字符串),不影响 row
    copy.name = 'Jane'; // row.name仍然是'John'// 修改嵌套对象的属性,会影响 row
    copy.address.street = 'New St.'; // row.address.street现在也是'New St.'

 async copyRow(row) {console.log("row", row);// this.loading = true;const copy = JSON.parse(JSON.stringify(row));delete copy.createTime;copy.dutyAppraisalId = null;copy.status = nullcopy.isRead = 0copy.progress = 0console.log("copy", copy);await this.getDetail(row.dutyAppraisalId);addDemo({status: 0,type: 0,...copy,dutyItems: this.tableData,}).then((res) => {if (res.code == 200) {this.$message({message: "新建成功",type: "success",});this.loading = false;this.getList();}});// .finally(() => {//   this.loading = false;// });},

5.删除

在这个项目中有3中删除

第一种:利用接口拿到id,接口删除

  del(No, data) {// console.log("No", No, "DATA", data);if (data.workItemId) {delDetailList(data.workItemId).then((res) => {if (res.code == 200) {this.$message({message: "删除成功",type: "success",});this.deleteFuc(No, data);}});} else {this.deleteFuc(No, data);}},

第二种:不需要调用接口时候,利用filter es6的语法

 // 使用数组的filter方法,传入一个回调函数作为筛选条件// 回调函数接受当前遍历项(item)作为参数,检查其"No"属性是否与传入的No参数相异// 若相异则保留该项,否则过滤掉const filterData = this.originalData.filter((item) => {return item.No !== No;});

第三种:直接用数组splice

      this.fileList.splice(index, 1);

6.导入

三部曲

第一步:

 <el-uploadclass="upload-demo":action="uploadFileUrl"multiple:show-file-list="false":headers="headers":on-success="handleUploadSuccess"><el-button>导入</el-button></el-upload>

第二步:定义, id不存在,存在,不确定存不存在的写法都在下方

import { getToken } from "@/utils/auth";
export default {components: { contentSet, editStandard },data() {return {activeName: "first",activeName2: "first",form: {},title: "",dialogVisible: false,// 接收数据tableData: [],updatedData: [],// 字典值List: [],showData: [], //展示数据originalData: [], //真正的数据// rowData: {}, //行数据uploadFileUrl: `${process.env.VUE_APP_BASE_API}/epb/workItem/importData${this.form && this.form.id ? "?workId=" + this.form.id : ""}`,// uploadFileUrl: `${process.env.VUE_APP_BASE_API}/epb/workItem/importData?workId=${this.form.id}`, // 上传文件服务器地址// uploadFileUrl: process.env.VUE_APP_BASE_API + "/epb/workItem/importData", // 上传文件服务器地址headers: {Authorization: "Bearer " + getToken(),},show: false,workList: [],loading: false,};},

第三步:

 // 导入文件handleUploadSuccess(res, file) {// console.log("res", res, "file", file);if (res.code == 200) {//深拷贝let mArr = JSON.parse(JSON.stringify(tableData));// 页面操作  concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。mArr = mArr.concat(res.data.workItemVos);mArr = mArr.map((item, index) => {return {...item,sort: item.sort + 1, //一开始就遍历加上序号markTime: new Date().getTime(),};});// console.log("mArr", mArr);this.getContentList(mArr);// this.workList = [];this.workList = this.workList.concat(res.data.workLabelVos);console.log("this.workList", this.workList);}},

7.导出

 <el-buttontype="primary"plainicon="el-icon-download"@click="handleExport">导出</el-button>/** 导出按钮操作 */handleExport() {this.download("/epb/dutyFulfill/export",{...this.queryParams,},`责任落实档案列表.xlsx`);},

8.多选框的表格

9.单选框的表格

10.时间搜索

    getList() {// this.getTime();let mData = Object.assign({pageNum: this.pagination.current,pageSize: this.pagination.pageSize,},// this.queryParams{...this.queryParams,startTime: this.queryParams?.date?.length ? dayjs(this.queryParams.date[0]).format("YYYY-MM-DD") : undefined,endTime: this.queryParams?.date?.length > 1 ? dayjs(this.queryParams.date[1]).format("YYYY-MM-DD") : undefined,});mData.createUserId = store.getters.userId;this.loading = true;listDemo(mData).then((res) => {if (res.code == 200) {console.log("res", res);this.remindersList = res.rows;console.log("this.remindersList", this.remindersList);this.pagination.total = res.total;this.loading = false;}}).finally(() => {this.loading = false;});},

11.对象的键名

   //         const obj = {//             a: 1,//             b: 2,//             c: []//           }//           obj['c']就是数组,拿到的是obj.c的值,可以用push
  groupAndMergeData(arr) {// console.log("a2222", arr);let groupedData = {}; // 遍历newAddData,按workContent字段分类arr.forEach((item) => {//         const obj = {//             a: 1,//             b: 2,//             c: []//           }//           obj['c']就是数组,拿到的是obj.c的值,可以用pushif (!groupedData[item.workContent]) {// [item.workContent]表示键名groupedData[item.workContent] = [item];} else {groupedData[item.workContent].push(item);// groupedData[item.workContent].sort((a, b) => a.sort - b.sort);groupedData[item.workContent].sort((a, b) => {// 先按照sort字段降序排序if (a.sort !== b.sort) {return a.sort - b.sort;} // 如果sort相同,则按照time字段升序排序(转换为毫秒)else {return b.markTime - a.markTime;}});}});// console.log("arr11111", arr);// console.log("groupedData", groupedData);// 合并所有子数组let mergedData = [];for (let category in groupedData) {mergedData = [...mergedData, ...groupedData[category]];}// console.log("mergedData", mergedData);// 全部数据保存到这个真正的数据里const sortData = [...mergedData].map((item, index) => {return {...item,No: index + 1, //一开始就遍历加上序号};});return sortData;},

分组 一种是对象的分组,一种的数组的分组

数组的分组

  let classifyWorkContentList = []; //类别数组[...sourceData].forEach((item) => {// .includes()方法返回一个布尔值(true或false)if (classifyWorkContentList.indexOf(item.workContent) === -1) {classifyWorkContentList.push(item.workContent);}});

12.文件的回显

  const fileArr =data?.fileUrl?.split(",")?.map((item, index) => {return {fileUrl: item,fileName: data?.fileName?.split(",")[index],};}) || [];this.form = data;this.$set(this.form, "fileList", fileArr);<el-descriptions-item label="附件" :span="2"><span v-for="(item, index) in form.fileList" :key="index"><a :href="item.fileUrl" target="_blank">{{ item.fileName }}</a>,</span></el-descriptions-item>

这边的index因为fileUrl和fileName不是一个数组里的,俩个本来是俩个字符串,然后用split分隔成俩个数组,这边的操作就是把它们弄到一个数组里

13.图片的回显

<template><div><el-image v-for="(item,index) in realSrcList" :key="index":src="`${item}`"fit="cover":style="`width:${realWidth};height:${realHeight};`":preview-src-list="realSrcList"><div slot="error" class="image-slot"><i class="el-icon-picture-outline"></i></div></el-image></div></template><script>export default {name: "ImagePreview",props: {src: {type: String,default: ""},width: {type: [Number, String],default: ""},height: {type: [Number, String],default: ""}},computed: {realSrc() {if (!this.src) {return;}let real_src = this.src.split(",")[0];return real_src;},realSrcList() {if (!this.src) {return;}let real_src_list = this.src.split(",");let srcList = [];real_src_list.forEach(item => {return srcList.push(item);});return srcList;},realWidth() {return typeof this.width == "string" ? this.width : `${this.width}px`;},realHeight() {return typeof this.height == "string" ? this.height : `${this.height}px`;}},
};
</script><style lang="scss" scoped>
.el-image {border-radius: 5px;background-color: #ebeef5;box-shadow: 0 0 5px 1px #ccc;::v-deep .el-image__inner {transition: all 0.3s;cursor: pointer;&:hover {transform: scale(1.2);}}::v-deep .image-slot {display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;color: #909399;font-size: 30px;}
}
</style>

父组件

 <ImagePreview:src="form.picUrl":width="150":height="150"></ImagePreview>

14.es6语法

map,filter

15.js逻辑关于党务工作清单的 

第一步:要先判断是编辑还是新增。第二步:要确定传给后端的格式。第三步:展示数据的格式。第四步:删除的排序要判断是有id的还是直接删除。第五步:当导入进来的时候,相当于新增,要进行,说明新增的时候要进行判断,如果是数据还是对象。第六步:对于这种提交数据和展示数据不一样数据格式时候要注意操作。

第一步:

  getContentList(value) {// console.log("我收到子组件传递的值", value);let newData = [];let newAddData = [];if (value.addType === "edit") {// console.log("this.originalData", this.originalData);newData = this.originalData.map((item) => {if (item.No === value.No) {return value;}return item;});} else {if (Array.isArray(value)) {newData = [...this.originalData, ...value];} else {// 若 res.data 不是数组,将其包装成数组再进行合并newData = [...this.originalData, value];}}// console.log("value111", value);// console.log("更新后的newData:", newData);const sortData = this.groupAndMergeData(newData);// 赋值给真正的数组this.originalData = sortData;// console.log("sortData时间字段", sortData);// 赋值给展示数据this.showData = this.handleData(sortData);},

数据分类

   // 分类排序groupAndMergeData(arr) {// console.log("a2222", arr);let groupedData = {}; // 遍历newAddData,按workContent字段分类arr.forEach((item) => {//         const obj = {//             a: 1,//             b: 2,//             c: []//           }//           obj['c']就是数组,拿到的是obj.c的值,可以用pushif (!groupedData[item.workContent]) {// [item.workContent]表示键名groupedData[item.workContent] = [item];} else {groupedData[item.workContent].push(item);// groupedData[item.workContent].sort((a, b) => a.sort - b.sort);groupedData[item.workContent].sort((a, b) => {// 先按照sort字段降序排序if (a.sort !== b.sort) {return a.sort - b.sort;} // 如果sort相同,则按照time字段升序排序(转换为毫秒)else {return b.markTime - a.markTime;}});}});// console.log("arr11111", arr);// console.log("groupedData", groupedData);// 合并所有子数组let mergedData = [];for (let category in groupedData) {mergedData = [...mergedData, ...groupedData[category]];}// console.log("mergedData", mergedData);// 全部数据保存到这个真正的数据里const sortData = [...mergedData].map((item, index) => {return {...item,No: index + 1, //一开始就遍历加上序号};});return sortData;},

 重点是对象键名 变数组

  //         const obj = {//             a: 1,//             b: 2,//             c: []//           }//           obj['c']就是数组,拿到的是obj.c的值,可以用push

 展示数据处理

 // 处理数据handleData(sourceData) {// 分类let classifyWorkContentList = []; //类别数组[...sourceData].forEach((item) => {// .includes()方法返回一个布尔值(true或false)if (classifyWorkContentList.indexOf(item.workContent) === -1) {classifyWorkContentList.push(item.workContent);}});console.log("classifyWorkContentList", classifyWorkContentList);// 按照表格样式修改数据结构// 例如[{workContent: 'xxx', workNormList: [{workItemId: 1111,workId: 11111 ,workContent:'xxx',sort: 1,workNorm:'xxx',No: 1,isDone: 0}]const handleData = classifyWorkContentList.map((item) => {return {workContent: item,workNormList: sourceData.filter((item2) => item2.workContent === item),};});return handleData;},

删除数据 

    deleteFuc(No, data) {const filterData = this.originalData.filter((item) => {return item.No !== No;});const sortData = filterData.map((item, index) => {return {...item,No: index + 1, //一开始就遍历加上序号};});this.originalData = sortData;// 赋值给展示数据this.showData = this.handleData(sortData);},// 删除del(No, data) {// console.log("No", No, "DATA", data);if (data.workItemId) {delDetailList(data.workItemId).then((res) => {if (res.code == 200) {this.$message({message: "删除成功",type: "success",});this.deleteFuc(No, data);}});} else {this.deleteFuc(No, data);}},

 导入文件

 // 导入文件handleUploadSuccess(res, file) {// console.log("res", res, "file", file);if (res.code == 200) {const tableData = [];let mArr = JSON.parse(JSON.stringify(tableData));// 页面操作  concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。mArr = mArr.concat(res.data.workItemVos);mArr = mArr.map((item, index) => {return {...item,sort: item.sort + 1, //一开始就遍历加上序号markTime: new Date().getTime(),};});// console.log("mArr", mArr);this.getContentList(mArr);// this.workList = [];this.workList = this.workList.concat(res.data.workLabelVos);console.log("this.workList", this.workList);}},

16.树形下拉框

子组件 

<template><div><a-tree-selectv-model="orgId"style="width: 100%"size="large":dropdown-style="{ maxHeight: '400px', overflow: 'auto', zIndex: 3000 }"placeholder="请选择"allow-cleartree-default-expand-all:disabled="disabled":tree-data="vorganTreeData":replaceFields="replaceFields"@change="onChange"></a-tree-select></div>
</template><script>
//注意!!!!!
//在modal弹窗组件中使用该组件需要在关闭弹窗方法里清空数据否则会报错
import { userdepList } from "@/api/user/user";
export default {name: "vorganTree",props: {value: {// 如果希望value可以接收int类型的值而不报错,可以将type类型修改为可以兼容字符串和整数的类型type: [String, Number],default: "",},disabled: {type: Boolean,default: false,},replaceFields: {type: Object,default: () => {return {children: "children",title: "label",key: "id",value: "id",};},},},data() {return {orgId: this.value,vorganTreeData: [],deptId: "",};},watch: {value: {handler(newVal) {this.orgId = newVal;},immediate: true,},},mounted() {// this.$bus.$on("id", (data) => {//   console.log("我是任务组件,收到了数据", data);//   this.deptId = data;// });this.deptId = this.$bus.id;this.userdepList();},methods: {userdepList() {userdepList({ ancestors: this.deptId }).then((res) => {console.log("res.data", res);this.vorganTreeData = res.data;});},selectClear() {this.orgId = undefined;},onChange(value, item, xx) {console.log(11111, value, item, xx);// this.$emit("update:value", value);this.$emit("getdep", value);},},
};
</script><style scoped lang="less">
</style>

父组件 

      <orginTree v-model="form.deptId" @getdep="getdep"></orginTree>

17.时间的回显

this.$set(this.form, "date", [dayjs(data.startTime).format("YYYY-MM-DD"),dayjs(data.endTime).format("YYYY-MM-DD"),]);

18.富文本去除标签 富文本组件事Editor

    <Editor v-model="form.requirement" :height="100"></Editor>// 提交数据时去除<p>标签const processedRequirement = that.form.requirement?.replace(/<\/?p>/g,"");

19.props接收兼容性写法

 props: {value: {// 如果希望value可以接收int类型的值而不报错,可以将type类型修改为可以兼容字符串和整数的类型type: [String, Number],default: "",},disabled: {type: Boolean,default: false,},replaceFields: {type: Object,default: () => {return {children: "children",title: "label",key: "id",value: "id",};},},},

20.文本的总体代码

<template><div class="upload-file"><el-uploadv-if="isUpload"multiple:action="uploadFileUrl":before-upload="handleBeforeUpload":file-list="fileList":limit="limit":on-error="handleUploadError":on-exceed="handleExceed":on-success="handleUploadSuccess":show-file-list="false":headers="headers"class="upload-file-uploader"ref="fileUpload"><!-- 上传按钮 --><el-button size="mini" type="primary">选取文件</el-button><!-- 上传提示 --><div class="el-upload__tip" slot="tip" v-if="showTip">请上传<template v-if="fileSize">大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-if="fileType">格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b></template>的文件</div></el-upload><!-- 文件列表 --><transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul" v-if="isFileList"><li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" style="padding: 0 4px" v-for="(file, index) in fileList"><el-link :href="`${file.url}`" :underline="false" target="_blank"><span class="el-icon-document"> {{ getFileName(file.name) }} </span></el-link><div class="ele-upload-list__item-content-action" v-if="isUpload"><el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link></div></li></transition-group></div>
</template><script>
import { getToken } from "@/utils/auth";
import { listByIds, delOss } from "@/api/system/oss";export default {name: "FileUpload",props: {// 值value: [String, Object, Array],// 数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array | Boolean,default: () => ["doc", "xls", "ppt", "txt", "pdf"],},// 是否显示提示isShowTip: {type: Boolean,default: true,},// 是否显示文件列表isFileList: {type: Boolean,default: true,},dataIndex: {type: Number | String,default: 0,},// 是否可以上传isUpload: {type: Boolean,default: true,},},data() {return {number: 0,uploadList: [],baseUrl: process.env.VUE_APP_BASE_API,uploadFileUrl: process.env.VUE_APP_BASE_API + "/system/oss/upload", // 上传文件服务器地址headers: {Authorization: "Bearer " + getToken(),},fileList: [],};},watch: {value: {async handler(val) {if (val) {let temp = 1;// 首先将值转为数组let list;if (Array.isArray(val)) {list = val;} else {console.log(val);await listByIds(val).then((res) => {list = res.data.map((oss) => {oss = {name: oss.originalName,url: oss.url,ossId: oss.ossId,};return oss;});this.$emit("getfile", list, this.dataIndex);});}// 然后将数组转为对象数组this.fileList = list.map((item) => {item = { name: item.name, url: item.url, ossId: item.ossId };item.uid = item.uid || new Date().getTime() + temp++;return item;});} else {this.fileList = [];return [];}},deep: true,immediate: true,},},computed: {// 是否显示提示showTip() {return this.isShowTip && (this.fileType || this.fileSize);},},methods: {// 上传前校检格式和大小handleBeforeUpload(file) {// 校检文件类型if (this.fileType) {const fileName = file.name.split(".");const fileExt = fileName[fileName.length - 1];const isTypeOk = this.fileType.indexOf(fileExt) >= 0;if (!isTypeOk) {this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);return false;}}// 校检文件大小if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSize;if (!isLt) {this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);return false;}}this.$modal.loading("正在上传文件,请稍候...");this.number++;return true;},// 文件个数超出handleExceed() {this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);},// 上传失败handleUploadError(err) {this.$modal.msgError("上传文件失败,请重试");this.$modal.closeLoading();},// 上传成功回调handleUploadSuccess(res, file) {if (res.code === 200) {this.uploadList.push({name: res.data.fileName,url: res.data.url,ossId: res.data.ossId,});this.uploadedSuccessfully();} else {this.number--;this.$modal.closeLoading();this.$modal.msgError(res.msg);this.$refs.fileUpload.handleRemove(file);this.uploadedSuccessfully();}},// 删除文件handleDelete(index) {let ossId = this.fileList[index].ossId;// delOss(ossId);this.fileList.splice(index, 1);this.$emit("input", this.listToString(this.fileList));},// 上传结束处理uploadedSuccessfully() {if (this.number > 0 && this.uploadList.length === this.number) {this.fileList = this.fileList.concat(this.uploadList);this.uploadList = [];this.number = 0;this.$emit("input", this.listToString(this.fileList));this.$modal.closeLoading();}},// 获取文件名称getFileName(name) {// 如果是url那么取最后的名字 如果不是直接返回if (name.lastIndexOf("/") > -1) {return name.slice(name.lastIndexOf("/") + 1);} else {return name;}},// 对象转成指定字符串分隔listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {strs += list[i].ossId + separator;}return strs != "" ? strs.substr(0, strs.length - 1) : "";},},
};
</script><style scoped lang="scss">
.upload-file-uploader {margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {border: 1px solid #e4e7ed;line-height: 2;margin-bottom: 10px;position: relative;
}
.upload-file-list .ele-upload-list__item-content {display: flex;justify-content: space-between;align-items: center;color: inherit;
}
.ele-upload-list__item-content-action .el-link {margin-right: 10px;
}
</style>

父组件

 <el-table-column label="操作"  prop="action" width="100"><template slot-scope="scope"><!-- <el-upload class="upload-demo" action="https://jsonplaceholder.typicode.com/posts/" :on-change="handleChange" :show-file-list="false"><el-button size="small" type="primary">点击上传</el-button></el-upload> --><FileUploadv-model="tableData[scope.$index].materialIds":dataIndex="scope.$index":isShowTip="false":fileType="false":isFileList="false":isUpload="scope.row.status == 3 || scope.row.status == 0 || scope.row.status == null"@getfile="getfile"></FileUpload></template></el-table-column>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ Algorithm 常用算法

C <algorithm> 头文件是标准库中提供的一系列算法&#xff0c;用于操作范围&#xff08;range&#xff09;内的元素。这些算法可以用于数组、容器如vector和list&#xff0c;以及其他满足相应迭代器要求的数据结构。以下是一些常用的C <algorithm> 中的算法及其使用…

为何网易游戏会选择引入OceanBase数据库

本文作者&#xff1a;田维繁&#xff0c;网易游戏关系型数据库小组负责人 作为中国游戏开发领域的佼佼者&#xff0c;网易游戏始终站在网络游戏自主研发的前沿。其产品及周边产品线丰富多样&#xff0c;因此&#xff0c;为满足各种业务场景的需求&#xff0c;需要多种不同的数据…

算法| ss 双指针

11.盛水最多的容器15.三数之和26.删除有序数组中的重复项27.移除元素75.颜色分类88.合并两个有序数组167.两数之和2-输入有序数组581.最短无序连续子数组2486.追加字符以获得子序列 11.盛水最多的容器 /*** param {number[]} height* return {number}*/ // 思路 // 左0 右 n-…

【环境变量】常见的环境变量 | 相关指令 | 环境变量系统程序的结合理解

目录 常见的环境变量 HOME PWD SHELL HISTSIZE 环境变量相关的指令 echo&env export unset 本地变量 环境变量整体理解 程序现象_代码查看环境变量 整体理解 环境变量表 环境变量表的传递 环境变量表的查看 测试验证 少说废话&#x1f197; 每个用户…

48V转15V,48V转12V,48V转24V高效率降压恒压芯片SL3041电路简单

在现代电子设备中&#xff0c;电源转换是一个关键且常见的技术。特别是对于那些需要将48V电压转换为更低电压&#xff08;如15V、12V或24V&#xff09;的设备&#xff0c;一个高效、可靠的降压恒压芯片至关重要。本文将详细介绍一款名为SL3041的高效率降压恒压芯片&#xff0c;…

C++ P1152 欢乐的跳

文章目录 一、题目描述欢乐的跳题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示 二、参考代码 一、题目描述 欢乐的跳 题目描述 一个 n n n 个元素的整数数组&#xff0c;如果数组两个连续元素之间差的绝对值包括了 [ 1 , n −…

#{} 和 ${}区别

1、参数是Integer类型时候没区别&#xff08;#是预编译SQL&#xff0c;$是即时SQL&#xff09; 2、当参数是String类型时&#xff0c;就会出错了 &#xff08;1&#xff09;这是$的报错信息&#xff0c;因为我们的参数admin并没有加引号所以不满足字符串条件 (2)正确的SQL &am…

蓝牙学习十(扫描)

一、简介 从之前的文章中我们知道&#xff0c;蓝牙GAP层定义了四种角色&#xff0c;广播者&#xff08;Broadcaster&#xff09;、观察者&#xff08;Observer&#xff09;、外围设备&#xff08;Peripheral&#xff09;、中央设备&#xff08;Central&#xff09;。 之前的学习…

基础总结篇:Activity生命周期

private int param 1; //Activity创建时被调用 Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, “onCreate called.”); setContentView(R.layout.lifecycle); Button btn (Button) findViewById(R.id.…

在JS中通过样式构建三角形的方法

第一种方法&#xff1a; .triangle {width: 0;height: 0;border-left: 50px solid transparent;border-right: 50px solid transparent;border-bottom: 100px solid blue; /* 三角形的颜色 */ }.triangle 类定义了一个零宽高的块级元素&#xff0c;并通过设置边框的样式来创建…

Python实现 AI 绘图(非常详细)零基础入门到精通,收藏这一篇就够了

今天给大家带来了 Python 对接阿里大模型&#xff0c;通过 AI 实现文本生成图片。 相关资料 这个功能使用的主要 API 是阿里的大模型服务。 开通服务 阿里文档 https://help.aliyun.com/zh/dashscope/developer-reference/quick-start-1?disableWebsiteRedirecttrue 获取 a…

K8S之Job和CronJob控制器

这里写目录标题 Job概念适用场景使用案例 CronJob概念适用场景使用案例 Job 概念 Job控制器用于管理Pod对象运行一次性任务&#xff0c;例如&#xff1a;对数据库备份&#xff0c;可以直接在k8s上启动一个mysqldump备份程序&#xff0c;也可以启动一个pod&#xff0c;这个pod…

Day3-HBase重要概念

HBase 结构 HRegion 概述 在HBase中&#xff0c;会从行键方向上对表来进行切分&#xff0c;切分出来的每一个结构称之为是一个HRegion 切分之后&#xff0c;每一个HRegion会交给某一个HRegionServer来进行管理。HRegionServer是HBase的从节点&#xff0c;每一个HRegionServ…

C++ 内存分配时地址对齐

如果数据地址的对齐与CPU相兼容&#xff0c;那么CPU读写内存时性能会更高。 因此在C中&#xff0c;有时会希望在堆或栈中分配内存时&#xff0c;返回的地址能按照特定的长度对齐。 如果希望在栈中分配的内存时&#xff0c;返回地址按照特定长度对齐&#xff0c;可以使用 alig…

光伏接口转接器配合光伏规约转换器实现发电用电信息采集支持接入各个型号逆变器

1.产品概述 DAQ-GP-485PIA光伏接口转接器&#xff08;以下简称转接器&#xff09;是我公司针对光伏发电领域国家电网公司最新需求设计的&#xff0c;光伏接口转接器是配合光伏规约转换器&#xff0c;实现逆变器发电、用电信息采集的设备。支持锦浪、古瑞瓦特、固德威、华为、奥…

阿里云数据库RDS MySQL实例删除ONLY_FULL_GROUP_BY参数值

概述 阿里云云数据库RDS MySQL实例中&#xff0c;如何删除sql_mode参数的ONLY_FULL_GROUP_BY值。 详细信息 阿里云提醒您&#xff1a;如果您对实例或数据有修改、变更等风险操作&#xff0c;务必注意实例的容灾、容错能力&#xff0c;确保数据安全。如果您对实例&#xff08;…

大模型现有领域研究

分类参考https://csdnnews.blog.csdn.net/article/details/137337597?spm1000.2115.3001.5926&ydrefereraHR0cHM6Ly93d3cuY3Nkbi5uZXQv 对现有领域热点进行总结&#xff0c;后续会基于这些进行补充&#xff0c;会对其中的名词进行解释。 开始编辑日期2024/4//4&#xff…

提升团队工程交付能力,从“看见”工程活动和研发模式开始

作者&#xff1a;张裕、雅纯 理想中的研发团队应当具有以下特征&#xff1a; 总是工作在最高优先级的事项上 理想的研发团队能够识别并始终集中精力在当前最紧迫和最有价值的任务上。这需要团队具备出色的项目管理能力和决策能力&#xff0c;以便能够正确评估优先级&#xff0…

Vue 项目如何在VSCode中进行断点调试

概要&#xff1a; 简单介绍一下&#xff0c;在VSCode中如何对Vue项目进行断点调试。具体内容包括但不限于&#xff1a;如何配置调试环境、如何在代码中设置断点、如何启动调试以及如何解决在调试过程中可能遇到的问题。 实际开发中&#xff0c;我们的前端项目一般都是在浏览器…

算法 day28 回溯4

93 复原IP地址 给定一个只包含数字的字符串 s &#xff0c;用以表示一个 IP 地址&#xff0c;返回所有可能的有效 IP 地址&#xff0c;这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。 有效 IP 地址 正好由…