Compare commits

..

No commits in common. '07db23c09e234ac55c8e9fe3f0593f58054d2671' and '714b4ad4ab164e29bff4cde63bcd112e8b1acc63' have entirely different histories.

@ -1,40 +1,14 @@
// 引入 CryptoJS 库 import CryptoJS from 'crypto-js'
// CryptoJS 是一个流行的 JavaScript 加密库,提供多种加密算法, // 加密
// 包括 AES高级加密标准。它允许开发者在客户端对数据进行加密和解密。 const keyStr = '-mall4j-password' // 解密用的key
import CryptoJS from 'crypto-js'; export function encrypt (word) {
const time = Date.now()
// 定义用于加密和解密的密钥
// keyStr 是一个固定的字符串,作为加密和解密时使用的密钥。 const key = CryptoJS.enc.Utf8.parse(keyStr)
// 注意:在实际应用中,应确保密钥的安全性,避免硬编码或泄露。 const srcs = CryptoJS.enc.Utf8.parse(time + word) // 加密方式: 时间戳 + 密文
const keyStr = '-mall4j-password'; // 解密用的key
/**
* 加密函数
* @param {string} word - 需要加密的明文字符串
* @returns {string} - 返回经过 AES 加密后的密文字符串
*/
export function encrypt(word) {
// 获取当前时间戳,用于生成唯一的加密内容前缀
// 这有助于防止相同的明文产生相同的密文,增加了安全性。
const time = Date.now();
// 将密钥字符串转换为字节数组 (WordArray),以便用于加密操作
// 使用 Utf8 编码来解析密钥字符串确保正确处理非ASCII字符。
const key = CryptoJS.enc.Utf8.parse(keyStr);
// 将时间戳与需要加密的文本连接起来,并将其转换为字节数组
// 同样使用 Utf8 编码来解析字符串,以确保正确处理所有字符。
const srcs = CryptoJS.enc.Utf8.parse(time + word); // 加密方式: 时间戳 + 密文
// 使用 AES 算法进行加密
// mode: ECB 表示使用电子密码本模式,这是一种简单的加密模式,但不适合加密大量数据或要求高安全性的场景。
// padding: Pkcs7 表示使用 PKCS#7 填充方案这是AES加密推荐的填充方式。
const encrypted = CryptoJS.AES.encrypt(srcs, key, { const encrypted = CryptoJS.AES.encrypt(srcs, key, {
mode: CryptoJS.mode.ECB, mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7 padding: CryptoJS.pad.Pkcs7
}); })
return encrypted.toString()
// 将加密后的结果转换为 Base64 字符串返回
// 这样可以方便地在网络上传输或存储加密数据。
return encrypted.toString();
} }

@ -1,44 +1,19 @@
/** // 防抖 防止表单重复提交
* 防抖函数 (Debounce Function)
* 用于限制某个函数在短时间内频繁触发时只执行一次
* 这对于防止表单重复提交搜索框输入触发等场景非常有用
* 因为它可以确保即使用户快速连续点击按钮或输入内容
* 相关操作也只会被执行一次直到经过一段设定的时间间隔后才会允许再次触发
*
* @param {Function} fn - 要防抖处理的目标函数
* @param {number} t - 可选参数指定等待的时间间隔毫秒默认为1000ms
* @returns {Function} - 返回一个新的函数该函数具有防抖行为
*/
export const Debounce = (fn, t) => { export const Debounce = (fn, t) => {
// 设置默认延迟时间为1000毫秒1秒 const delay = t || 1000
const delay = t || 1000; let timer
// 定义一个变量来保存定时器ID用于清除之前的定时器
let timer;
// 返回一个新函数,这个函数会替代原始函数被调用
return function () { return function () {
// 保存当前函数调用的所有参数和上下文 const args = arguments
const args = arguments;
const context = this;
// 如果之前有未完成的定时器,则清除它
if (timer) { if (timer) {
clearTimeout(timer); clearTimeout(timer)
} }
// 检查是否是首次调用或上一次调用已经超过了设定的时间间隔 const callNow = !timer
const callNow = !timer;
// 设置一个新的定时器在指定的延迟时间后将timer置为空
// 置空是为了下一次调用时能够正确判断是否立即执行目标函数
timer = setTimeout(() => { timer = setTimeout(() => {
timer = null; timer = null
}, delay); }, delay)
// 如果是首次调用或者上一次调用已经超过了设定的时间间隔,则立即执行目标函数 if (callNow) fn.apply(this, args)
if (callNow) {
fn.apply(context, args);
} }
}; }
};

