添加新的需求
This commit is contained in:
300
pc-cattle-transportation/src/utils/aiotagro.js
Normal file
300
pc-cattle-transportation/src/utils/aiotagro.js
Normal file
@@ -0,0 +1,300 @@
|
||||
/**
|
||||
* 通用js方法封装处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
// 日期格式化
|
||||
export function parseTime(time, pattern) {
|
||||
if (arguments.length === 0 || !time) {
|
||||
return null;
|
||||
}
|
||||
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
|
||||
let date;
|
||||
if (typeof time === 'object') {
|
||||
date = time;
|
||||
} else {
|
||||
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
time = parseInt(time, 10);
|
||||
} else if (typeof time === 'string') {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
time = time
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
.replace(new RegExp(/-/gm), '/')
|
||||
.replace('T', ' ')
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
.replace(new RegExp(/\.[\d]{3}/gm), '');
|
||||
}
|
||||
if (typeof time === 'number' && time.toString().length === 10) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
time *= 1000;
|
||||
}
|
||||
date = new Date(time);
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay(),
|
||||
};
|
||||
const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key];
|
||||
// Note: getDay() returns 0 on Sunday
|
||||
if (key === 'a') {
|
||||
return ['日', '一', '二', '三', '四', '五', '六'][value];
|
||||
}
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = `0${value}`;
|
||||
}
|
||||
return value || 0;
|
||||
});
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
export function resetForm(refName) {
|
||||
if (this.$refs[refName]) {
|
||||
this.$refs[refName].resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加日期范围
|
||||
export function addDateRange(params, dateRange, propName) {
|
||||
const search = params;
|
||||
search.params = typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
dateRange = Array.isArray(dateRange) ? dateRange : [];
|
||||
if (typeof propName === 'undefined') {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
search.params.beginTime = dateRange[0];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
search.params.endTime = dateRange[1];
|
||||
} else {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
search.params[`begin${propName}`] = dateRange[0];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
search.params[`end${propName}`] = dateRange[1];
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
// 回显数据字典
|
||||
export function selectDictLabel(datas, value) {
|
||||
if (value === undefined) {
|
||||
return '';
|
||||
}
|
||||
const actions = [];
|
||||
Object.keys(datas).some((key) => {
|
||||
if (datas[key].value === `${value}`) {
|
||||
actions.push(datas[key].label);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (actions.length === 0) {
|
||||
actions.push(value);
|
||||
}
|
||||
return actions.join('');
|
||||
}
|
||||
|
||||
// 回显数据字典(字符串数组)
|
||||
export function selectDictLabels(datas, value, separator) {
|
||||
if (value === undefined || value.length === 0) {
|
||||
return '';
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
value = value.join(',');
|
||||
}
|
||||
const actions = [];
|
||||
const currentSeparator = undefined === separator ? ',' : separator;
|
||||
const temp = value.split(currentSeparator);
|
||||
Object.keys(value.split(currentSeparator)).some((val) => {
|
||||
let match = false;
|
||||
Object.keys(datas).some((key) => {
|
||||
if (datas[key].value == `${temp[val]}`) {
|
||||
actions.push(datas[key].label + currentSeparator);
|
||||
match = true;
|
||||
}
|
||||
});
|
||||
if (!match) {
|
||||
actions.push(temp[val] + currentSeparator);
|
||||
}
|
||||
});
|
||||
return actions.join('').substring(0, actions.join('').length - 1);
|
||||
}
|
||||
|
||||
// 字符串格式化(%s )
|
||||
export function sprintf(str) {
|
||||
const args = arguments;
|
||||
let flag = true;
|
||||
let i = 1;
|
||||
str = str.replace(/%s/g, function () {
|
||||
const arg = args[i++];
|
||||
if (typeof arg === 'undefined') {
|
||||
flag = false;
|
||||
return '';
|
||||
}
|
||||
return arg;
|
||||
});
|
||||
return flag ? str : '';
|
||||
}
|
||||
|
||||
// 转换字符串,undefined,null等转化为""
|
||||
export function parseStrEmpty(str) {
|
||||
if (!str || str == 'undefined' || str == 'null') {
|
||||
return '';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// 数据合并
|
||||
export function mergeRecursive(source, target) {
|
||||
// eslint-disable-next-line guard-for-in,no-restricted-syntax
|
||||
for (const p in target) {
|
||||
try {
|
||||
if (target[p].constructor === Object) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
source[p] = mergeRecursive(source[p], target[p]);
|
||||
} else {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
source[p] = target[p];
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
source[p] = target[p];
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
*/
|
||||
export function handleTree(data, id, parentId, children) {
|
||||
const config = {
|
||||
id: id || 'id',
|
||||
parentId: parentId || 'pid',
|
||||
childrenList: children || 'children',
|
||||
};
|
||||
|
||||
const childrenListMap = {};
|
||||
const nodeIds = {};
|
||||
const tree = [];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const d of data) {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const parentId = d[config.parentId];
|
||||
if (childrenListMap[parentId] == null) {
|
||||
childrenListMap[parentId] = [];
|
||||
}
|
||||
nodeIds[d[config.id]] = d;
|
||||
childrenListMap[parentId].push(d);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const d of data) {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const parentId = d[config.parentId];
|
||||
if (nodeIds[parentId] == null) {
|
||||
tree.push(d);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const t of tree) {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
adaptToChildrenList(t);
|
||||
}
|
||||
|
||||
function adaptToChildrenList(o) {
|
||||
if (childrenListMap[o[config.id]] !== null) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
o[config.childrenList] = childrenListMap[o[config.id]];
|
||||
}
|
||||
if (o[config.childrenList]) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const c of o[config.childrenList]) {
|
||||
adaptToChildrenList(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数处理
|
||||
* @param {*} params 参数
|
||||
*/
|
||||
export function tansParams(params) {
|
||||
let result = '';
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const propName of Object.keys(params)) {
|
||||
const value = params[propName];
|
||||
const part = `${encodeURIComponent(propName)}=`;
|
||||
if (value !== null && value !== '' && typeof value !== 'undefined') {
|
||||
if (typeof value === 'object') {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const key of Object.keys(value)) {
|
||||
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const params = `${propName}[${key}]`;
|
||||
const subPart = `${encodeURIComponent(params)}=`;
|
||||
result += `${subPart + encodeURIComponent(value[key])}&`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += `${part + encodeURIComponent(value)}&`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 返回项目路径
|
||||
export function getNormalPath(p) {
|
||||
if (p.length === 0 || !p || p == 'undefined') {
|
||||
return p;
|
||||
}
|
||||
|
||||
const res = p.replace('//', '/');
|
||||
if (res[res.length - 1] === '/') {
|
||||
return res.slice(0, res.length - 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 验证是否为blob格式
|
||||
export function blobValidate(data) {
|
||||
return data.type !== 'application/json';
|
||||
}
|
||||
|
||||
// 扫描二维码获取设备id过滤
|
||||
export function getDeviceId(url) {
|
||||
let size = '';
|
||||
// 2406501594
|
||||
if (!isNaN(Number(url))) {
|
||||
size = url;
|
||||
} else if (url.indexOf('/jbq/') != -1) {
|
||||
// https://iot.aiotagro.com/jbq/2406501594
|
||||
size = url.split('/jbq/')[url.split('/jbq/').length - 1];
|
||||
} else if (url.indexOf('device_sn') != -1) {
|
||||
// https://farm.aiotagro.com/source/index.html?devicesn=2408400279&嚓te&t=1730775527
|
||||
|
||||
const parsedUrl = new URL(url);
|
||||
size = parsedUrl.searchParams.get('device_sn');
|
||||
// https://farm.aiotagro.com/source/index.html?device_sn=2408400301
|
||||
// size = url.split('devicesn=')[url.split('devicesn=').length-1]
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return size;
|
||||
}
|
||||
15
pc-cattle-transportation/src/utils/auth.js
Normal file
15
pc-cattle-transportation/src/utils/auth.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
const TokenKey = 'Admin-Token';
|
||||
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey);
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return Cookies.set(TokenKey, token);
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey);
|
||||
}
|
||||
141
pc-cattle-transportation/src/utils/axios.ts
Normal file
141
pc-cattle-transportation/src/utils/axios.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import Axios from 'axios';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
|
||||
// import { useUserStore } from "~/store/user";
|
||||
// const userStore=useUserStore();
|
||||
export let isRelogin = { show: false };
|
||||
// @ts-ignore
|
||||
Axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'; //设置前后端请求文档的类型
|
||||
|
||||
// 开发环境使用 /api 前缀,让 vite proxy 代理生效
|
||||
// 生产环境使用环境变量配置的域名
|
||||
const baseURL: any = import.meta.env.VITE_API_DOMAIN || '/api'; //设置统一接口地址前缀
|
||||
|
||||
const axios = Axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL,
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
// 前置拦截器(发起请求之前的拦截)
|
||||
axios.interceptors.request.use(
|
||||
(config) => {
|
||||
let userStore = localStorage.getItem('userStore');
|
||||
let token = '';
|
||||
if (userStore) {
|
||||
const us = JSON.parse(userStore);
|
||||
token = us.token;
|
||||
}
|
||||
if (token) {
|
||||
// @ts-ignore
|
||||
config.headers.Authorization = token;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// 后置拦截器(获取到响应时的拦截)
|
||||
axios.interceptors.response.use(
|
||||
(response) => {
|
||||
//后端没报错
|
||||
/**
|
||||
* 根据你的项目实际情况来对 response 和 error 做处理
|
||||
* 这里对 response 和 error 不做任何处理,直接返回
|
||||
*/
|
||||
const responseData = response.data;
|
||||
|
||||
|
||||
|
||||
// 单独判断导出问题-start
|
||||
if(toString.call(responseData) === '[object Blob]' && (responseData.type !== 'application/json')) {
|
||||
download(response);
|
||||
return ElMessage({
|
||||
type: 'success',
|
||||
message: '导出成功!',
|
||||
});
|
||||
}else if(toString.call(responseData) === '[object Blob]' && (responseData.type == 'application/json')){
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
return ElMessage.error(`登录过期,请重新登录!`);
|
||||
}
|
||||
// 单独判断导出问题-end
|
||||
|
||||
if (responseData && (responseData.code == 200 || responseData.status == 0)) {
|
||||
return Promise.resolve(response.data); //成功==》可以执行then方法
|
||||
|
||||
}else if(responseData.code === 401){
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
return ElMessage.error(`登录过期,请重新登录!`);
|
||||
}
|
||||
// console.log(responseData);
|
||||
// if (responseData && (responseData.code === 650)) {
|
||||
// ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
|
||||
// confirmButtonText: '重新登录',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning',
|
||||
// })
|
||||
// .then(() => {
|
||||
// window.location.href = '/login';
|
||||
// })
|
||||
// .catch(() => {});
|
||||
// // eslint-disable-next-line prefer-promise-reject-errors
|
||||
// return Promise.reject('无效的会话,或者会话已过期,请重新登录。');
|
||||
// }
|
||||
|
||||
const { msg } = responseData;
|
||||
ElMessage.error(msg?.length > 50 ? `抱歉!当前系统繁忙,请您刷新页面或稍后再试.` : msg);
|
||||
// ElMessage.error(`抱歉!当前系统繁忙,请您刷新页面或稍后再试。`);
|
||||
return Promise.reject(msg);
|
||||
},
|
||||
(error) => {
|
||||
//后端自己的接口报错
|
||||
if(error.code == "ECONNABORTED") {
|
||||
ElMessage.error(`抱歉!网络请求超时,请稍后再试!`);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
if (error.response.status === 509) {
|
||||
const html = error.response.data;
|
||||
}
|
||||
if (error.response && error.response.data) {
|
||||
if (error.response.status !== 509 && error.response.status !== 401) {
|
||||
ElMessage.error(`抱歉!当前系统繁忙,请您刷新页面或稍后再试。`);
|
||||
}
|
||||
} else {
|
||||
// ElMessage.error(`${error}`);
|
||||
ElMessage.error(`抱歉!当前系统繁忙,请您刷新页面或稍后再试。`);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// 下载文件
|
||||
function download(res: any) {
|
||||
const blob = new Blob([res.data], { type: 'application/vnd.ms-excel' }); // type是文件类,详情可以参阅blob文件类型
|
||||
// 创建新的URL并指向File对象或者Blob对象的地址
|
||||
const blobURL = window.URL.createObjectURL(blob);
|
||||
// 创建a标签,用于跳转至下载链接
|
||||
const tempLink = document.createElement('a');
|
||||
tempLink.style.display = 'none';
|
||||
tempLink.href = blobURL;
|
||||
if(res.headers['content-disposition']){
|
||||
tempLink.setAttribute('download', decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]));
|
||||
}
|
||||
// 兼容:某些浏览器不支持HTML5的download属性
|
||||
if (typeof tempLink.download === 'undefined') {
|
||||
tempLink.setAttribute('target', '_blank');
|
||||
}
|
||||
// 挂载a标签
|
||||
document.body.appendChild(tempLink);
|
||||
tempLink.click();
|
||||
document.body.removeChild(tempLink);
|
||||
// 释放blob URL地址
|
||||
window.URL.revokeObjectURL(blobURL);
|
||||
}
|
||||
|
||||
export default axios;
|
||||
6
pc-cattle-transportation/src/utils/errorCode.js
Normal file
6
pc-cattle-transportation/src/utils/errorCode.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
401: '认证失败,无法访问系统资源',
|
||||
403: '当前操作没有权限',
|
||||
404: '访问资源不存在',
|
||||
default: '系统未知错误,请反馈给管理员',
|
||||
};
|
||||
125
pc-cattle-transportation/src/utils/imageUtils.js
Normal file
125
pc-cattle-transportation/src/utils/imageUtils.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 图片处理工具函数
|
||||
*/
|
||||
|
||||
/**
|
||||
* 处理逗号分隔的图片URL
|
||||
* @param {string} imageUrl - 逗号分隔的图片URL字符串
|
||||
* @returns {Array} 图片URL数组
|
||||
*/
|
||||
export const getImageList = (imageUrl) => {
|
||||
if (!imageUrl || imageUrl.trim() === '') {
|
||||
return [];
|
||||
}
|
||||
// 按逗号分割并过滤空字符串
|
||||
return imageUrl.split(',').map(url => url.trim()).filter(url => url !== '');
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取代理图片URL(如果后端支持)
|
||||
* @param {string} originalUrl - 原始图片URL
|
||||
* @returns {string} 代理后的URL或原始URL
|
||||
*/
|
||||
export const getProxyImageUrl = (originalUrl) => {
|
||||
if (!originalUrl || !originalUrl.startsWith('http')) {
|
||||
return originalUrl;
|
||||
}
|
||||
// 使用后端代理访问图片,避免CORS问题
|
||||
// 注意:这里需要完整的URL路径
|
||||
return `/api/member/proxy/image?url=${encodeURIComponent(originalUrl)}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 测试图片URL的可访问性
|
||||
* @param {string} imageUrl - 图片URL
|
||||
* @returns {Promise<boolean>} 是否可访问
|
||||
*/
|
||||
export const testImageUrl = async (imageUrl) => {
|
||||
try {
|
||||
console.log('测试图片URL:', imageUrl);
|
||||
const response = await fetch(imageUrl, {
|
||||
method: 'HEAD',
|
||||
mode: 'cors'
|
||||
});
|
||||
console.log('图片URL测试结果:', {
|
||||
url: imageUrl,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers: Object.fromEntries(response.headers.entries())
|
||||
});
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error('图片URL测试失败:', imageUrl, error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理图片加载错误
|
||||
* @param {string} imageUrl - 失败的图片URL
|
||||
* @param {number} index - 图片索引
|
||||
*/
|
||||
export const handleImageError = (imageUrl, index) => {
|
||||
// 如果是腾讯云COS图片,这是预期的CORS错误,不需要详细日志
|
||||
if (imageUrl.includes('cos.ap-guangzhou.myqcloud.com')) {
|
||||
console.log(`腾讯云COS图片加载失败 (索引: ${index}):`, imageUrl);
|
||||
console.log('这是预期的CORS错误,图片将显示占位符');
|
||||
return;
|
||||
}
|
||||
|
||||
// 其他图片的错误才显示详细日志
|
||||
console.error(`图片加载失败 (索引: ${index}):`, imageUrl);
|
||||
console.error('可能的原因:');
|
||||
console.error('1. URL格式不正确');
|
||||
console.error('2. 服务器无法访问');
|
||||
console.error('3. CORS跨域问题');
|
||||
console.error('4. 网络连接问题');
|
||||
|
||||
// 尝试手动验证URL
|
||||
try {
|
||||
const url = new URL(imageUrl);
|
||||
console.error('URL解析成功:', url.href);
|
||||
console.error('协议:', url.protocol);
|
||||
console.error('主机:', url.hostname);
|
||||
console.error('路径:', url.pathname);
|
||||
} catch (e) {
|
||||
console.error('URL格式无效:', e.message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取图片列表(带代理支持)
|
||||
* @param {string} imageUrl - 逗号分隔的图片URL字符串
|
||||
* @param {boolean} useProxy - 是否使用代理
|
||||
* @returns {Array} 处理后的图片URL数组
|
||||
*/
|
||||
export const getImageListWithProxy = (imageUrl, useProxy = false) => {
|
||||
const urls = getImageList(imageUrl);
|
||||
|
||||
if (useProxy) {
|
||||
return urls.map(url => getProxyImageUrl(url));
|
||||
}
|
||||
|
||||
return urls;
|
||||
};
|
||||
|
||||
/**
|
||||
* 智能图片URL处理 - 根据域名决定是否使用代理
|
||||
* @param {string} imageUrl - 逗号分隔的图片URL字符串
|
||||
* @returns {Array} 处理后的图片URL数组
|
||||
*/
|
||||
export const getImageListSmart = (imageUrl) => {
|
||||
const urls = getImageList(imageUrl);
|
||||
|
||||
return urls.map(url => {
|
||||
// 如果是腾讯云COS的图片,暂时直接返回原始URL
|
||||
// 浏览器会显示占位符,但不会报错
|
||||
if (url.includes('cos.ap-guangzhou.myqcloud.com')) {
|
||||
console.log('检测到腾讯云COS图片,暂时使用原始URL(显示占位符):', url);
|
||||
return url; // 暂时直接返回,让浏览器显示占位符
|
||||
}
|
||||
// 其他图片直接返回原始URL
|
||||
console.log('其他图片,直接使用原始URL:', url);
|
||||
return url;
|
||||
});
|
||||
};
|
||||
30
pc-cattle-transportation/src/utils/jsencrypt.js
Normal file
30
pc-cattle-transportation/src/utils/jsencrypt.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min';
|
||||
|
||||
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
||||
|
||||
const publicKey =
|
||||
'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==';
|
||||
|
||||
const privateKey =
|
||||
'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
|
||||
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
|
||||
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
|
||||
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
|
||||
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
|
||||
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
|
||||
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
|
||||
'UP8iWi1Qw0Y=';
|
||||
|
||||
// 加密
|
||||
export function encrypt(txt) {
|
||||
const encryptor = new JSEncrypt();
|
||||
encryptor.setPublicKey(publicKey); // 设置公钥
|
||||
return encryptor.encrypt(txt); // 对数据进行加密
|
||||
}
|
||||
|
||||
// 解密
|
||||
export function decrypt(txt) {
|
||||
const encryptor = new JSEncrypt();
|
||||
encryptor.setPrivateKey(privateKey); // 设置私钥
|
||||
return encryptor.decrypt(txt); // 对数据进行解密
|
||||
}
|
||||
13
pc-cattle-transportation/src/utils/loadBmap.js
Normal file
13
pc-cattle-transportation/src/utils/loadBmap.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export function BMPGL(ak) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
window.init = function () {
|
||||
// eslint-disable-next-line
|
||||
resolve(BMapGL);
|
||||
};
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = `http://api.map.baidu.com/api?v=3.0&type=webgl&ak=${ak}&callback=init`;
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
49
pc-cattle-transportation/src/utils/permission.js
Normal file
49
pc-cattle-transportation/src/utils/permission.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import useUserStore from '~/store/modules/user';
|
||||
|
||||
/**
|
||||
* 字符权限校验
|
||||
* @param {Array} value 校验值
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function checkPermi(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const { permissions } = useUserStore();
|
||||
const permissionDatas = value;
|
||||
const all_permission = '*:*:*';
|
||||
|
||||
const hasPermission = permissions.some((permission) => {
|
||||
return all_permission === permission || permissionDatas.includes(permission);
|
||||
});
|
||||
|
||||
if (!hasPermission) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色权限校验
|
||||
* @param {Array} value 校验值
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function checkRole(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const { roles } = useUserStore();
|
||||
const permissionRoles = value;
|
||||
const super_admin = 'admin';
|
||||
|
||||
const hasRole = roles.some((role) => {
|
||||
return super_admin === role || permissionRoles.includes(role);
|
||||
});
|
||||
|
||||
if (!hasRole) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.error(`need roles! Like checkRole="['admin','editor']"`);
|
||||
return false;
|
||||
}
|
||||
187
pc-cattle-transportation/src/utils/request.js
Normal file
187
pc-cattle-transportation/src/utils/request.js
Normal file
@@ -0,0 +1,187 @@
|
||||
import axios from 'axios';
|
||||
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { getToken } from '~/utils/auth';
|
||||
import errorCode from '~/utils/errorCode';
|
||||
import { tansParams, blobValidate } from '~/utils/ruoyi';
|
||||
import cache from '~/plugins/cache';
|
||||
|
||||
let downloadLoadingInstance;
|
||||
// 是否显示重新登录
|
||||
export const isRelogin = { show: false };
|
||||
|
||||
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API || '/api',
|
||||
// 超时
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false;
|
||||
// 是否需要防止数据重复提交
|
||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
|
||||
|
||||
// 优先从localStorage获取token(与axios.ts保持一致)
|
||||
let token = null;
|
||||
const userStoreStr = localStorage.getItem('userStore');
|
||||
if (userStoreStr) {
|
||||
try {
|
||||
const userStore = JSON.parse(userStoreStr);
|
||||
token = userStore.token;
|
||||
} catch (e) {
|
||||
console.error('解析userStore失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果localStorage没有,则从Cookie获取
|
||||
if (!token) {
|
||||
token = getToken();
|
||||
}
|
||||
|
||||
if (token && !isToken) {
|
||||
// 检查token是否已经包含Bearer前缀
|
||||
if (token.startsWith('Bearer ')) {
|
||||
config.headers.Authorization = token;
|
||||
} else {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
}
|
||||
// get请求映射params参数
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = `${config.url}?${tansParams(config.params)}`;
|
||||
url = url.slice(0, -1);
|
||||
config.params = {};
|
||||
config.url = url;
|
||||
}
|
||||
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
|
||||
const requestObj = {
|
||||
url: config.url,
|
||||
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
|
||||
time: new Date().getTime(),
|
||||
};
|
||||
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
|
||||
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
|
||||
if (requestSize >= limitSize) {
|
||||
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。');
|
||||
return config;
|
||||
}
|
||||
const sessionObj = cache.session.getJSON('sessionObj');
|
||||
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
|
||||
cache.session.setJSON('sessionObj', requestObj);
|
||||
} else {
|
||||
const s_url = sessionObj.url; // 请求地址
|
||||
const s_data = sessionObj.data; // 请求数据
|
||||
const s_time = sessionObj.time; // 请求时间
|
||||
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
|
||||
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
|
||||
const message = '数据正在处理,请勿重复提交';
|
||||
console.warn(`[${s_url}]: ${message}`);
|
||||
return Promise.reject(new Error(message));
|
||||
}
|
||||
cache.session.setJSON('sessionObj', requestObj);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
Promise.reject(error);
|
||||
},
|
||||
);
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(
|
||||
(res) => {
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = res.data.code || 200;
|
||||
// 获取错误信息
|
||||
const msg = errorCode[code] || res.data.msg || errorCode.default;
|
||||
// 二进制数据则直接返回
|
||||
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
|
||||
return res.data;
|
||||
}
|
||||
if (code === 401 || code === 650) {
|
||||
if (!isRelogin.show) {
|
||||
isRelogin.show = true;
|
||||
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
|
||||
confirmButtonText: '重新登录',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
isRelogin.show = false;
|
||||
location.href = '/login';
|
||||
})
|
||||
.catch(() => {
|
||||
isRelogin.show = false;
|
||||
});
|
||||
}
|
||||
return Promise.reject('无效的会话,或者会话已过期,请重新登录。');
|
||||
}
|
||||
if (code === 500) {
|
||||
ElMessage({ message: msg, type: 'error' });
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
if (code === 601) {
|
||||
ElMessage({ message: msg, type: 'warning' });
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
if (code !== 200) {
|
||||
ElNotification.error({ title: msg });
|
||||
return Promise.reject('error');
|
||||
}
|
||||
return Promise.resolve(res.data);
|
||||
},
|
||||
(error) => {
|
||||
let { message } = error;
|
||||
if (message == 'Network Error') {
|
||||
message = '后端接口连接异常';
|
||||
} else if (message.includes('timeout')) {
|
||||
message = '系统接口请求超时';
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
message = `系统接口${message.substr(message.length - 3)}异常`;
|
||||
}
|
||||
ElMessage({ message, type: 'error', duration: 5 * 1000 });
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// 通用下载方法
|
||||
export function download(url, params, filename, config) {
|
||||
downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
|
||||
return service
|
||||
.post(url, params, {
|
||||
transformRequest: [
|
||||
(params) => {
|
||||
return tansParams(params);
|
||||
},
|
||||
],
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
responseType: 'blob',
|
||||
...config,
|
||||
})
|
||||
.then(async (data) => {
|
||||
const isBlob = blobValidate(data);
|
||||
if (isBlob) {
|
||||
const blob = new Blob([data]);
|
||||
saveAs(blob, filename);
|
||||
} else {
|
||||
const resText = await data.text();
|
||||
const rspObj = JSON.parse(resText);
|
||||
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode.default;
|
||||
ElMessage.error(errMsg);
|
||||
}
|
||||
downloadLoadingInstance.close();
|
||||
})
|
||||
.catch((r) => {
|
||||
console.error(r);
|
||||
ElMessage.error('下载文件出现错误,请联系管理员!');
|
||||
downloadLoadingInstance.close();
|
||||
});
|
||||
}
|
||||
|
||||
export default service;
|
||||
43
pc-cattle-transportation/src/utils/ruoyi.js
Normal file
43
pc-cattle-transportation/src/utils/ruoyi.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 通用js方法封装处理
|
||||
*/
|
||||
|
||||
/**
|
||||
* 参数处理
|
||||
* @param {*} params 参数
|
||||
*/
|
||||
export function tansParams(params) {
|
||||
let result = '';
|
||||
for (const propName of Object.keys(params)) {
|
||||
const value = params[propName];
|
||||
const part = `${encodeURIComponent(propName)}=`;
|
||||
if (value !== null && value !== '' && typeof value !== 'undefined') {
|
||||
if (typeof value === 'object') {
|
||||
for (const key of Object.keys(value)) {
|
||||
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
|
||||
const params = `${propName}[${key}]`;
|
||||
const subPart = `${encodeURIComponent(params)}=`;
|
||||
result += `${subPart + encodeURIComponent(value[key])}&`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += `${part + encodeURIComponent(value)}&`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否为blob格式
|
||||
*/
|
||||
export async function blobValidate(data) {
|
||||
try {
|
||||
const text = await data.text();
|
||||
JSON.parse(text);
|
||||
return false;
|
||||
} catch (error) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
67
pc-cattle-transportation/src/utils/scrollTo.js
Normal file
67
pc-cattle-transportation/src/utils/scrollTo.js
Normal file
@@ -0,0 +1,67 @@
|
||||
Math.easeInOutQuad = function (t, b, c, d) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
t /= d / 2;
|
||||
if (t < 1) {
|
||||
return (c / 2) * t * t + b;
|
||||
}
|
||||
// eslint-disable-next-line no-param-reassign,no-plusplus
|
||||
t--;
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b;
|
||||
};
|
||||
|
||||
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
|
||||
const requestAnimFrame = (function () {
|
||||
return (
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
function (callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
}
|
||||
);
|
||||
})();
|
||||
|
||||
/**
|
||||
* Because it's so fucking difficult to detect the scrolling element, just move them all
|
||||
* @param {number} amount
|
||||
*/
|
||||
function move(amount) {
|
||||
document.documentElement.scrollTop = amount;
|
||||
document.body.parentNode.scrollTop = amount;
|
||||
document.body.scrollTop = amount;
|
||||
}
|
||||
|
||||
function position() {
|
||||
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} to
|
||||
* @param {number} duration
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function scrollTo(to, duration, callback) {
|
||||
const start = position();
|
||||
const change = to - start;
|
||||
const increment = 20;
|
||||
let currentTime = 0;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
duration = typeof duration === 'undefined' ? 500 : duration;
|
||||
const animateScroll = function () {
|
||||
// increment the time
|
||||
currentTime += increment;
|
||||
// find the value with the quadratic in-out easing function
|
||||
const val = Math.easeInOutQuad(currentTime, start, change, duration);
|
||||
// move the document.body
|
||||
move(val);
|
||||
// do the animation unless its over
|
||||
if (currentTime < duration) {
|
||||
requestAnimFrame(animateScroll);
|
||||
} else if (callback && typeof callback === 'function') {
|
||||
// the animation is done so lets callback
|
||||
callback();
|
||||
}
|
||||
};
|
||||
animateScroll();
|
||||
}
|
||||
31
pc-cattle-transportation/src/utils/service.js
Normal file
31
pc-cattle-transportation/src/utils/service.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// post请求
|
||||
export const post = (config) => {
|
||||
return Service({
|
||||
...config,
|
||||
method: 'post',
|
||||
data: config.data,
|
||||
});
|
||||
};
|
||||
// get请求
|
||||
export const get = (config) => {
|
||||
return Service({
|
||||
...config,
|
||||
method: 'get',
|
||||
params: config.data,
|
||||
});
|
||||
};
|
||||
// put请求
|
||||
export const put = (config) => {
|
||||
return Service({
|
||||
...config,
|
||||
method: 'put',
|
||||
data: config.data,
|
||||
});
|
||||
};
|
||||
// delete请求
|
||||
export const del = (config) => {
|
||||
return Service({
|
||||
...config,
|
||||
method: 'delete',
|
||||
});
|
||||
};
|
||||
165
pc-cattle-transportation/src/utils/superAdminHelper.js
Normal file
165
pc-cattle-transportation/src/utils/superAdminHelper.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import { getMenuList, assignRoleMenus, getUserList } from '@/api/permission.js';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
/**
|
||||
* 为超级管理员账户分配所有菜单权限
|
||||
* @param {string} mobile 手机号,默认为 '15900000000'
|
||||
* @returns {Promise<boolean>} 是否成功
|
||||
*/
|
||||
export async function assignAllPermissionsToSuperAdmin(mobile = '15900000000') {
|
||||
try {
|
||||
console.log(`=== 开始为超级管理员 ${mobile} 分配所有菜单权限 ===`);
|
||||
|
||||
// 1. 获取用户列表,找到目标用户
|
||||
const userListRes = await getUserList();
|
||||
if (userListRes.code !== 200) {
|
||||
throw new Error('获取用户列表失败');
|
||||
}
|
||||
|
||||
const targetUser = userListRes.data.find(user => user.mobile === mobile);
|
||||
if (!targetUser) {
|
||||
throw new Error(`未找到手机号为 ${mobile} 的用户`);
|
||||
}
|
||||
|
||||
console.log('=== 找到目标用户 ===', targetUser);
|
||||
|
||||
// 2. 获取所有菜单列表
|
||||
const menuListRes = await getMenuList();
|
||||
if (menuListRes.code !== 200) {
|
||||
throw new Error('获取菜单列表失败');
|
||||
}
|
||||
|
||||
const allMenus = menuListRes.data || [];
|
||||
const allMenuIds = allMenus.map(menu => menu.id);
|
||||
|
||||
console.log('=== 获取到所有菜单 ===', {
|
||||
totalMenus: allMenus.length,
|
||||
menuIds: allMenuIds
|
||||
});
|
||||
|
||||
// 3. 为超级管理员角色分配所有菜单权限
|
||||
const assignRes = await assignRoleMenus({
|
||||
roleId: targetUser.roleId,
|
||||
menuIds: allMenuIds
|
||||
});
|
||||
|
||||
if (assignRes.code === 200) {
|
||||
console.log('=== 权限分配成功 ===');
|
||||
ElMessage.success(`成功为超级管理员 ${mobile} 分配了 ${allMenuIds.length} 个菜单权限`);
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(assignRes.msg || '权限分配失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('=== 权限分配失败 ===', error);
|
||||
ElMessage.error(`权限分配失败: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查超级管理员权限状态
|
||||
* @param {string} mobile 手机号,默认为 '15900000000'
|
||||
* @returns {Promise<Object>} 权限状态信息
|
||||
*/
|
||||
export async function checkSuperAdminPermissions(mobile = '15900000000') {
|
||||
try {
|
||||
console.log(`=== 检查超级管理员 ${mobile} 的权限状态 ===`);
|
||||
|
||||
// 1. 获取用户列表,找到目标用户
|
||||
const userListRes = await getUserList();
|
||||
if (userListRes.code !== 200) {
|
||||
throw new Error('获取用户列表失败');
|
||||
}
|
||||
|
||||
const targetUser = userListRes.data.find(user => user.mobile === mobile);
|
||||
if (!targetUser) {
|
||||
throw new Error(`未找到手机号为 ${mobile} 的用户`);
|
||||
}
|
||||
|
||||
// 2. 获取该用户当前已分配的菜单权限
|
||||
const { getRoleMenuIds } = await import('@/api/permission.js');
|
||||
const roleMenuRes = await getRoleMenuIds(targetUser.roleId);
|
||||
|
||||
if (roleMenuRes.code !== 200) {
|
||||
throw new Error('获取角色菜单权限失败');
|
||||
}
|
||||
|
||||
const assignedMenuIds = roleMenuRes.data || [];
|
||||
|
||||
// 3. 获取所有菜单数量
|
||||
const menuListRes = await getMenuList();
|
||||
if (menuListRes.code !== 200) {
|
||||
throw new Error('获取菜单列表失败');
|
||||
}
|
||||
|
||||
const totalMenus = menuListRes.data.length;
|
||||
|
||||
const status = {
|
||||
user: targetUser,
|
||||
totalMenus: totalMenus,
|
||||
assignedMenus: assignedMenuIds.length,
|
||||
isComplete: assignedMenuIds.length === totalMenus,
|
||||
missingMenus: totalMenus - assignedMenuIds.length
|
||||
};
|
||||
|
||||
console.log('=== 权限状态检查结果 ===', status);
|
||||
|
||||
return status;
|
||||
|
||||
} catch (error) {
|
||||
console.error('=== 权限状态检查失败 ===', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键为超级管理员分配所有权限(包含UI提示)
|
||||
* @param {string} mobile 手机号,默认为 '15900000000'
|
||||
*/
|
||||
export async function quickAssignAllPermissions(mobile = '15900000000') {
|
||||
try {
|
||||
// 先检查当前状态
|
||||
const status = await checkSuperAdminPermissions(mobile);
|
||||
|
||||
if (status.isComplete) {
|
||||
ElMessage.info(`超级管理员 ${mobile} 已经拥有所有菜单权限`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 确认操作
|
||||
const confirmed = await new Promise((resolve) => {
|
||||
ElMessageBox.confirm(
|
||||
`确定要为超级管理员 ${mobile} 分配所有菜单权限吗?\n\n当前状态:\n- 总菜单数:${status.totalMenus}\n- 已分配:${status.assignedMenus}\n- 缺失:${status.missingMenus}`,
|
||||
'确认分配权限',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
).then(() => resolve(true)).catch(() => resolve(false));
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
ElMessage.info('已取消权限分配');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行分配
|
||||
const success = await assignAllPermissionsToSuperAdmin(mobile);
|
||||
|
||||
if (success) {
|
||||
// 重新检查状态
|
||||
const newStatus = await checkSuperAdminPermissions(mobile);
|
||||
ElMessage.success(`权限分配完成!现在拥有 ${newStatus.assignedMenus}/${newStatus.totalMenus} 个菜单权限`);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
} catch (error) {
|
||||
console.error('=== 快速分配权限失败 ===', error);
|
||||
ElMessage.error(`操作失败: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
90
pc-cattle-transportation/src/utils/validate.js
Normal file
90
pc-cattle-transportation/src/utils/validate.js
Normal file
@@ -0,0 +1,90 @@
|
||||
// 判断给定的字符串是否是有效的用户名
|
||||
export function validUsername(str) {
|
||||
const valid_map = ['admin', 'editor'];
|
||||
return valid_map.indexOf(str.trim()) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断url是否是http或https
|
||||
* @param {string} path
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isHttp(url) {
|
||||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1;
|
||||
}
|
||||
|
||||
// 数字转化为大写金额
|
||||
export function digitUppercase(n) {
|
||||
const fraction = ['角', '分'];
|
||||
const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
||||
const unit = [
|
||||
['元', '万', '亿'],
|
||||
['', '拾', '佰', '仟'],
|
||||
];
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
n = Math.abs(n);
|
||||
let s = '';
|
||||
// eslint-disable-next-line no-plusplus
|
||||
for (let i = 0; i < fraction.length; i++) {
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
s += (digit[Math.floor(n * 10 * 10 ** i) % 10] + fraction[i]).replace(/零./, '');
|
||||
}
|
||||
s = s || '整';
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
n = Math.floor(n);
|
||||
// eslint-disable-next-line no-plusplus
|
||||
for (let i = 0; i < unit[0].length && n > 0; i++) {
|
||||
let p = '';
|
||||
// eslint-disable-next-line no-plusplus
|
||||
for (let j = 0; j < unit[1].length && n > 0; j++) {
|
||||
p = digit[n % 10] + unit[1][j] + p;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
n = Math.floor(n / 10);
|
||||
}
|
||||
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
|
||||
}
|
||||
return s
|
||||
.replace(/(零.)*零元/, '元')
|
||||
.replace(/(零.)+/g, '零')
|
||||
.replace(/^整$/, '零元整');
|
||||
}
|
||||
|
||||
// 将一个数组中的空元素去掉
|
||||
export function cleanArray(actual) {
|
||||
const newArray = [];
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
if (actual[i]) {
|
||||
newArray.push(actual[i]);
|
||||
}
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
export function uniqueArr(arr) {
|
||||
return Array.from(new Set(arr));
|
||||
}
|
||||
|
||||
// 将URL中的查询参数转换为对象
|
||||
export function param2Obj(url) {
|
||||
const search = url.split('?')[1];
|
||||
if (!search) {
|
||||
return {};
|
||||
}
|
||||
return JSON.parse(`{"${decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`);
|
||||
}
|
||||
|
||||
// 将对象转为为数组 =====》 待验证
|
||||
export function toNumericPairs(obj) {
|
||||
const entries = Object.entries(input);
|
||||
return entries.map((entry) => [Number(entry[0]), entry[1]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断path是否为外链
|
||||
* @param {string} path
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isExternal(path) {
|
||||
return /^(https?:|mailto:|tel:)/.test(path);
|
||||
}
|
||||
79
pc-cattle-transportation/src/utils/validateFuns.js
Normal file
79
pc-cattle-transportation/src/utils/validateFuns.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// 验证手机号
|
||||
export function checkMobile(str) {
|
||||
const regMobile = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
|
||||
return regMobile.test(str);
|
||||
}
|
||||
// 验证座机号
|
||||
export function checkPhone(str) {
|
||||
const isPhone = /^([0-9]{3,4}-)?[0-9]{7,8}$/;
|
||||
return isPhone.test(str);
|
||||
}
|
||||
// 手机号中间四位变成 *
|
||||
export function telFormat(tel) {
|
||||
tel = String(tel);
|
||||
return `${tel.substr(0, 3)}****${tel.substr(7)}`;
|
||||
}
|
||||
|
||||
// 验证身份证
|
||||
export function isIdCard(str) {
|
||||
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
|
||||
return reg.test(str);
|
||||
}
|
||||
|
||||
// 验证名字
|
||||
export function isChineseName(str) {
|
||||
const reg = /^[\u4E00-\u9FA5]{2,4}$/;
|
||||
return reg.test(str);
|
||||
}
|
||||
// 验证邮箱
|
||||
export function checkEmail(str) {
|
||||
const reg = /^([0-9A-Za-z\-_\.]+)@([0-9a-z]+\.[a-z]{2,3}(\.[a-z]{2})?)$/g;
|
||||
return reg.test(str);
|
||||
}
|
||||
|
||||
// 验证网址是否有效
|
||||
export function validURL(url) {
|
||||
const reg =
|
||||
/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
|
||||
return reg.test(url);
|
||||
}
|
||||
// 验证url是否是http或https
|
||||
export function isHttp(url) {
|
||||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1;
|
||||
}
|
||||
|
||||
// 验证path是否为外链
|
||||
export function isExternal(path) {
|
||||
return /^(https?:|mailto:|tel:)/.test(path);
|
||||
}
|
||||
|
||||
// 验证参数是否为数组
|
||||
export function isArray(arg) {
|
||||
if (typeof Array.isArray === 'undefined') {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]';
|
||||
}
|
||||
return Array.isArray(arg);
|
||||
}
|
||||
// 验证参数是否为字符串类型
|
||||
export function isString(str) {
|
||||
if (typeof str === 'string' || str instanceof String) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证一个字符串是否只包含小写字母
|
||||
export function validLowerCase(str) {
|
||||
const reg = /^[a-z]+$/;
|
||||
return reg.test(str);
|
||||
}
|
||||
// 验证一个字符串是否只包含大写字母
|
||||
export function validUpperCase(str) {
|
||||
const reg = /^[A-Z]+$/;
|
||||
return reg.test(str);
|
||||
}
|
||||
// 验证一个字符串是否只包含英文字母
|
||||
export function validAlphabets(str) {
|
||||
const reg = /^[A-Za-z]+$/;
|
||||
return reg.test(str);
|
||||
}
|
||||
Reference in New Issue
Block a user