1.读取json文件内容
typescript
/**
* 读取JSON文件内容
*
* @template T 返回的数据类型
* @param {File} file 文件选择框选择的文件对象
* @returns {Promise<T>} 解析后的JSON数据
*/
export function readJSON<T>(file: File): Promise<T> {
return new Promise((resolve, reject) => {
const fileName = file.name;
const fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
if (fileExtension !== "json") {
reject(new Error("文件类型不合法,请选择JSON格式文件!"));
return;
}
if (window.FileReader) {
const reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = () => {
try {
resolve(JSON.parse(reader.result as string));
} catch (error) {
reject(new Error("解析JSON文件失败"));
}
};
reader.onerror = () => {
reject(new Error("读取文件失败"));
};
}
});
}
代码改进点
- 参数类型从
any
改为明确的File
类型,提升类型安全性 - 添加错误处理逻辑,使用
reject
返回错误状态 - 优化变量命名,
fileType
改为更准确的fileExtension
- 添加
try-catch
处理JSON解析可能出现的异常 - 添加文件读取错误的处理逻辑
使用示例
typescript
const fileInput = document.getElementById('file-input') as HTMLInputElement;
fileInput.addEventListener('change', async (event) => {
const file = event.target.files?.[0];
if (!file) return;
try {
const data = await readJSON<MyDataType>(file);
console.log(data);
} catch (error) {
console.error(error.message);
}
});
2. 判断是否 "经度,纬度" 字符串值
以下是实现判断字符串是否为"经度,纬度"格式的TypeScript代码:
typescript
/**
* 判断是否 "经度,纬度" 字符串值
*
* @export
* @param {string} text 传入的字符串
* @return {boolean} 是否 经度,纬度
*/
export function isLonLat(text: string): boolean {
const reg = /^-?((0|1?[0-7]?[0-9]?)(([.][0-9]*)?)|180(([.][0]*)?)),-?((0|[1-8]?[0-9]?)(([.][0-9]*)?)|90(([.][0]*)?))$/
return reg.test(text)
}
该正则表达式解析:
-
经度部分:
-?((0|1?[0-7]?[0-9]?)(([.][0-9]*)?)|180(([.][0]*)?))
- 允许负号开头
- 0-179度,可选小数部分
- 或180度整数(可选.0结尾)
-
纬度部分:
-?((0|[1-8]?[0-9]?)(([.][0-9]*)?)|90(([.][0]*)?))
- 允许负号开头
- 0-89度,可选小数部分
- 或90度整数(可选.0结尾)
-
经度纬度用逗号分隔
3. 获取URL参数
typescript
/**
* 获取URL参数
*
* @export
* @param {string} parameter url参数名
* @return {string | null} 参数值
*/
export function getQueryString(parameter: string): string | null {
return new URL(window.location.href).searchParams.get(parameter)
}
函数说明: 该函数使用现代URL API解析当前页面URL的查询参数,比传统字符串分割方法更可靠。参数说明:
- parameter: 需要获取的URL参数名称
- 返回值: 参数值字符串,若不存在则返回null
使用示例:
typescript
// 假设当前URL为 https://example.com?name=test&id=123
const name = getQueryString('name') // 返回 'test'
const age = getQueryString('age') // 返回 null
注意事项:
- 需要浏览器支持URL接口(所有现代浏览器均支持)
- 返回的字符串不会被自动解码,如需解码URI组件需额外处理
- 参数名称区分大小写
4. 将指定的异步方法转为Promise
typescript
/**
* 将指定的异步方法转为Promise
*
* @param {*} context
* @param {string} apiName
* @param {string} [success="success"]
* @param {string} [error="error"]
* @return {*} Promise
*/
export function apiToSync(context: any, apiName: string, success = "success", error = "error") {
return new Promise((resolve, reject) => {
context[apiName]({
[success]: (res: any) => resolve(res),
[error]: (err: any) => reject(err)
})
})
}
typescript
/**
* 将多个异步方法转为Promise数组
*
* @param {*} context
* @param {string[]} apiNames
* @param {string} [success="success"]
* @param {string} [error="error"]
* @return {*} Promise[]
*/
export function apiArrayToSync(context: any, apiNames: string[], success = "success", error = "error") {
return apiNames.map(apiName => apiToSync(context, apiName, success, error))
}
代码实现了以下功能:
apiToSync
函数将单个异步API转换为PromiseapiArrayToSync
函数批量转换多个API为Promise数组- 支持自定义成功和失败的回调字段名
- 保留了原始API的context调用方式
- 类型标注使用TypeScript语法
5. 将指定的多个异步方法转为Promise
typescript
/**
* 将指定的多个异步方法转为Promise
*
* @param {*} context
* @param {string[]} apiNames
* @param {string} [success="success"]
* @param {string} [error="error"]
* @return {*} Promise[]
*/
export function apiArrayToSync(context: any, apiNames: string[], success = "success", error = "error") {
return apiNames.map((name) => {
const apiFunc = context[name]
return (options: any) =>
new Promise((resolve, reject) => {
options[success] = function (result: any) {
resolve(result)
}
options[error] = function (error) {
reject(error)
}
apiFunc.call(context, options)
})
})
}
使用方法
typescript
// 假设有一个对象包含异步API方法
const apiObject = {
asyncApi1(options: any) {
setTimeout(() => {
options.success('Result from asyncApi1')
}, 1000)
},
asyncApi2(options: any) {
setTimeout(() => {
options.success('Result from asyncApi2')
}, 500)
}
}
// 转换为Promise数组
const promiseArray = apiArrayToSync(apiObject, ['asyncApi1', 'asyncApi2'])
// 使用Promise.all并行调用
Promise.all([
promiseArray[0]({}),
promiseArray[1]({})
]).then(results => {
console.log(results) // ['Result from asyncApi1', 'Result from asyncApi2']
}).catch(error => {
console.error(error)
})
关键点说明
- 该函数将基于回调的异步方法转换为Promise形式
- 支持自定义成功和失败的回调键名
- 返回的是Promise数组,可以配合Promise.all使用
- 保持了原始方法的this绑定
参数说明
context
: 包含异步方法的对象apiNames
: 需要转换的方法名数组success
: 成功回调的键名,默认为'success'error
: 失败回调的键名,默认为'error'
6. 单个权限验证
typescript
/**
* 单个权限验证
* @param value 权限值
* @returns 有权限,返回 `true`,反之则反
*/
export function auth(value: string): boolean {
const stores = useUserInfo();
return stores.userInfos.authBtnList.some((v: string) => v === value);
}
7. 多个权限验证,满足一个则为true
typescript
/**
* 多个权限验证,满足一个则为 true
* @param value 权限值
* @returns 有权限,返回 `true`,反之则反
*/
export function auths(value: Array<string>): boolean {
let flag = false;
const stores = useUserInfo();
stores.userInfos.authBtnList.map((val: string) => {
value.map((v: string) => {
if (val === v) flag = true;
});
});
return flag;
}
8. 多个权限验证,全部满足则为 true
typescript
/**
* 多个权限验证,全部满足则为 true
* @param value 权限值
* @returns 有权限,返回 `true`,反之则反
*/
export function authAll(value: Array<string>): boolean {
const stores = useUserInfo();
return judementSameArr(value, stores.userInfos.authBtnList);
}
/**
* 判断两数组字符串是否相同(用于按钮权限验证),数组字符串中存在相同时会自动去重(按钮权限标识不会重复)
* @param news 新数据
* @param old 源数据
* @returns 两数组相同返回 `true`,反之则反
*/
export function judementSameArr(newArr: unknown[] | string[], oldArr: string[]): boolean {
const news = removeDuplicate(newArr);
const olds = removeDuplicate(oldArr);
let count = 0;
const leng = news.length;
for (let i in olds) {
for (let j in news) {
if (olds[i] === news[j]) count++;
}
}
return count === leng ? true : false;
}
9. 获取UI框架图片URL
typescript
/**
* 获取UI框架图片URL
* @param name 图片名称
* @param prefix 前置根路径
*/
export function getImageUrl(name: string | unknown, prefix = 'frame') {
return new URL(`/src/assets/images/${prefix}/${name}.png`, import.meta.url).href;
}
/**
* 获取业务图片URL
* @param name 图片名称
*/
export function getBaseImage(name: string | unknown) {
return new URL(`/src/assets/images/${name}.png`, import.meta.url).href;
}
/**
* 获取IConURL
* @param name 图标名称
*/
export function getIconUrl(name: string | unknown) {
return new URL(`/src/assets/icons/${name}.png`, import.meta.url).href;
}
10. 转换秒单位为X小时X分钟X秒的格式
typescript
/**
* 转换秒单位为X小时X分钟X秒的格式
* @returns {String}
*/
export function transSeconds(rawSeconds: number) {
if (rawSeconds && rawSeconds > 0) {
let last = 0;
const hours = Math.floor(rawSeconds / 3600);
last = rawSeconds - hours * 3600;
const minute = parseInt(Math.floor(last / 60).toString());
const seconds = parseInt((rawSeconds - hours * 3600 - minute * 60).toString());
return `${hours > 0 ? hours + '小时' : ''}${minute}分${seconds}秒`;
}
return '';
}
11. 输入框限制只能输入数字,并且范围为0-999
typescript
<el-input clearable maxlength="3" v-model.number="form.warningthresholdmin" @input="validateMinValue"></el-input>
// 输入框限制输入只能输入正整数,并且不能大于999
const validateMinValue = (value: any) => {
// 将输入值转换为数字
let num = Number(value);
if (!value) {
form.warningthresholdmin = '';
return;
}
// 检查输入值是否是数字
if (isNaN(num)) {
// 如果不是数字,将其设置为空字符串
form.warningthresholdmin = '';
return;
}
// 检查输入值是否在 0 到 999 的范围内
if (num < 0) {
num = 0;
} else if (num > 999) {
num = 999;
}
// 更新输入框的值
form.warningthresholdmin = num;
}
12. 输入框限制只能输入数字,支持小数,小数点前四位,小数点后六位(经纬度输入框)
typescript
<el-input placeholder="请输入经度" maxlength="10" @input="e => handleInput(e,'longitude')" clearable v-model="form.longitude"></el-input>
<el-input placeholder="请输入纬度" maxlength="10" @input="e => handleInput(e, 'latitude')" clearable v-model="form.latitude"></el-input>
// 限制经纬度输入只能输入数字0-9999.999999
const handleInput = (value: any, type: string) => {
// 处理空值
if (!value) {
if (type === "latitude") {
form.latitude = '';
} else {
form.longitude = '';
}
return;
}
let val = value.toString();
// 非法输入,限制范围或清空
if (val === '.') {
// 允许小数点开头,后续通过正则处理
if (type === "latitude") {
form.latitude = '0.';
} else {
form.longitude = '0.';
}
} else {
// 移除非法字符
val = val.replace(/[^0-9\.]/g, '');
val = val.replace(/(\..*)\./g, '$1'); // 只允许一个小数点
// 限制小数点后六位
const parts = val.split('.');
if (parts.length > 1 && parts[1].length > 6) {
parts[1] = parts[1].substring(0, 6);
val = parts.join('.');
}
// 转换为数字并限制范围
let num = parseFloat(val);
let number = val;
// 检查输入值是否是数字
if (isNaN(num)) {
// 如果不是数字,将其设置为空字符串
if (type === "latitude") {
form.latitude = '';
} else {
form.longitude = '';
}
return;
}
// 检查输入值是否在 0 到 999 的范围内
if (number < 0) {
number = 0;
} else if (number > 9999.999999) {
number = 9999.999999;
}
if (type === "latitude") {
form.latitude = number;
} else {
form.longitude = number;
}
}
}