@ -1,202 +1,190 @@
// 引入必要的库和模块 import axios from 'axios'
import axios from 'axios'; // 用于发起HTTP请求 import qs from 'qs'
import qs from 'qs'; // 用于序列化查询参数 import cookie from 'vue-cookies'
import cookie from 'vue-cookies'; // 用于管理cookie import router from '@/router'
import router from '@/router'; // 项目路由实例 import merge from 'lodash/merge'
import merge from 'lodash/merge'; // 用于合并对象 import { clearLoginInfo } from '@/utils'
import { clearLoginInfo } from '@/utils'; // 清除登录信息的工具函数 import { ElMessage } from 'element-plus'
import { ElMessage } from 'element-plus'; // Element Plus的消息提示组件
// 创建一个自定义的axios实例
const http = axios.create({ const http = axios.create({
timeout: 1000 * 30, // 设置请求超时时间为30秒 timeout: 1000 * 30,
withCredentials: true, // 允许跨域请求时携带凭证如Cookie withCredentials: true,
headers: { headers: {
'Content-Type': 'application/json; charset=utf-8' // 默认设置请求头为JSON格式 'Content-Type': 'application/json; charset=utf-8'
} }
}); })
/** /**
* 请求拦截器 * 请求拦截
* 在每个请求发送之前执行可以在此处添加通用的请求头或处理请求参数等
*/ */
http.interceptors.request.use( http.interceptors.request.use(
config => { config => {
// 如果存在Authorization token则添加到请求头中 config.headers.Authorization = cookie.get('Authorization') // 请求头带上token
config.headers.Authorization = cookie.get('Authorization'); // 只针对get方式进行序列化
if (config.method === 'get' || config.method === 'GET') {
// 对GET请求进行参数序列化支持数组格式重复参数 config.paramsSerializer = function (params) {
if (config.method.toLowerCase() === 'get') { return qs.stringify(params, { arrayFormat: 'repeat' })
config.paramsSerializer = params => qs.stringify(params, { arrayFormat: 'repeat' });
} }
}
return config; return config
}, },
error => Promise.reject(error) // 捕获请求错误并返回拒绝的Promise error => {
); return Promise.reject(error)
}
)
/** /**
* 响应拦截器 * 响应拦截
* 在接收到响应数据后执行可以根据响应状态码或自定义业务逻辑来处理响应
*/ */
http.interceptors.response.use( http.interceptors.response.use(
response => { response => {
// 直接返回blob类型的响应数据 // blob 格式处理
if (response.request.responseType === 'blob') { if (response.request.responseType === 'blob') {
return response; return response
} }
const res = response.data
const res = response.data; // 00000 请求成功
if (res.code === '00000' || res.code === 'A00002') {
// 根据不同的响应码执行相应的操作 return res
switch (res.code) { }
case '00000': // 成功响应 // A00001 用于直接显示提示用户的错误,内容由输入决定
case 'A00002': // 特定成功的响应码 if (res.code === 'A00001') {
return res;
case 'A00001': // 用户级错误消息
ElMessage({ ElMessage({
message: res.msg || res.data || 'Error', message: res.msg || res.data || 'Error',
type: 'error', type: 'error',
duration: 1500 duration: 1.5 * 1000
}); })
return Promise.reject(res); return Promise.reject(res)
}
case 'A00004': // 未授权 // A00004 未授权
clearLoginInfo(); if (res.code === 'A00004') {
router.push({ name: 'login' }); clearLoginInfo()
break; router.push({ name: 'login' })
}
case 'A00005': // 服务器异常 // A00005 服务器异常
console.error(`接口地址: ${response.config.url.replace(import.meta.env.VITE_APP_BASE_API, '')}`, '\n', `异常信息: ${res}`); if (res.code === 'A00005') {
// eslint-disable-next-line no-console
console.error('============== 请求异常 ==============', '\n', `接口地址: ${response.config.url.replace(import.meta.env.VITE_APP_BASE_API, '')}`, '\n', `异常信息: ${res}`, '\n', '============== 请求异常 end ==========')
ElMessage({ ElMessage({
message: '服务器出了点小差,请稍后再试', message: '服务器出了点小差,请稍后再试',
type: 'error', type: 'error',
duration: 1500, duration: 1.5 * 1000,
customClass: 'element-error-message-zindex' customClass: 'element-error-message-zindex'
}); })
return Promise.reject(res); return Promise.reject(res)
default:
return res;
} }
}, },
error => { error => {
// 处理不同HTTP状态码的错误响应 // eslint-disable-next-line no-console
console.log('请求失败:', error.response); console.log('========请求失败========', '\n', error.response, '\n', '========请求失败 end========')
const status = error.response?.status; switch (error.response.status) {
case 400:
switch (status) {
case 400: // 客户端错误
ElMessage({ ElMessage({
message: error.response.data, message: error.response.data,
type: 'error', type: 'error',
duration: 1500, duration: 1500,
customClass: 'element-error-message-zindex' customClass: 'element-error-message-zindex'
}); })
break; break
case 401:
case 401: // 未授权 clearLoginInfo()
clearLoginInfo(); router.push({ name: 'login' })
router.push({ name: 'login' }); break
break; case 405:
case 405: // 方法不允许
ElMessage({ ElMessage({
message: 'http请求方式有误', message: 'http请求方式有误',
type: 'error', type: 'error',
duration: 1500, duration: 1500,
customClass: 'element-error-message-zindex' customClass: 'element-error-message-zindex'
}); })
break; break
case 500:
case 500: // 服务器内部错误
ElMessage({ ElMessage({
message: '服务器出了点小差,请稍后再试', message: '服务器出了点小差,请稍后再试',
type: 'error', type: 'error',
duration: 1500, duration: 1500,
customClass: 'element-error-message-zindex' customClass: 'element-error-message-zindex'
}); })
break; break
case 501:
case 501: // 服务器不支持当前请求功能
ElMessage({ ElMessage({
message: '服务器不支持当前请求所需要的某个功能', message: '服务器不支持当前请求所需要的某个功能',
type: 'error', type: 'error',
duration: 1500, duration: 1500,
customClass: 'element-error-message-zindex' customClass: 'element-error-message-zindex'
}); })
break; break
} }
return Promise.reject(error)
return Promise.reject(error);
} }
); )
/** /**
* 请求地址处理 * 请求地址处理
* @param {string} actionName - API方法名称 * @param {*} actionName action方法名称
* @returns {string} - 完整的API请求URL
*/ */
http.adornUrl = actionName => import.meta.env.VITE_APP_BASE_API + actionName; http.adornUrl = actionName => {
return import.meta.env.VITE_APP_BASE_API + actionName
}
/** /**
* IM请求地址处理 * im请求地址处理
* @param {string} actionName - IM API方法名称 * @param {*} actionName action方法名称
* @returns {string} - 完整的IM API请求URL
*/ */
http.adornImUrl = actionName => import.meta.env.VITE_APP_IM_API + actionName; http.adornImUrl = actionName => {
return import.meta.env.VITE_APP_IM_API + actionName
}
/** /**
* IM WebSocket请求地址处理 * im ws 请求地址处理
* @param {string} actionName - WebSocket IM API方法名称 * @param {*} actionName action方法名称
* @returns {string} - 完整的WebSocket IM API请求URL
*/ */
http.adornWsImUrl = actionName => import.meta.env.VITE_APP_WS_IM_API + actionName; http.adornWsImUrl = actionName => {
return import.meta.env.VITE_APP_WS_IM_API + actionName
}
/** /**
* GET请求参数处理 * get请求参数处理
* @param {Object} [params={}] - 参数对象 * @param {*} params 参数对象
* @param {boolean} [openDefultParams=true] - 是否开启默认参数 * @param {*} openDefultParams 是否开启默认参数?
* @returns {Object} - 处理后的参数对象
*/ */
http.adornParams = (params = {}, openDefultParams = true) => { http.adornParams = (params = {}, openDefultParams = true) => {
const defaults = { t: Date.now() }; // 添加时间戳以防止缓存 const defaults = {
return openDefultParams ? merge(defaults, params) : params; t: Date.now()
}; }
return openDefultParams ? merge(defaults, params) : params
}
/** /**
* POST请求数据处理 * post请求数据处理
* @param {Object} [data={}] - 数据对象 * @param {*} data 数据对象
* @param {boolean} [openDefultdata=true] - 是否开启默认数据 * @param {*} openDefultdata 是否开启默认数据?
* @param {string} [contentType='json'] - 数据格式'json' 'form' * @param {*} contentType 数据格式
* @returns {string|FormData} - 处理后的数据 * json: 'application/json; charset=utf-8'
* form: 'application/x-www-form-urlencoded; charset=utf-8'
*/ */
http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => { http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => {
const defaults = { t: Date.now() }; const defaults = {
data = openDefultdata ? merge(defaults, data) : data; t: Date.now()
}
// 根据contentType决定如何序列化数据 data = openDefultdata ? merge(defaults, data) : data
return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data); return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
}; }
/**
* 文件上传函数
* @param {string} url - 上传文件的目标URL
* @param {File} file - 要上传的文件
* @returns {Promise} - 返回上传结果的Promise
*/
const uploadFile = function (url, file) { const uploadFile = function (url, file) {
const config = { const config = {
// 添加请求头
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
Authorization: cookie.get('Authorization') // 添加token到请求头 Authorization: cookie.get('Authorization') // 请求头带上token
} }
}; }
const param = new FormData(); const param = new FormData()
param.append('file', file); // 向FormData对象添加文件 // 通过append向form对象添加数据
return axios.post(url, param, config); param.append('file', file)
}; return axios.post(url, param, config)
}
export default http;
export { uploadFile }; export default http
export { uploadFile }

