微语:代码适合中午敲,早晚出BUG
vue-ueditor-wrap设置内容高度自动图片缩放问题 Vue
vue-ueditor-wrap设置内容高度自动图片缩放问题
可能会因为层级问题导致缩放没有效果需要设置'zIndex'层级配置
editorConfig: {
toolbars: [
[
...
],
],
zIndex: 9000,
},
vue3中使用MAthJax入门教程2.x Vue
MAthJax用于在页面中显示一些数学公式
官网下载代码地址为:https://www.mathjax.org/
1.在index.html中引入
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
2.页面更新的时候需要重新渲染
` nextTick(() => {
if (window.MathJax && window.MathJax?.Hub) {
// 添加到 MathJax 渲染队列
window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub])
}
Avue+vue2实现大型文件切片上传 Vue
1.Avue配置项avue-crud中需要添加文件上传前函数
<avue-crud
:upload-before="uploadBefore"
>
</avue-crud>
2.工具函数代码
// 引入axios进行http请求
import axios from "axios";
// 异步函数Fileslicing,用于处理文件的分片上传
async function Fileslicing(vueInstance, file, done, loading, column) {
let _this = vueInstance; // 将vue实例保存在_this中,用于后续引用
const CHUNK_SIZE = 1 * 1024 * 1024; // 定义每个分片的大小为1MB
// const CHUNK_SIZE = 512 * 1024; // 或定义分片大小为500KB
const totalChunks = Math.ceil(file.size / CHUNK_SIZE); // 计算总的分片数量
let uploadedChunks = 0; // 已上传分片的计数器
const overallStartTime = performance.now(); // 记录开始上传的时间
// 循环处理每个分片
for (let index = 0; index < totalChunks; index++) {
const start = index * CHUNK_SIZE; // 计算当前分片的起始位置
const end = Math.min(start + CHUNK_SIZE, file.size); // 计算结束位置,确保不超出文件大小
const blob = file.slice(start, end); // 从文件中切割出当前分片
// 创建一个新的文件对象用于上传,包含当前分片内容
const chunkFile = new File([blob], `${file.name}-${index}`, {
type: file.type,
});
const formData = new FormData(); // 使用FormData上传分片
formData.append("file", chunkFile); // 添加当前分片
formData.append("chunkNumber", index); // 当前分片的序号
formData.append("totalChunks", totalChunks); // 总分片数
formData.append("fileName", file.name); // 原文件名
try {
// 发起分片上传请求
const response = await axios.post(
"/api/blade-resource/oss/endpoint/chunk",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
uploadedChunks++; // 上传成功后,已上传分片数+1
// 计算并显示上传进度
const progressPercentage = ((uploadedChunks / totalChunks) * 100).toFixed(2);
// 显示上传进度的通知
vueInstance.$notify.info({
title: "进度",
message: `当前上传进度: ${progressPercentage}%`,
});
if(progressPercentage == 100){
// 如果上传进度达到100%,显示文件上传完成的通知
vueInstance.$notify({
type: 'success',
title: "通知",
message: `文件已上传完成!正在处理中请稍等......`,
});
}
// 如果当前分片是最后一个分片
if (index === totalChunks - 1) {
// 发起合并文件的请求
const fileData = {
fileName: file.name,
totalChunks: totalChunks,
};
const Stresponse = await axios.post(
"/api/blade-resource/oss/endpoint/mergeFile",
fileData,
{
headers: {
"Content-Type": "application/json",
},
}
);
if (Stresponse.data.code === 200) {
// 如果文件合并成功
const overallEndTime = performance.now(); // 记录操作结束时间
// 计算总耗时
const totalFunctionTime = (overallEndTime - overallStartTime) / 1000;
column.tip = ``; // 可根据需要进行操作
let url = (Stresponse.data.data.domain + '/' + Stresponse.data.data.name);
_this.form.videoUrl = url; // 更新vue实例中的视频URL
loading(); // 可能是结束加载状态的函数
// 显示上传成功的消息
vueInstance.$message.success(
`上传成功:文件名:${file.name},文件大小${(file.size / (1024 * 1024)).toFixed(2)} MB, 上传进度: ${progressPercentage}%,总耗时:${totalFunctionTime.toFixed(2)}秒`
);
} else {
// 如果文件合并失败
loading();
vueInstance.$message.error("文件合并失败");
}
}
} catch (error) {
// 如果上传过程中出现错误
vueInstance.$message.error("上传出错");
loading(); // 结束加载状态
return; // 停止执行
}
}
}
// 导出Fileslicing函数,使其在Vue实例中可用
export default {
install(Vue) {
Vue.prototype.$fileslicing = Fileslicing;
},
};
3.注册全局,在main.js中引入
import FileslicingPlugin from '../src/util/Fileslicing';
Vue.use(FileslicingPlugin);
4.页面使用
Avue文件上传前函数
uploadBefore(file, done, loading, column) {
this.$fileslicing(this,file,done,loading,column);//文件切换全局函数(初始)
},
Vue配置API代理 Vue
vite.config.js配置如下
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [
vue(), // 添加 Vue 插件配置
],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
},
},
server: {
port: 2888,
proxy: {
'/api': {
target: 'http://192.168.3.14:13000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
})
axios封装
import axios from 'axios';
// 创建axios实例
const instance = axios.create({
timeout: 10000, // 设置超时时间为10秒
headers: {
'Content-Type': 'application/json', // 设置Content-Type
},
// 删除baseURL配置
});
// 添加请求拦截器
instance.interceptors.request.use(
config => {
// 在请求发送之前做些什么
// 如果需要在请求发送前进行额外的处理,可以在这里添加
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
response => {
// 对响应数据做处理
return response.data;
},
error => {
// 对响应错误做处理
return Promise.reject(error);
}
);
export default instance;
API引用
import request from '@/axios';
export const $_deliveryInfo = (params) => {
return request({
url: '/api/logpm-distribution/a/abc', // 注意这里的 URL带上API 更改
method: 'get',
params
})
}
启动项目如果只有本地地址需要再package.json中配置
"scripts": {
"dev": "vite --host",
},
Vue3中判断对象中是否存在指定参数 Vue
export function checkParams(data, targetParam) {
const keys = Object.keys(data);
if (keys.includes(targetParam) && keys.every(key => key === targetParam || data[key] === "")) {
return true; // 指定参数存在且没有其他参数或其他参数值为空时返回 true
} else {
return false; // 其他情况返回 false
}
};
参数说明:
data:传入一个对象
targetParam:传入要校验的参数
使用示例:
let data1 = {
operatorTime: '123123'
};
let targetParam1 = 'operatorTime';
console.log(checkParams(data1, targetParam1)); // 输出 true
let data2 = {
serviceNumber: '',
operatorTime: ''
};
let targetParam2 = 'operatorTime';
console.log(checkParams(data2, targetParam2)); // 输出 false
let data3 = {
serviceNumber: '',
operatorTime: '456456'
};
let targetParam3 = 'operatorTime';
console.log(checkParams(data3, targetParam3)); // 输出 true
饿了么表格组件 Vue
<template>
<!-- 表格组件 -->
<div class="el-content-el" ref="TabHeight">
<!-- 搜索功能 -->
<div class="SoInput" v-show="searchSo" ref="SoHeight">
<el-form label-position="top" label-width="100px" :model="SoInfoData">
<el-form-item label="盘点任务编码:">
<el-input v-model="SoInfoData.a" placeholder="请输入盘点任务编码" />
</el-form-item>
</el-form>
<div class="SoBtn">
<el-button type="primary" @click="SoInput"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button class="SoEmpty" type="primary" @click="SoEmpty">
<el-icon><Delete /></el-icon> 清空
</el-button>
</div>
</div>
<!-- 顶部开始 -->
<div class="el-Cart-button">
<!-- 表格顶部左侧按钮 -->
<div class="el-Cart-button-left">
<el-button type="primary" @click="AddInfo"
><el-icon><Plus /></el-icon>新 增</el-button
>
<el-button @click="handleDelete"
><el-icon><Delete /></el-icon>删 除</el-button
>
<el-button @click="handleDelete"
><el-icon><Edit /></el-icon>查看维修记录</el-button
>
<!-- <el-button link type="primary" icon="el-icon-view" @click="toggleSelection()"
>多选测试</el-button
> -->
</div>
<!-- 表格顶部右侧按钮 -->
<div class="el-Cart-button-right">
<!-- 刷新按钮 -->
<button @click="refresh">
<el-icon color="#ccc"><Refresh /></el-icon>
</button>
<!-- 功能按钮 -->
<button @click="menu = true">
<el-icon color="#ccc"><Operation /></el-icon>
</button>
<!-- 搜索按钮 -->
<button @click="search">
<el-icon color="#ccc"><Search /></el-icon>
</button>
</div>
</div>
<!-- 顶部结束 -->
<div class="el-Cart">
<!-- 表格列开始 -->
<el-table
v-loading="loading"
element-loading-text="数据正在更新中..."
:data="data"
row-key="name"
border
:height="TabHeight + 'px'"
style="width: 100%"
ref="tableRef"
@select-all="selectAll"
@select="selectChange"
>
<el-table-column type="selection" width="55" fixed />
<el-table-column type="index" fixed width="50" height="100" label="#" align="center" />
<template v-for="(item, index) in menuData" :key="item.label">
<!--
Type ===1 普通文本
Type ===2 图片显示
Type ===3 操作功能
label: 标题
width: 宽度
prop: 数据字段
-->
<template v-if="item.type === 1">
<el-table-column
v-if="item.head"
:prop="item.prop"
:label="item.label"
:width="item.width"
:fixed="item.fixed"
align="center"
>
<template #default="props">
<span>{{ props.row[item.prop] ? props.row[item.prop] : '/' }}</span>
</template>
</el-table-column>
</template>
<template v-if="item.type === 2">
<el-table-column
v-if="item.head"
:label="item.label"
:width="item.width"
:fixed="item.fixed"
align="center"
>
<template #default="props">
<img :src="props.row[item.prop]" class="el-Img" />
</template>
</el-table-column>
</template>
<template v-if="item.type === 3">
<el-table-column
v-if="item.head"
fixed="right"
label="操作"
width="280"
align="center "
>
<template #default="scope">
<div :class="ElBtnClass">
<el-button
:link="ElButtonS[0].link"
:class="ElButtonS[0].class"
:auto-insert-space="ElButtonS[0].space"
:size="ElButtonS[0].size"
:icon="ElButtonS[0].icon"
@click="DeleteEvent(scope.row)"
>删除</el-button
>
<el-button
:link="ElButtonS[1].link"
:class="ElButtonS[1].class"
:auto-insert-space="ElButtonS[1].space"
:size="ElButtonS[1].size"
:icon="ElButtonS[1].icon"
@click="EditEvent(scope.row)"
>编辑</el-button
>
<el-button
:link="ElButtonS[2].link"
:class="ElButtonS[2].class"
:auto-insert-space="ElButtonS[2].space"
:size="ElButtonS[2].size"
:icon="ElButtonS[2].icon"
@click="ViewEvent(scope.row)"
>查看</el-button
>
</div>
</template>
</el-table-column>
</template>
</template>
</el-table>
<!-- 表格翻页功能 -->
<div class="demo-pagination-block">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="pageList"
:disabled="disabled"
:background="background"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="PageSizeChange"
@current-change="SizeChange"
/>
</div>
</div>
<!-- 弹窗组件 -->
<div class="addlalog">
<el-dialog v-model="AddLalog" title="新增产品">
<el-form label-position="top" label-width="100px" :model="AddForm">
<el-form-item label="产品名称">
<el-input v-model="AddForm.name" placeholder="请输入产品名称" />
</el-form-item>
<el-form-item label="购买金额">
<el-input v-model="AddForm.purchaseAmount" placeholder="请输入购买金额" />
</el-form-item>
<el-form-item label="当前使用仓">
<el-input v-model="AddForm.currentUsageWarehouse" placeholder="请输入当前使用仓" />
</el-form-item>
<el-form-item label="设备序列号S/N">
<el-input v-model="AddForm.deviceSerialNumber" placeholder="请输入设备序列号" />
</el-form-item>
<el-form-item label="是否收取押金">
<el-select v-model="AddForm.isDeposit" class="m-2" placeholder="选择是否收取押金">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="采购公司">
<el-input v-model="AddForm.purchasingCompany" placeholder="请输入采购公司" />
</el-form-item>
<el-form-item label="保修截至时间">
<el-date-picker
v-model="AddForm.warrantyPeriodEndTime"
type="date"
placeholder="选择保修截至日期"
size="default"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="图片">
<!-- photo -->
<el-upload
ref="uploadRef"
class="upload-demo"
:action="doubledCount"
:on-success="ImgSuccess"
:before-upload="beforeAvatarUpload"
:headers="headers"
v-if="!img"
>
<template #trigger>
<div class="img-icon">
<el-button type="primary">点击上传图片</el-button>
<el-icon><UploadFilled /></el-icon>
</div>
</template>
</el-upload>
<div class="el-load-img" v-else>
<div class="el-img">
<div class="el-img-left">
<el-icon><Link /></el-icon>
<span>{{ ImgText }}</span>
</div>
</div>
<div class="el-z">
<el-image
:src="url"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="UrlImg"
:initial-index="4"
:z-index="10"
fit="cover"
/>
</div>
<el-icon><SuccessFilled /></el-icon>
</div>
</el-form-item>
<el-form-item label="型号">
<el-input v-model="AddForm.model" placeholder="请输入型号" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="AddForm.state" class="m-2" placeholder="选择状态">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="使用人">
<el-input v-model="AddForm.user" placeholder="请输入使用人" />
</el-form-item>
<el-form-item label="使用人岗位">
<el-input v-model="AddForm.userPosition" placeholder="请输入使用人岗位" />
</el-form-item>
<el-form-item label="押金金额(RMB)">
<el-input v-model="AddForm.deposit" placeholder="请输入押金金额(元)" />
</el-form-item>
<el-form-item label="购买时间">
<el-date-picker
v-model="AddForm.buyingTime"
type="date"
placeholder="选择购买日期"
size="default"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="AddForm.notes" placeholder="请输入备注" />
</el-form-item>
</el-form>
<!-- 弹窗底部提交按钮 -->
<div class="el-dialog-button">
<el-button type="danger" @click="submit">
<el-icon><Select /></el-icon>
确认提交
</el-button>
</div>
</el-dialog>
</div>
<!-- 弹窗结束 -->
<!-- 右侧功能列表弹窗 -->
<div class="el-menu-load">
<el-drawer v-model="menu" direction="rtl">
<template #header>
<h4>菜单功能列表</h4>
</template>
<!-- 默认插入到侧边栏内容 -->
<!-- 表格功能列表 -->
<template #default>
<div v-if="!Btn">
<el-tabs type="border-card">
<el-tab-pane label="表格功能">
<el-table :data="menuData" border :height="menuHeight + 'px'">
<el-table-column
v-for="column in MenuTop"
:key="column.prop"
:prop="column.prop"
:label="column.label"
:width="column.width"
>
<!--
/
MenuTop: 0:菜单选项
true-label: 1.选中时候的值
false-label: 2.没有选中时候的值
@change: 3.当绑定时候的值发生变化的时候触发
label: 4.选中状态的值
/
-->
<!-- 标题 -->
<template #default="scope">
<template v-if="column.prop == 'label'">
<el-text class="mx-1">{{ scope.row[column.prop] }}</el-text>
</template>
<!-- 隐藏复选框 -->
<template v-else-if="column.label == '隐藏'">
<el-checkbox-group v-model="checkList">
<el-checkbox
:key="scope.row['label']"
:label="scope.row['label']"
@change="CheckBox(scope.row, 1)"
>
<!-- 用于隐藏文字 -->
<template #default="scope">
<!-- {{ scope }} -->
</template>
</el-checkbox>
</el-checkbox-group>
</template>
<template v-else-if="column.label == '冻结'">
<el-checkbox-group v-model="flexList">
<el-checkbox
:key="scope.row['label']"
:label="scope.row['label']"
@change="CheckBox(scope.row, 2)"
>
<!-- 用于隐藏文字 -->
<template #default="scope">
<!-- {{ scope }} -->
</template>
</el-checkbox>
</el-checkbox-group>
</template>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="按钮功能">
<!-- <div class="el-title-btn">
<span> 表格操作按钮风格选择 </span>
</div> -->
<el-radio-group v-model="BtnRadio" @change="btnClass">
<el-radio label="1" size="default" border>链接样式风格</el-radio>
<el-radio label="2" size="default" border>按钮样式风格</el-radio>
</el-radio-group>
</el-tab-pane>
<el-tab-pane label="表格导出">Role</el-tab-pane>
<el-tab-pane label="待添加">Task</el-tab-pane>
</el-tabs>
</div>
<!-- 按钮功能结束-->
</template>
</el-drawer>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { getList, getDetail, $_AddInfo, update, remove, $_TableList } from '@/api/basic/basicPda'; //API
import { ElMessage, type UploadProps } from 'element-plus';
import { getToken } from '@/utils/auth';
// 菜单功能标题
const MenuTop = ref([
{
prop: 'label',
label: '列名',
width: '',
},
{
prop: '',
label: '隐藏',
},
{
prop: '',
label: '冻结',
},
{
prop: '',
label: '排序',
},
]);
// 按钮配置
const ElButtonS = ref([
// 1.link 切换按钮样式(文本模式-false ,按钮模式-tre)
// 2.class 按钮样式名(用于切换按钮样式)
// 3.space 是否开启按钮文子直接间距(true开启 ,false关闭)
// 4.size 按钮尺寸默认小尺寸('large'| 'default'| 'small')
// 5.icon 按钮图标
// 6.table 按钮名称
{
link: false,
class: 'el-btn-danger',
space: true,
size: 'small',
icon: 'el-icon-delete',
table: '删除',
},
{
link: false,
class: 'el-btn-success',
space: true,
size: 'small',
icon: 'Edit',
table: '编辑',
},
{
link: false,
class: 'el-btn-view',
space: true,
size: 'small',
icon: 'el-icon-view',
table: '查看',
},
]);
const currentPage = ref(1); // 默认页码
const pageSize = ref(30); // 默认每一页几条
const total = ref(0); //页码总页数
const pageList = ref([5, 10, 50, 100, 200]); // 选择每页显示多少条
const background = ref(true); // 是否开启背景颜色
const disabled = ref(false); // 是否禁止使用页码功能
const data = ref([]); // 表格数据
const TabHeight = ref(); //动态获取表格高度
const AddLalog = ref(false); //提交弹窗
const img = ref(false); //图片是否上传成功
const ImgText = ref(''); //图片上传成功文件名
const AddForm = ref({}); //表单所有信息
const uploadRef = ref(); //图片上传
const tableRef = ref(null); // 用于引用 table 实例
const menu = ref(true); //功能菜单列表
const menuHeight = ref(); //右侧菜单栏高度,用于固定表头
const checkList = ref<(string | number)[]>([]); //隐藏
const flexList = ref<(string | number)[]>([]); //冻结
const loading = ref(false); //刷新功能
const SoHeight = ref(); //搜索栏高度动态
const BtnRadio = ref('1'); //按钮样式风格切换
const ElBtnClass = ref('el-Btn-link'); //按钮样式风格类名
const searchSo = ref(false); //控制搜索框是否显示隐藏
const SoInfoData = ref({ a: 123 }); //搜索框表单数据
//下拉选择框
const options = [
{
value: '0',
label: '是',
},
{
value: '1',
label: '否',
},
];
//下拉选择框
const options2 = [
{
value: '1',
label: '正常',
},
{
value: '2',
label: '维修',
},
{
value: '3',
label: '不能使用(不能开机)',
},
];
// 菜单功能头部
// 菜单功能列表
const menuData = ref([
{
prop: 'name',
label: '产品名称',
type: 1,
values: '',
width: '150',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'currentUsageWarehouse',
label: '当前使用仓',
type: 1,
values: '',
width: '150',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'model',
label: '型号',
type: 1,
values: '',
width: '150',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'purchaseAmount',
label: '购买金额',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'state',
label: '状态',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'user',
label: '使用人',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'deviceSerialNumber',
label: '设备序列号S/N',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'userPosition',
label: '使用人岗位',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'isDeposit',
label: '是否收取押金',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'deposit',
label: '押金金额(元)',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'purchasingCompany',
label: '采购公司',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'photo',
label: '商品图片',
type: 2,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'buyingTime',
label: '购买时间',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'notes',
label: '备注',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: 'warrantyPeriodEndTime',
label: '保修截止时间',
type: 1,
values: '',
width: '180',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
{
prop: '',
label: '操作',
type: 3,
values: '',
width: '280',
checkarr: [],
fixed: false,
sortable: true,
head: true,
},
]);
// 图片上传背景图,固定白色背景
const url =
'https://img1.baidu.com/it/u=1996827238,2183445322&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889';
// 图片预览显示
const UrlImg = ref([]);
// 图片上传接口
const doubledCount = computed(() => {
return '/api/blade-resource/oss/endpoint/put-file';
});
// 图片上传必须携带TOKEN
const headers = computed(() => {
return { 'Blade-Auth': 'Bearer ' + getToken() };
});
// 获取表格数据
function onLoad() {
// 获取表格数据API($_TableList)
$_TableList({ current: currentPage.value, size: pageSize.value }).then(res => {
//表格信息
data.value = res.data.data.records; //获取到的数据存到暂存区 DOM更新之后在放入正式变量(先计算出表格高度)
const setIn = setTimeout(() => {
toggleSelection(); //表格自动选中函数
clearTimeout(setIn); //清除定时器
}, 0);
});
}
onLoad();
// 动态计算表格高度
const TabHeig = () => {
TabHeight.value = TabHeight.value.offsetHeight - 92; //表格高度
menuHeight.value = window.innerHeight - 136; //侧边栏表格宽度
};
// 动态获取DOM高度给表单防止页面出现滚动条
onMounted(async () => {
//默认值88
TabHeig(); //调用表格计算高度
// 等待DOM高度被复制之后在请求数据,防止被数据撑开高度
});
// 新增数据功能
const AddInfo = () => {
AddLalog.value = true; //展开表单弹窗
};
// 表格自动选中
const toggleSelection = () => {
if (data.value) {
data.value.forEach((row, i) => {
tableRef.value!.toggleRowSelection(data.value[i], true);
});
}
//对表单进行循环把所有表格进行全部选中,或者通过IF对条件满足进行选中
};
// 图片上传
const imageUrl = ref('');
// 图片上传成功回调函数
const ImgSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
if (response.success === true) {
img.value = true;
// 图片放入预览
UrlImg.value.push(response.data.link);
// 图片存入表单准备提交
AddForm.value.photo = response.data.link;
// 显示图片名字
ImgText.value = response.data.originalName;
}
};
// 上传图片规则
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
if (rawFile.type !== 'image/png') {
ElMessage.error('图片格式只能为image/png!');
return false;
} else if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error('图片大小不能大于2MB!');
return false;
}
return true;
};
// 字典转换(英文转中文)
let dictionary = (columnNames, text) => {
// columnNames:传入的数组,要修改的字段名
// text:传入要修改的对象
const mapping = text;
// 只获取指定参数对应的列数据,并将英文字段名替换为中文字段名
const filteredData = userList.value.map(item => {
const translatedItem = {};
for (let column of columnNames) {
const chineseColumn = mapping[column] || column;
translatedItem[chineseColumn] = item[column];
}
return translatedItem;
});
// 把修修改好表头数据赋值给要导出的工作表
expExcel.value = filteredData;
};
// 表单信息提交
const submit = () => {
console.log(AddForm.value);
$_AddInfo(AddForm.value).then(res => {
console.log(res);
});
};
// 每页多少条触发
const PageSizeChange = val => {
console.log('每一页', val, '条');
};
// 页码翻页触发
const SizeChange = val => {
console.log('当前是第', val, '页');
};
// 表格全选功能触发
const selectAll = val => {
console.log(val);
};
// 表格单个选中触发事件
const selectChange = (selection, row) => {
// 1.selection 选中的数组
// 2.row 选中的当前行
console.log(selection);
};
// 删除触发事件
const DeleteEvent = val => {
// 接收点击删除当前行数据
console.log('触发了删除事件', val);
};
// 编辑触发事件
const EditEvent = val => {
// 接收点击编辑当前行数据
console.log('触发了编辑事件', val);
};
// 查看事件
const ViewEvent = val => {
//接收点击查看当前行数据;
console.log('触发了查看事件', val);
};
// 菜单功能选择触发
const CheckBox = (scope, type: number) => {
console.log(scope, 'scope');
if (type === 1) {
scope.head = !scope.head;
}
if (type === 2) {
scope.fixed = !scope.fixed;
}
};
// 刷新触发事件
const refresh = () => {
loading.value = !loading.value;
};
// 搜索展开功能
const search = () => {
searchSo.value = !searchSo.value;
if (searchSo.value) {
// 展开
setTimeout(() => {
console.log(SoHeight.value.offsetHeight);
console.log(TabHeight.value.offsetHeight);
TabHeight.value = TabHeight.value.offsetHeight - SoHeight.value.offsetHeight - 91; //表格高度
}, 0);
} else {
// 关闭
TabHeight.value = TabHeight.value.offsetHeight - 91; //表格高度
}
};
// 顶部搜索功能
const SoInput = () => {};
// 顶部清空搜索
const SoEmpty = () => {};
// 按钮样式风格切换
const btnClass = type => {
// 切换链接样式风格
if (type == 1) {
ElBtnClass.value = 'el-Btn-link';
}
// 切换按钮样式风格
if (type == 2) {
ElBtnClass.value = 'el-Btn-btn';
}
};
</script>
<style scoped lang="scss">
// 最外层 IDV
.el-content-el {
padding: 0 8px;
padding-top: 8px;
background-color: #fff;
height: 100%;
box-sizing: border-box;
overflow-y: hidden; //防止页面重新计算高度的时候出现滚动条闪烁
// 表格顶部按钮
:deep(.el-Cart-button) {
margin-bottom: 8px;
display: flex;
justify-content: space-between;
}
// 表格顶部左侧、右侧按钮样式
.el-Cart-button-left,
.el-Cart-button-right {
display: flex;
margin: 0 0px;
justify-content: space-between;
}
.el-Cart-button-left {
:deep(button) {
padding: 0 14px;
min-width: 70px;
display: flex;
span {
width: 100%;
display: inline-flex;
align-items: center;
justify-content: space-between;
i {
margin-right: 6px;
}
}
}
}
.el-Cart-button-right {
display: flex;
margin: 0 0px;
justify-content: space-between;
align-items: center;
button {
background-color: transparent;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ccc;
margin-right: 8px;
&:hover {
background-color: #172e601f;
i {
color: #0e2549;
}
}
// 去掉最后一个按钮右侧边距
&:last-child {
margin-right: 0;
}
}
}
.el-Cart {
// 表格标题颜色
:deep(.el-table__header) {
th {
background-color: #fafafa;
color: #000;
}
}
// 组件样式开始
// 分页样式
.demo-pagination-block {
display: flex;
justify-content: flex-end;
margin-top: 6px;
}
// 表格行高度
:deep(.el-table__row) {
height: 60px;
}
// 表格图片
.el-Img {
width: 100%;
height: 40px;
img {
width: 100%;
height: 100%;
}
}
}
// 新增数据弹窗组件样式
:deep(.addlalog) {
// 弹窗
.el-dialog__header {
border-bottom: 1px solid #172e607d;
margin-right: 0;
margin-bottom: 0;
padding-bottom: 20px;
position: relative;
i {
color: #172e60;
border-radius: 50%;
border: 1px solid;
transition: transform 1s;
}
}
.el-dialog__header button:hover {
i {
transform: rotate(360deg);
}
}
// 弹窗标题左侧小竖线
.el-dialog__header::after {
content: '';
display: block;
width: 3px;
height: 16px;
background-color: #172e60;
position: absolute;
left: 8px;
top: 24px;
}
.el-dialog__body {
.el-form {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.el-form-item {
width: 276px;
.el-form-item__label {
font-family: '黑体';
}
}
/* 去掉第三个、第六个、第九个div的右外边距 */
.el-form-item:nth-child(3n) {
margin-right: 0;
}
}
.el-form-item__content {
height: 30px;
// 日期选择框
.el-input {
width: 100%;
height: 30px !important;
}
// 下拉选择框
.el-select {
width: 100%;
}
}
}
// 底部提交
:deep(.el-dialog-button) {
display: flex;
justify-content: flex-end;
}
.el-dialog-button button:hover {
color: #fff;
background-color: #10d070;
transition: all 0.3s ease-in-out; /* 添加动画效果 */
background-color: #10d070;
border: 1px solid #10d070;
}
// 图片上传
.img-icon {
width: 100%;
position: relative;
.el-button {
width: 100%;
background-color: #fff;
color: #a8abb9;
justify-content: flex-start;
border: 1px solid #dcdfe6;
}
i {
position: absolute;
left: 110px;
top: 8px;
font-size: 18px;
}
}
:deep(.el-load-img) {
width: 100%;
height: 32px;
display: flex;
align-items: center;
justify-content: space-between;
.el-image {
width: 100%;
height: auto;
img {
width: 100%;
}
}
.el-image-viewer__canvas {
img {
width: 50%;
height: 50%;
z-index: 10;
}
}
.el-z {
.el-image {
position: absolute;
height: 28px;
top: 2px;
left: 1px;
}
}
.el-icon {
color: #10d070;
}
}
:deep(.upload-demo) {
width: 100%;
.el-upload {
width: 100%;
}
ul {
margin-top: 0;
}
}
// 图片上传成功
.el-img {
border: 1px solid #ccc;
width: 100%;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: space-between;
height: 30px;
position: absolute;
top: 0;
left: 0;
.el-img-left {
display: flex;
align-items: center;
span {
z-index: 9;
}
i {
margin-right: 8px;
color: #10d070;
z-index: 9;
}
}
i {
color: #10d070;
margin-left: 6px;
}
}
// 侧边弹窗功能样式
:deep(.el-menu-load) {
.el-drawer__header {
padding: 0;
padding-left: 20px;
position: relative;
border-bottom: 1px solid #172e5f;
margin-bottom: 0;
i {
color: #172e60;
}
}
.el-drawer__header::after {
content: '';
display: block;
width: 4px;
height: 18px;
background-color: #172e60;
position: absolute;
top: 23px;
left: 9px;
}
.el-table__inner-wrapper {
.cell {
text-align: center;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.el-table__row {
height: 40px;
}
}
// 上移,下移按钮
.el-text {
margin: 0 5px;
}
}
.el-table__row {
height: 40px;
// 链接样式风格(默认)
.el-Btn-link {
.el-btn-danger,
.el-btn-success,
.el-btn-view {
color: #172e60;
background-color: transparent;
border: 1px solid transparent;
}
}
// 按钮样式风格
.el-Btn-btn {
// 删除按钮颜色
.el-btn-danger {
background-color: #f56c6c;
border: 1px solid #f56c6c;
color: #fff;
padding: 5px 11px;
}
// 编辑按钮颜色
.el-btn-success {
background-color: #409eff;
border: 1px solid #409eff;
color: #fff;
padding: 5px 11px;
}
// 查看按钮颜色
.el-btn-view {
background-color: #172e60;
border: 1px solid #172e60;
color: #fff;
padding: 5px 11px;
}
}
}
:deep(.SoInput) {
width: 100%;
transition: all 0.5s;
display: flex;
justify-content: space-between;
.el-form {
display: flex;
flex-wrap: wrap;
.el-form-item {
width: auto;
display: flex;
align-items: center;
justify-items: center;
margin-bottom: 8px;
margin-right: 18px;
justify-content: space-between;
}
.el-form-item__label {
margin-bottom: 0;
}
.el-form-item__content {
width: 259px;
}
}
// 右侧搜索清空按钮样式
.SoBtn {
display: flex;
.SoEmpty {
background-color: transparent;
color: #000;
border: 1px solid #ccc;
}
}
}
}
</style>
数组如何递归降维 JavaScript
Array.prototype.myReduce = function () {
let newArr = [];
for (let item of this) {
if (Array.isArray(item)) {
newArr = newArr.concat(item.myReduce());
} else {
newArr.push(item);
}
}
return newArr;
};
// 多维数组
let arr = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
console.log(arr.myReduce());