diff --git a/src/api/admin/sys-public-param.js b/src/api/admin/sys-public-param.js new file mode 100644 index 0000000000000000000000000000000000000000..5408ddbc9e5c37bae47f4247834d64a6963e4a7e --- /dev/null +++ b/src/api/admin/sys-public-param.js @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +import request from '@/router/axios' + +export function fetchList(query) { + return request({ + url: '/admin/param/page', + method: 'get', + params: query + }) +} + +export function addObj(obj) { + return request({ + url: '/admin/param', + method: 'post', + data: obj + }) +} + +export function getObj(key) { + return request({ + url: '/admin/param/publicValue/' + key, + method: 'get' + }) +} + +export function delObj(id) { + return request({ + url: '/admin/param/' + id, + method: 'delete' + }) +} + +export function putObj(obj) { + return request({ + url: '/admin/param', + method: 'put', + data: obj + }) +} + +export function refreshCache() { + return request({ + url: '/admin/param/sync', + method: 'put' + }) +} diff --git a/src/const/crud/admin/sys-public-param.js b/src/const/crud/admin/sys-public-param.js new file mode 100644 index 0000000000000000000000000000000000000000..f8e8b2e39141b7b8b3161f567fde11e87670a952 --- /dev/null +++ b/src/const/crud/admin/sys-public-param.js @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +import { rule } from "@/util/validateRules"; + +import {getObj} from '@/api/admin/sys-public-param' + + +var validateParam = (rule, value, callback) => { + getObj(value).then(response => { + if (window.boxType === 'edit') callback() + const result = response.data.data + if (result !== null) { + callback(new Error('参数键已经存在')) + } else { + callback() + } + }) +} + +export const tableOption = { + border: true, + index: true, + indexLabel: '序号', + stripe: true, + menuAlign: 'center', + searchMenuSpan: 6, + column: [ + { + label: '名称', + search: true, + prop: 'publicName', + rules: [ + { required: true, message: '请输名称', trigger: 'blur' }, + { max: 30, message: '长度在 30 个字符', trigger: 'blur' }, + { validator: rule.validatorNameCn, trigger: 'blur'} + ] + }, + { + label: '键', + prop: 'publicKey', + rules: [ + { required: true, message: '请输入键', trigger: 'blur' }, + { validator: rule.validatorKey, trigger: 'blur'}, + { validator: validateParam, trigger: 'blur'}, + ] + + }, + { + label: '值', + overHidden: true, + prop: 'publicValue', + rules: [ + { required: true, message: '请输入值', trigger: 'blur' } + ] + }, + { + label: '编码', + prop: 'validateCode' + }, + { + label: '类型', + prop: 'systemFlag', + type: 'select', + dicUrl: '/admin/dict/type/dict_type', + rules: [{ + required: true, + message: '请输入类型', + trigger: 'blur' + }], + search: true + }, + { + label: '状态', + prop: 'status', + width: 80, + type: 'select', + dicUrl: '/admin/dict/type/status_type', + rules: [ + { required: true, message: '请输入值', trigger: 'blur' } + ] + }, + { + label: '类型', + prop: 'publicType', + width: 80, + type: 'select', + dicUrl: '/admin/dict/type/param_type', + rules: [{ + required: true, + message: '请选择类型', + trigger: 'blur' + }] + } + // 省略 ... + ] +} diff --git a/src/util/util.js b/src/util/util.js index f8b61cb6a89e7ecaeda2810def67ab28b551c65b..1e2352b06e4b1c829f65fd47fc2e5da4be877616 100644 --- a/src/util/util.js +++ b/src/util/util.js @@ -1,328 +1,328 @@ -import {validatenull} from "./validate"; -import request from "@/router/axios"; -import * as CryptoJS from "crypto-js"; - -// 表单序列化 -export const serialize = data => { - let list = []; - Object.keys(data).forEach(ele => { - list.push(`${ele}=${data[ele]}`); - }); - return list.join("&"); -}; -export const getObjType = obj => { - var toString = Object.prototype.toString; - var map = { - "[object Boolean]": "boolean", - "[object Number]": "number", - "[object String]": "string", - "[object Function]": "function", - "[object Array]": "array", - "[object Date]": "date", - "[object RegExp]": "regExp", - "[object Undefined]": "undefined", - "[object Null]": "null", - "[object Object]": "object" - }; - if (obj instanceof Element) { - return "element"; - } - return map[toString.call(obj)]; -}; -/** - * 对象深拷贝 - */ -export const deepClone = data => { - var type = getObjType(data); - var obj; - if (type === "array") { - obj = []; - } else if (type === "object") { - obj = {}; - } else { - // 不再具有下一层次 - return data; - } - if (type === "array") { - for (var i = 0, len = data.length; i < len; i++) { - obj.push(deepClone(data[i])); - } - } else if (type === "object") { - for (var key in data) { - obj[key] = deepClone(data[key]); - } - } - return obj; -}; -/** - * 判断路由是否相等 - */ -export const diff = (obj1, obj2) => { - delete obj1.close; - var o1 = obj1 instanceof Object; - var o2 = obj2 instanceof Object; - if (!o1 || !o2) { - /* 判断不是对象 */ - return obj1 === obj2; - } - - if (Object.keys(obj1).length !== Object.keys(obj2).length) { - return false; - // Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如:数组返回下表:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2; - } - - for (var attr in obj1) { - var t1 = obj1[attr] instanceof Object; - var t2 = obj2[attr] instanceof Object; - if (t1 && t2) { - return diff(obj1[attr], obj2[attr]); - } else if (obj1[attr] !== obj2[attr]) { - return false; - } - } - return true; -}; -/** - * 设置灰度模式 - */ -export const toggleGrayMode = status => { - if (status) { - document.body.className = document.body.className + " grayMode"; - } else { - document.body.className = document.body.className.replace(" grayMode", ""); - } -}; -/** - * 设置主题 - */ -export const setTheme = name => { - document.body.className = name; -}; - -/** - *加密处理 - */ -export const encryption = params => { - let {data, type, param, key} = params; - const result = JSON.parse(JSON.stringify(data)); - if (type === "Base64") { - param.forEach(ele => { - result[ele] = btoa(result[ele]); - }); - } else { - param.forEach(ele => { - var data = result[ele]; - key = CryptoJS.enc.Latin1.parse(key); - var iv = key; - // 加密 - var encrypted = CryptoJS.AES.encrypt(data, key, { - iv: iv, - mode: CryptoJS.mode.CFB, - padding: CryptoJS.pad.NoPadding - }); - result[ele] = encrypted.toString(); - }); - } - return result; -}; -/** - * 浏览器判断是否全屏 - */ -export const fullscreenToggel = () => { - if (fullscreenEnable()) { - exitFullScreen(); - } else { - reqFullScreen(); - } -}; -/** - * esc监听全屏 - */ -export const listenfullscreen = callback => { - function listen() { - callback(); - } - - document.addEventListener("fullscreenchange", function () { - listen(); - }); - document.addEventListener("mozfullscreenchange", function () { - listen(); - }); - document.addEventListener("webkitfullscreenchange", function () { - listen(); - }); - document.addEventListener("msfullscreenchange", function () { - listen(); - }); -}; -/** - * 浏览器判断是否全屏 - */ -export const fullscreenEnable = () => { - return ( - document.isFullScreen || - document.mozIsFullScreen || - document.webkitIsFullScreen - ); -}; - -/** - * 浏览器全屏 - */ -export const reqFullScreen = () => { - if (document.documentElement.requestFullScreen) { - document.documentElement.requestFullScreen(); - } else if (document.documentElement.webkitRequestFullScreen) { - document.documentElement.webkitRequestFullScreen(); - } else if (document.documentElement.mozRequestFullScreen) { - document.documentElement.mozRequestFullScreen(); - } -}; -/** - * 浏览器退出全屏 - */ -export const exitFullScreen = () => { - if (document.documentElement.requestFullScreen) { - document.exitFullScreen(); - } else if (document.documentElement.webkitRequestFullScreen) { - document.webkitCancelFullScreen(); - } else if (document.documentElement.mozRequestFullScreen) { - document.mozCancelFullScreen(); - } -}; -/** - * 递归寻找子类的父类 - */ - -export const findParent = (menu, id) => { - for (let i = 0; i < menu.length; i++) { - if (menu[i].children.length != 0) { - for (let j = 0; j < menu[i].children.length; j++) { - if (menu[i].children[j].id == id) { - return menu[i]; - } else { - if (menu[i].children[j].children.length != 0) { - return findParent(menu[i].children[j].children, id); - } - } - } - } - } -}; - -/** - * 动态插入css - */ - -export const loadStyle = url => { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - const head = document.getElementsByTagName("head")[0]; - head.appendChild(link); -}; -/** - * 判断路由是否相等 - */ -export const isObjectValueEqual = (a, b) => { - let result = true; - Object.keys(a).forEach(ele => { - const type = typeof a[ele]; - if (type === "string" && a[ele] !== b[ele]) result = false; - else if ( - type === "object" && - JSON.stringify(a[ele]) !== JSON.stringify(b[ele]) - ) - result = false; - }); - return result; -}; -/** - * 根据字典的value显示label - */ -export const findByvalue = (dic, value) => { - let result = ""; - if (validatenull(dic)) return value; - if ( - typeof value === "string" || - typeof value === "number" || - typeof value === "boolean" - ) { - let index = 0; - index = findArray(dic, value); - if (index != -1) { - result = dic[index].label; - } else { - result = value; - } - } else if (value instanceof Array) { - result = []; - let index = 0; - value.forEach(ele => { - index = findArray(dic, ele); - if (index != -1) { - result.push(dic[index].label); - } else { - result.push(value); - } - }); - result = result.toString(); - } - return result; -}; -/** - * 根据字典的value查找对应的index - */ -export const findArray = (dic, value) => { - for (let i = 0; i < dic.length; i++) { - if (dic[i].value == value) { - return i; - } - } - return -1; -}; -/** - * 生成随机len位数字 - */ -export const randomLenNum = (len, date) => { - let random = ""; - random = Math.ceil(Math.random() * 100000000000000) - .toString() - .substr(0, len || 4); - if (date) random = random + Date.now(); - return random; -}; - -/** - * - * @param url 目标下载接口 - * @param query 查询参数 - * @param fileName 文件名称 - * @returns {*} - */ -export function downBlobFile(url, query, fileName) { - return request({ - url: url, - method: "get", - responseType: "blob", - params: query - }).then(response => { - // 处理返回的文件流 - const blob = response.data; - if (blob && blob.size === 0) { - this.$notify.error("内容为空,无法下载"); - return; - } - const link = document.createElement("a"); - link.href = URL.createObjectURL(blob); - link.download = fileName; - document.body.appendChild(link); - link.click(); - window.setTimeout(function () { - URL.revokeObjectURL(blob); - document.body.removeChild(link); - }, 0); - }); -} +import {validatenull} from "./validate"; +import request from "@/router/axios"; +import * as CryptoJS from "crypto-js"; + +// 表单序列化 +export const serialize = data => { + let list = []; + Object.keys(data).forEach(ele => { + list.push(`${ele}=${data[ele]}`); + }); + return list.join("&"); +}; +export const getObjType = obj => { + var toString = Object.prototype.toString; + var map = { + "[object Boolean]": "boolean", + "[object Number]": "number", + "[object String]": "string", + "[object Function]": "function", + "[object Array]": "array", + "[object Date]": "date", + "[object RegExp]": "regExp", + "[object Undefined]": "undefined", + "[object Null]": "null", + "[object Object]": "object" + }; + if (obj instanceof Element) { + return "element"; + } + return map[toString.call(obj)]; +}; +/** + * 对象深拷贝 + */ +export const deepClone = data => { + var type = getObjType(data); + var obj; + if (type === "array") { + obj = []; + } else if (type === "object") { + obj = {}; + } else { + // 不再具有下一层次 + return data; + } + if (type === "array") { + for (var i = 0, len = data.length; i < len; i++) { + obj.push(deepClone(data[i])); + } + } else if (type === "object") { + for (var key in data) { + obj[key] = deepClone(data[key]); + } + } + return obj; +}; +/** + * 判断路由是否相等 + */ +export const diff = (obj1, obj2) => { + delete obj1.close; + var o1 = obj1 instanceof Object; + var o2 = obj2 instanceof Object; + if (!o1 || !o2) { + /* 判断不是对象 */ + return obj1 === obj2; + } + + if (Object.keys(obj1).length !== Object.keys(obj2).length) { + return false; + // Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如:数组返回下表:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2; + } + + for (var attr in obj1) { + var t1 = obj1[attr] instanceof Object; + var t2 = obj2[attr] instanceof Object; + if (t1 && t2) { + return diff(obj1[attr], obj2[attr]); + } else if (obj1[attr] !== obj2[attr]) { + return false; + } + } + return true; +}; +/** + * 设置灰度模式 + */ +export const toggleGrayMode = status => { + if (status) { + document.body.className = document.body.className + " grayMode"; + } else { + document.body.className = document.body.className.replace(" grayMode", ""); + } +}; +/** + * 设置主题 + */ +export const setTheme = name => { + document.body.className = name; +}; + +/** + *加密处理 + */ +export const encryption = params => { + let {data, type, param, key} = params; + const result = JSON.parse(JSON.stringify(data)); + if (type === "Base64") { + param.forEach(ele => { + result[ele] = btoa(result[ele]); + }); + } else { + param.forEach(ele => { + var data = result[ele]; + key = CryptoJS.enc.Latin1.parse(key); + var iv = key; + // 加密 + var encrypted = CryptoJS.AES.encrypt(data, key, { + iv: iv, + mode: CryptoJS.mode.CFB, + padding: CryptoJS.pad.NoPadding + }); + result[ele] = encrypted.toString(); + }); + } + return result; +}; +/** + * 浏览器判断是否全屏 + */ +export const fullscreenToggel = () => { + if (fullscreenEnable()) { + exitFullScreen(); + } else { + reqFullScreen(); + } +}; +/** + * esc监听全屏 + */ +export const listenfullscreen = callback => { + function listen() { + callback(); + } + + document.addEventListener("fullscreenchange", function () { + listen(); + }); + document.addEventListener("mozfullscreenchange", function () { + listen(); + }); + document.addEventListener("webkitfullscreenchange", function () { + listen(); + }); + document.addEventListener("msfullscreenchange", function () { + listen(); + }); +}; +/** + * 浏览器判断是否全屏 + */ +export const fullscreenEnable = () => { + return ( + document.isFullScreen || + document.mozIsFullScreen || + document.webkitIsFullScreen + ); +}; + +/** + * 浏览器全屏 + */ +export const reqFullScreen = () => { + if (document.documentElement.requestFullScreen) { + document.documentElement.requestFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + document.documentElement.webkitRequestFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.documentElement.mozRequestFullScreen(); + } +}; +/** + * 浏览器退出全屏 + */ +export const exitFullScreen = () => { + if (document.documentElement.requestFullScreen) { + document.exitFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + document.webkitCancelFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.mozCancelFullScreen(); + } +}; +/** + * 递归寻找子类的父类 + */ + +export const findParent = (menu, id) => { + for (let i = 0; i < menu.length; i++) { + if (menu[i].children.length != 0) { + for (let j = 0; j < menu[i].children.length; j++) { + if (menu[i].children[j].id == id) { + return menu[i]; + } else { + if (menu[i].children[j].children.length != 0) { + return findParent(menu[i].children[j].children, id); + } + } + } + } + } +}; + +/** + * 动态插入css + */ + +export const loadStyle = url => { + const link = document.createElement("link"); + link.type = "text/css"; + link.rel = "stylesheet"; + link.href = url; + const head = document.getElementsByTagName("head")[0]; + head.appendChild(link); +}; +/** + * 判断路由是否相等 + */ +export const isObjectValueEqual = (a, b) => { + let result = true; + Object.keys(a).forEach(ele => { + const type = typeof a[ele]; + if (type === "string" && a[ele] !== b[ele]) result = false; + else if ( + type === "object" && + JSON.stringify(a[ele]) !== JSON.stringify(b[ele]) + ) + result = false; + }); + return result; +}; +/** + * 根据字典的value显示label + */ +export const findByvalue = (dic, value) => { + let result = ""; + if (validatenull(dic)) return value; + if ( + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" + ) { + let index = 0; + index = findArray(dic, value); + if (index != -1) { + result = dic[index].label; + } else { + result = value; + } + } else if (value instanceof Array) { + result = []; + let index = 0; + value.forEach(ele => { + index = findArray(dic, ele); + if (index != -1) { + result.push(dic[index].label); + } else { + result.push(value); + } + }); + result = result.toString(); + } + return result; +}; +/** + * 根据字典的value查找对应的index + */ +export const findArray = (dic, value) => { + for (let i = 0; i < dic.length; i++) { + if (dic[i].value == value) { + return i; + } + } + return -1; +}; +/** + * 生成随机len位数字 + */ +export const randomLenNum = (len, date) => { + let random = ""; + random = Math.ceil(Math.random() * 100000000000000) + .toString() + .substr(0, len || 4); + if (date) random = random + Date.now(); + return random; +}; + +/** + * + * @param url 目标下载接口 + * @param query 查询参数 + * @param fileName 文件名称 + * @returns {*} + */ +export function downBlobFile(url, query, fileName) { + return request({ + url: url, + method: "get", + responseType: "blob", + params: query + }).then(response => { + // 处理返回的文件流 + const blob = response.data; + if (blob && blob.size === 0) { + this.$notify.error("内容为空,无法下载"); + return; + } + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = fileName; + document.body.appendChild(link); + link.click(); + window.setTimeout(function () { + URL.revokeObjectURL(blob); + document.body.removeChild(link); + }, 0); + }); +} diff --git a/src/util/validateRules.js b/src/util/validateRules.js new file mode 100644 index 0000000000000000000000000000000000000000..ede0f4bb90a4cd83b83ec2e02407585943a92b75 --- /dev/null +++ b/src/util/validateRules.js @@ -0,0 +1,48 @@ +/** + * @desc [自定义校验规则] + * @example + * import { validateRule } from "@/utils/validateRules"; + * rules: [ + * { validator: validateRule.emailValue, trigger: 'blur'} + * ] + */ + +export const rule = { + /** + * 校验 请输入中文、英文、数字包括下划线 + * 名称校验 + */ + validatorNameCn(rule, value, callback) { + let acount = /^[\u4E00-\u9FA5A-Za-z0-9_]+$/ + if (value && (!(acount).test(value))) { + callback(new Error('请输入中文、英文、数字包括下划线')) + } else { + callback() + } + }, + /** + * 校验 请输入中文、英文、数字包括下划线 + * 名称校验 + */ + validatorKey(rule, value, callback) { + let acount = /^[A-Z_]+$/ + if (value && (!(acount).test(value))) { + callback(new Error('请输入大写英文、下划线')) + } else { + callback() + } + }, + + /** + * 校验首尾空白字符的正则表达式 + * + */ + checkSpace(rule, value, callback) { + let longrg = /[^\s]+$/; + if(!longrg.test(value)){ + callback(new Error('请输入非空格信息')); + } else { + callback(); + } + }, +} diff --git a/src/views/admin/param/index.vue b/src/views/admin/param/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..c790e024107891e6d2083549696c4d475785b2f4 --- /dev/null +++ b/src/views/admin/param/index.vue @@ -0,0 +1,166 @@ + + + +