@ -1,150 +1,109 @@
import cookie from 'vue-cookies'; // 用于管理浏览器中的cookie import cookie from 'vue-cookies'
import router from '@/router'; // 引入Vue Router实例 import router from '@/router'
/** /**
* 获取UUID通用唯一识别码 * 获取uuid
* @returns {string} - 返回一个随机生成的UUID字符串
*/ */
export function getUUID() { export function getUUID () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
// 使用位运算生成随机数,并根据'x'或'y'的不同生成不同的值 return (c === 'x' ? (Math.random() * 16) | 0 : 'r&0x3' | '0x8').toString(16)
return (c === 'x' ? (Math.random() * 16) | 0 : ('r&0x3' | '0x8')).toString(16); })
});
} }
/** /**
* 检查用户是否有特定权限 * 是否有权限
* @param {string} key - 权限标识符 * @param {*} key
* @returns {boolean} - 如果用户有此权限则返回true否则返回false
*/ */
export function isAuth(key) { export function isAuth (key) {
const authorities = JSON.parse(sessionStorage.getItem('Authorities') || '[]'); // 尝试从sessionStorage中获取用户权限列表 const authorities = JSON.parse(sessionStorage.getItem('Authorities') || '[]')
if (authorities.length) { if (authorities.length) {
for (const i in authorities) { for (const i in authorities) {
const element = authorities[i]; const element = authorities[i]
if (element === key) { if (element === key) {
return true; // 如果找到匹配的权限则返回true return true
} }
} }
} }
return false; // 如果没有找到匹配的权限则返回false return false
} }
/** /**
* 清除登录信息 * 清除登录信息
*/ */
export function clearLoginInfo() { export function clearLoginInfo () {
cookie.remove('Authorization'); // 移除存储在cookie中的授权token cookie.remove('Authorization')
router.options.isAddDynamicMenuRoutes = false; // 禁用动态路由添加功能 router.options.isAddDynamicMenuRoutes = false
} }
/** /**
* 树形数据转换 * 树形数据转换
* 将扁平的数据结构转换为树形结构 * @param {*} data
* @param {Array} data - 扁平化的数据数组 * @param {*} id
* @param {string} [id='id'] - 数据项ID字段名默认为'id' * @param {*} pid
* @param {string} [pid='parentId'] - 数据项父级ID字段名默认为'parentId'
* @returns {Array} - 转换后的树形数据结构
*/ */
export function treeDataTranslate(data, id = 'id', pid = 'parentId') { export function treeDataTranslate (data, id = 'id', pid = 'parentId') {
const res = []; // 存储根节点 const res = []
const temp = {}; // 临时对象,用于快速查找子节点 const temp = {}
// 首先将所有元素存入temp对象中以它们的ID作为键
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
temp[data[i][id]] = data[i]; temp[data[i][id]] = data[i]
} }
// 再次遍历data数组构建树结构
for (let k = 0; k < data.length; k++) { for (let k = 0; k < data.length; k++) {
// 如果当前元素有父级元素且不是自身,则将其作为子元素加入到父元素下
if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) { if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
if (!temp[data[k][pid]].children) { if (!temp[data[k][pid]].children) {
temp[data[k][pid]].children = []; temp[data[k][pid]].children = []
} }
if (!temp[data[k][pid]]._level) { if (!temp[data[k][pid]]._level) {
temp[data[k][pid]]._level = 1; temp[data[k][pid]]._level = 1
} }
data[k]._level = temp[data[k][pid]]._level + 1; data[k]._level = temp[data[k][pid]]._level + 1
temp[data[k][pid]].children.push(data[k]); temp[data[k][pid]].children.push(data[k])
} else { } else {
// 如果没有父级元素,则认为是根节点,直接加入到结果数组中 res.push(data[k])
res.push(data[k]);
} }
} }
return res
return res;
} }
/** function idListFromTree (data, val, res = [], id = 'id', children = 'children') {
* 递归函数从树结构中提取指定ID路径
* @param {Array} data - 树形数据结构
* @param {any} val - 查找的目标ID
* @param {Array} [res=[]] - 存储找到的ID路径
* @param {string} [id='id'] - 数据项ID字段名默认为'id'
* @param {string} [children='children'] - 数据项子元素字段名默认为'children'
* @returns {boolean} - 是否找到了目标ID
*/
function idListFromTree(data, val, res = [], id = 'id', children = 'children') {
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const element = data[i]; const element = data[i]
if (element[children]) {
// 递归处理子元素 if (idListFromTree(element[children], val, res, id, children)) {
if (element[children] && idListFromTree(element[children], val, res, id, children)) { res.push(element[id])
res.push(element[id]); // 当找到目标时将当前节点ID加入路径 return true
return true; }
} }
// 如果当前节点就是目标节点,直接加入路径并返回
if (element[id] === val) { if (element[id] === val) {
res.push(element[id]); res.push(element[id])
return true; return true
} }
} }
return false;
} }
/** /**
* 将数组中的parentId列表取出倒序排列 * 将数组中的parentId列表取出倒序排列
* @param {Array} data - 树形数据结构
* @param {any} val - 查找的目标ID
* @param {string} [id='id'] - 数据项ID字段名默认为'id'
* @param {string} [children='children'] - 数据项子元素字段名默认为'children'
* @returns {Array} - 倒序排列的ID路径
*/ */
export function idList(data, val, id = 'id', children = 'children') { // eslint-disable-next-line no-unused-vars
const res = []; export function idList (data, val, id = 'id', children = 'children') {
idListFromTree(data, val, res, id, children); // 调用递归函数查找ID路径 const res = []
return res.reverse(); // 返回倒序排列的结果 idListFromTree(data, val, res, id)
return res
} }
/** /**
* 文件地址校验与处理 * 文件地址校验
* @param {string|Array} fileUrl - 获取到的文件路径或文件路径数组 * @param fileUrl 获取到的文件路径
* @returns {string|Array} - 处理后的文件路径或路径数组
*/ */
export function checkFileUrl(fileUrl) { export function checkFileUrl (fileUrl) {
if (fileUrl === '') return ''; // 如果输入为空字符串,直接返回空字符串 if (fileUrl === '') return ''
const baseUrl = import.meta.env.VITE_APP_RESOURCES_URL
const baseUrl = import.meta.env.VITE_APP_RESOURCES_URL; // 获取资源基础URL // 适配el-image 图片组件预览功能
if (fileUrl && typeof fileUrl === 'object') {
// 如果fileUrl是一个对象如el-image组件传递的对象则递归处理每个元素 // eslint-disable-next-line no-return-assign
if (fileUrl && typeof fileUrl === 'object' && !Array.isArray(fileUrl)) { return fileUrl.map(el => el = checkFileUrl(el))
return Object.keys(fileUrl).reduce((acc, key) => { } else {
acc[key] = checkFileUrl(fileUrl[key]); if (fileUrl && fileUrl.indexOf('http') === -1) {
return acc; return baseUrl + fileUrl
}, {}); } else {
} return fileUrl
// 如果fileUrl是数组则映射处理每个元素
if (Array.isArray(fileUrl)) {
return fileUrl.map(el => checkFileUrl(el));
} }
// 对于单个文件路径如果它不是绝对路径则拼接基础URL
if (fileUrl && typeof fileUrl === 'string' && fileUrl.indexOf('http') === -1) {
return baseUrl + fileUrl;
} }
return fileUrl; // 如果已经是绝对路径或无效路径,则直接返回原值
} }

