import axios from 'axios';
axios({
url: 接口路径,
method: 请求方式,
}).then(回调方法)
> 或者
fetch(路径, {
method: 请求方法
})
.then(回调)
import { 方法名 } from 调用路径;
function debounce(){
// axios
}
export default{
debounce,
}
<template #examine="{record }">
<a-space>
<a @click="examine(record.fileName)">查看</a>
</a-space>
</template>
slots: { customRender: ‘examine’ }
>static async blobDownload(url, params,filename) {
if (params === undefined) {
params = {};
}
if(filename === undefined){
filename = '导出文件.xlsx'
}
const form = params
axios({ // 用axios发送post请求
method: 'post',
url: url,
data: form,
responseType: 'blob' // 表明返回服务器返回的数据类型
}).then((res) => { // 处理返回的文件流
const content = res.data
const blob = new Blob([content])
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = filename
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, filename)
}
return true
})
}
>static export(params,obj,name) {
return Request.blobDownload('/ai-plus/bank/flow/task/result/excel?taskId='+params,obj,name);
}
export(record.jobId, record.jobName)
记住方法一定要导出才能够调用
let oImg = e.target;
let disX = e.clientX - oImg.offsetLeft;
let disY = e.clientY - oImg.offsetTop;
document.onmousemove = e => {
e.preventDefault();
let left = e.clientX - disX;
let top = e.clientY - disY;
document.querySelector('.moveImage').style.left = left + 'px';
document.querySelector('.moveImage').style.top = top + 'px';
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
};
let nowScrollTop = document.getElementById('masks').scrollTop;
let nowScrollLeft = document.getElementById('masks').scrollLeft;
if (nowScrollTop - (offsetY - pdfObj.imgOffsetY) >= 0) {
document.getElementById('masks').scrollTop = nowScrollTop - (offsetY - pdfObj.imgOffsetY);
}
if (nowScrollLeft - (offsetX - pdfObj.imgOffsetX) >= 0) {
document.getElementById('masks').scrollLeft = nowScrollLeft - (offsetX - pdfObj.imgOffsetX);
}
if (this.mainImgUrl.indexOf(imgUrl) !== -1) {
let index = this.mainImgUrl.indexOf(imgUrl);
this.mianImage(this.showMainImgUrl[index - 1], index - 1);
} else {
let index = this.detailImgUrl.indexOf(imgUrl);
this.detailImage(this.showDetailImgUrl[index - 1], index - 1);
}
具体可参照ai+后台管理系统sku文件
websocket = new WebSocket('ws://172.168.30.5:8089/biSocket/1513721148340064257');
websocket.onopen = function () {
console.log('连接已经建立');
};
websocket.onmessage = function (e) {
getMessage(e);
};
websocket.onerror = function () {
netWorkOutAge.value = true;
console.log('发生错误');
console.log('onerror发送成功');
heartCheck.start();
};
websocket.onclose = function (e) {
console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean);
netWorkOutAge.value = true;
document.querySelector('.main').setAttribute('style', 'opacity:0.4');
console.log('onclose发送成功');
//断开网络后连接网络刷新请求
console.log('断开连接后发送成功');
//连接关闭启动定时任务 五秒后在创建
heartCheck.start();
};
//定时器 只执行一次的那种 只是为了限制重连频率 = =
let heartCheck = {
timeout: 5000, //重连时间
timeoutObj: null,
start: function () {
this.timeoutObj = setTimeout(function () {
websocket.send("{'messageType': 'ROBOT_CURRENT_JOB_ACK'}");
getSocket(); //重新创建 websocket 对象并赋值
}, this.timeout);
}
};
保证不断开的原理就是设置定时器,具体可看mro-bi-fronted这个项目代码
import * as tocbot from 'tocbot';
tocbot.init({
tocSelector: '.allTitles',
contentSelector: '.content_left',
ignoreSelector: 'js-toc-ignore',
headingSelector: 'h1',
scrollSmooth: true,
hasInnerContainers: false,
headingsOffset: 80,
scrollSmoothOffset: true,
fixedSidebarOffset: 'auto',
scrollEndCallback: function() {
window.tocPhase = null;
},
onclick: function() {
window.tocPhase = true;
}
});
注意一定要注意它的执行栈的执行顺序,在异步中使用该方法
https://blog.csdn.net/cune1359/article/details/106844182
官方文档
文字高亮不仅后端可以处理,前端也可以处理
export function highLightTableMsg(msg, highLightStr) {
if (msg == null) {
msg = ''
}
if (highLightStr == null) {
highLightStr = ''
}
if (msg instanceof Object) {
msg = JSON.stringify(msg)
}
if (highLightStr instanceof Object) {
highLightStr = JSON.stringify(highLightStr)
}
if (!(msg instanceof String)) {
msg = msg.toString()
}
if (!(highLightStr instanceof String)) {
highLightStr = highLightStr.toString()
}
var htmlStr = ''
if (highLightStr.length > 0) {
if (msg.indexOf(highLightStr) !== -1) {
assemblyStr(msg, highLightStr)
} else {
htmlStr = '<span>' + msg + '</span>'
}
} else {
htmlStr = '<span>' + msg + '</span>'
}
function assemblyStr(msgAssembly, highLightAssembly) {
if (msgAssembly.indexOf(highLightAssembly) !== -1) {
var length = highLightAssembly.length
var start = msgAssembly.indexOf(highLightAssembly)
htmlStr = htmlStr + '<span>' + msgAssembly.substring(0, start) + '</span>' + '<span class="log-hight-light" style="color:#C92B2F">' + highLightAssembly + '</span>'
msgAssembly = msgAssembly.substring(start + length, msgAssembly.length)
assemblyStr(msgAssembly, highLightAssembly)
} else {
htmlStr = htmlStr + '<span>' + msgAssembly + '</span>'
}
}
return htmlStr
}
import { highLightTableMsg } from '../../utils/highLight';
highLightTableMsg(val, searchValue); //查询结果标红
两个参数分别对应标题和文本
import { debounce } from ‘lodash-es’;
//防抖防止多次调用
const filterOption = debounce(async value => {
let allDataValue = await axios.get(`store/mall/list?storeName=${value}`);
if (allDataValue.data.code === '00000') {
if (allDataValue.data.data.length > 0) {
allDataValue.data.data.forEach(() => {
dataValue.value = allDataValue.data.data.map(element => ({
value: element.storeName,
storeId: element.storeId
}));
});
storeArr.push(...allDataValue.data.data)
fetch.value = true;
} else {
fetch.value = false;
}
}
}, 300);
<a-select
show-search
placeholder="请输入店铺名称"
style="width: 300px"
:default-active-first-option="false"
:show-arrow="false"
:not-found-content="fetch ? undefined : '搜索内容不存在'"
@search="filterOption"
:getPopupContainer="
triggerNode => {
return triggerNode.parentNode || document.body;
}
"
:options="dataValue"
@change="handleChange"
>
<template v-if="fetch" #notFoundContent>
<a-spin size="small"></a-spin>
</template>
</a-select>
<ele-pro-table
ref="table"
row-key="brandId"
:datasource="url"
:columns="columns"
:where="where"
@change="tablaChange"
v-model:selection="selection"
:scroll="{ x: 'max-content' }"
>
</ele-pro-table>
组件自带的有分页,请求地址,还有页码点击的事件
比如说@change事件就代表获取当前页数
tablaChange(pagination) {
this.pageNo = pagination.current;
}
const columns = [
{
title: '商城订单编号',
dataIndex: 'ordersSn'
},
{
title: 'orderId',
dataIndex: 'omsSn'
},
{
title: 'OMS推送状态',
dataIndex: 'omsCreateStatus',
customRender: record => {
return record.record.omsCreateStatus == 1 ? '推送成功' : '推送失败';
}
},
{
title: '下单企业名称',
dataIndex: 'companyName'
},
{
title: '下单用户名称',
dataIndex: 'memberName'
},
{
title: '用户联系电话',
dataIndex: 'memberMobile'
},
{
title: '商城订单状态',
dataIndex: 'ordersStateName'
},
{
title: '订单金额',
dataIndex: 'ordersAmount'
},
{
title: '支付方式',
dataIndex: 'payment',
customRender: record => {
return record.text == 0 ? '在线支付' : record.text == 1 ? '线下支付' : '账期支付';
}
},
{
title: '下单时间',
dataIndex: 'createTime',
// customRender: ({ item }) => moment(item).format('YYYY-MM-DD:HH:MM:SS')
},
{
title: '操作',
key: 'action',
width: 150,
align: 'center',
slots: { customRender: 'action' }
}
];
在当前表头设置
customRender: record => {
return record.text == 0 ? '在线支付' : record.text == 1 ? '线下支付' : '账期支付';
}
其次就可以生成模板在文本当中
<!-- table操作栏按钮 -->
<template #action="{ record }">
<a-space>
<a @click="openEdit(record)">详情</a>
<a-divider type="vertical" />
<a-popconfirm
v-if="record.omsCreateStatus !== 1"
title="是否确定要重新推送"
ok-text="是"
cancel-text="否"
@confirm="confirm(record.ordersId)"
@cancel="cancel"
>
<a href="#">重新推送</a>
</a-popconfirm>
</a-space>
</template>
提示:局部刷新表格可以通过ajax请求的原理,增加一个loading框让用户以为是在刷新界面
弹出层主要是父与子之间的通信,利用父传子的原理
调用子组件
import { BrandApi } from '@/api/BrandApi';
生成模板即可
<!-- 编辑弹窗 -->
<brand-edit v-model:visible="showEdit" :data="current" @done="reload" />
可以看出,‘ :’是父组件传给子组件的值;‘@’是传递的一种方法回调
emits: ['done', 'update:visible'],
inject: ['reload'],
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
不了解的小伙伴可以看看这篇博客
http://events.jianshu.io/p/be840cc0fa6a
一般来说,会先都是通过v-model双向绑定来实现的
其次,回显得注意那些为必填非必填的情况
// 表单验证规则
const rules = {
showImage: [{ required: true, message: '请输入品牌图片', type: 'string', trigger: 'blur' }],
brandName: [{ required: true, message: '请输入品牌名称', type: 'string', trigger: 'blur' }],
registerNumber: [{ required: true, message: '请输入商标注册号', type: 'string', trigger: 'blur' }]
},
:getPopupContainer="
(triggerNode) => {
return triggerNode.parentNode || document.body
}"
…
vue3.x
https://cn.vuejs.org/
ant-design
https://www.antdv.com/components/overview