@ -1,35 +1,102 @@
/**
* 单位选项列表
* 此数组包含了多个对象每个对象代表一个可能的商品单位
* 用于在用户界面中提供选择比如商品库存管理订单录入等场景
* 每个对象都有两个属性
* - label: 显示给用户的文本标签
* - value: 实际存储或传递的数据值
*/
export const unitOption = [ export const unitOption = [
{ label: '件', value: '件' }, // 通用计数单位 {
{ label: '盒', value: '盒' }, // 适用于装在盒子中的物品 lable: '件',
{ label: '箱', value: '箱' }, // 大量物品的包装单位 value: '件'
{ label: '包', value: '包' }, // 适用于包裹或小袋装的物品 },
{ label: '瓶', value: '瓶' }, // 适用于液体或粉末状物品 {
{ label: '只', value: '只' }, // 适用于单个独立物品,如手套、袜子等 lable: '盒',
{ label: '千克', value: '千克' }, // 重量单位1000克 value: '盒'
{ label: '克', value: '克' }, // 较小的重量单位 },
{ label: '斤', value: '斤' }, // 传统中国重量单位等于500克 {
{ label: '两', value: '两' }, // 传统中国重量单位等于50克 lable: '箱',
{ label: '双', value: '双' }, // 适用于成对物品,如鞋子、筷子等 value: '箱'
{ label: '套', value: '套' }, // 适用于一组或多件相关联的物品 },
{ label: '对', value: '对' }, // 适用于成对物品,类似“双” {
{ label: '块', value: '块' }, // 适用于固体物品,如巧克力、石头等 lable: '包',
{ label: '台', value: '台' }, // 适用于大型设备或机器 value: '包'
{ label: '本', value: '本' }, // 适用于书籍或其他装订成册的物品 },
{ label: '把', value: '把' }, // 适用于手持工具或武器 {
{ label: '码', value: '码' }, // 长度单位约等于0.9144米 lable: '瓶',
{ label: '捆', value: '捆' }, // 适用于捆绑在一起的物品 value: '瓶'
{ label: '提', value: '提' }, // 适用于手提袋或携带方便的物品 },
{ label: '杯', value: '杯' }, // 适用于饮品或小容量容器 {
{ label: '听', value: '听' }, // 适用于罐装食品或饮料 lable: '只',
{ label: '条', value: '条' }, // 适用于细长形物品,如鱼、香烟等 value: '只'
{ label: '副', value: '副' }, // 适用于眼镜、耳环等成对使用的物品 },
{ label: '顶', value: '顶' } // 适用于帽子、帐篷等覆盖物 {
]; lable: '千克',
value: '千克'
},
{
lable: '克',
value: '克'
},
{
lable: '斤',
value: '斤'
},
{
lable: '两',
value: '两'
},
{
lable: '双',
value: '双'
},
{
lable: '套',
value: '套'
},
{
lable: '对',
value: '对'
},
{
lable: '块',
value: '块'
},
{
lable: '台',
value: '台'
},
{
lable: '本',
value: '本'
},
{
lable: '把',
value: '把'
},
{
lable: '码',
value: '码'
},
{
lable: '捆',
value: '捆'
},
{
lable: '提',
value: '提'
},
{
lable: '杯',
value: '杯'
},
{
lable: '听',
value: '听'
},
{
lable: '条',
value: '条'
},
{
lable: '副',
value: '副'
},
{
lable: '顶',
value: '顶'
}
]

@ -1,69 +1,49 @@
/** /**
* 验证邮箱格式是否正确 * 邮箱
* @param {string} s - 要验证的字符串 * @param {*} s
* @returns {boolean} - 如果符合标准邮箱格式则返回true否则返回false
*/ */
export function isEmail(s) { export function isEmail (s) {
// 正则表达式用于匹配标准的电子邮件地址格式: return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
// - 用户名部分只能包含字母、数字、下划线或连字符
// - 域名部分同样只允许字母、数字、下划线或连字符
// - 域名后缀长度为2到3个字符并且可以有一个或两个层级例如.com, .co.uk
return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s);
} }
/** /**
* 验证手机号码格式是否正确 * 手机号码
* @param {string} s - 要验证的字符串 * @param {*} s
* @returns {boolean} - 如果符合中国大陆手机号码格式则返回true否则返回false
*/ */
export function isMobile(s) { export function isMobile (s) {
// 正则表达式用于匹配中国大陆的手机号码: return /^1[0-9]{10}$/.test(s)
// - 以1开头后面跟随10位数字
return /^1[0-9]{10}$/.test(s);
} }
/** /**
* 验证电话号码格式是否正确 * 电话号码
* @param {string} s - 要验证的字符串 * @param {*} s
* @returns {boolean} - 如果符合固定电话号码格式则返回true否则返回false
*/ */
export function isPhone(s) { export function isPhone (s) {
// 正则表达式用于匹配中国大陆的固定电话号码: return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
// - 可选区号3到4位数字用短横线分隔
// - 主号码由7到8位数字组成
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s);
} }
/** /**
* 验证URL地址格式是否正确 * URL地址
* @param {string} s - 要验证的字符串 * @param {*} s
* @returns {boolean} - 如果符合标准URL格式则返回true否则返回false
*/ */
export function isURL(s) { export function isURL (s) {
// 正则表达式用于匹配标准的URL地址 return /^http[s]?:\/\/.*/.test(s)
// - 开头必须是http:// 或 https://
// - 后面跟任意数量的字符
return /^http[s]?:\/\/.*/.test(s);
} }
/** /**
* 验证QQ号码格式是否正确 * qq
* @param {string} s - 要验证的字符串 * @param {*} s
* @returns {boolean} - 如果符合QQ号码格式则返回true否则返回false
*/ */
export function isQq(s) { export function isQq (s) {
// 正则表达式用于匹配有效的QQ号码 return /[1-9][0-9]{4,14}/.test(s)
// - QQ号码至少5位最多15位数字
// - 不能以0开头
return /^[1-9][0-9]{4,14}$/.test(s);
} }
/** /**
* 判断字符串是否全为空格只要有一个非空格字符即返回false * 判断是否全为空格 只要有一个其他字符返回false
* @param {string} str - 要验证的字符串 * @param {String} str
* @returns {boolean} - 如果字符串全部为空格则返回true否则返回false * @returns {Boolean}
*/ */
export function validNoEmptySpace(str) { export function validNoEmptySpace (str) {
const reg = /^\s+$/g; // 匹配整个字符串全是空白字符(包括空格、制表符等)的正则表达式 const reg = /^\s+$/g
return reg.test(str); // 如果字符串完全匹配上述规则则返回true否则返回false return reg.test(str)
} }

Loading…
Cancel
Save