From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/utils/index.ts | 537 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 537 insertions(+), 0 deletions(-)
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..0bcedb4
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,537 @@
+import { toNumber } from 'lodash-es'
+
+/**
+ *
+ * @param component 闇�瑕佹敞鍐岀殑缁勪欢
+ * @param alias 缁勪欢鍒悕
+ * @returns any
+ */
+export const withInstall = <T>(component: T, alias?: string) => {
+ const comp = component as any
+ comp.install = (app: any) => {
+ app.component(comp.name || comp.displayName, component)
+ if (alias) {
+ app.config.globalProperties[alias] = component
+ }
+ }
+ return component as T & Plugin
+}
+
+/**
+ * @param str 闇�瑕佽浆涓嬪垝绾跨殑椹煎嘲瀛楃涓�
+ * @returns 瀛楃涓蹭笅鍒掔嚎
+ */
+export const humpToUnderline = (str: string): string => {
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase()
+}
+
+/**
+ * @param str 闇�瑕佽浆椹煎嘲鐨勪笅鍒掔嚎瀛楃涓�
+ * @returns 瀛楃涓查┘宄�
+ */
+export const underlineToHump = (str: string): string => {
+ if (!str) return ''
+ return str.replace(/\-(\w)/g, (_, letter: string) => {
+ return letter.toUpperCase()
+ })
+}
+
+/**
+ * 椹煎嘲杞í鏉�
+ */
+export const humpToDash = (str: string): string => {
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase()
+}
+
+export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
+ dom.style.setProperty(prop, val)
+}
+
+/**
+ * 鏌ユ壘鏁扮粍瀵硅薄鐨勬煇涓笅鏍�
+ * @param {Array} ary 鏌ユ壘鐨勬暟缁�
+ * @param {Functon} fn 鍒ゆ柇鐨勬柟娉�
+ */
+// eslint-disable-next-line
+export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
+ if (ary.findIndex) {
+ return ary.findIndex(fn)
+ }
+ let index = -1
+ ary.some((item: T, i: number, ary: Array<T>) => {
+ const ret: T = fn(item, i, ary)
+ if (ret) {
+ index = i
+ return ret
+ }
+ })
+ return index
+}
+
+export const trim = (str: string) => {
+ return str.replace(/(^\s*)|(\s*$)/g, '')
+}
+
+/**
+ * @param {Date | number | string} time 闇�瑕佽浆鎹㈢殑鏃堕棿
+ * @param {String} fmt 闇�瑕佽浆鎹㈢殑鏍煎紡 濡� yyyy-MM-dd銆亂yyy-MM-dd HH:mm:ss
+ */
+export function formatTime(time: Date | number | string, fmt: string) {
+ if (!time) return ''
+ else {
+ const date = new Date(time)
+ const o = {
+ 'M+': date.getMonth() + 1,
+ 'd+': date.getDate(),
+ 'H+': date.getHours(),
+ 'm+': date.getMinutes(),
+ 's+': date.getSeconds(),
+ 'q+': Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds()
+ }
+ if (/(y+)/.test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+ }
+ for (const k in o) {
+ if (new RegExp('(' + k + ')').test(fmt)) {
+ fmt = fmt.replace(
+ RegExp.$1,
+ RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
+ )
+ }
+ }
+ return fmt
+ }
+}
+
+/**
+ * 鐢熸垚闅忔満瀛楃涓�
+ */
+export function toAnyString() {
+ const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
+ const r: number = (Math.random() * 16) | 0
+ const v: number = c === 'x' ? r : (r & 0x3) | 0x8
+ return v.toString()
+ })
+ return str
+}
+
+/**
+ * 鐢熸垚鎸囧畾闀垮害鐨勯殢鏈哄瓧绗︿覆
+ *
+ * @param length 瀛楃涓查暱搴�
+ */
+export function generateRandomStr(length: number): string {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+ let result = ''
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length))
+ }
+ return result
+}
+
+/**
+ * 鏍规嵁鏀寔鐨勬枃浠剁被鍨嬬敓鎴� accept 灞炴�у��
+ *
+ * @param supportedFileTypes 鏀寔鐨勬枃浠剁被鍨嬫暟缁勶紝濡� ['PDF', 'DOC', 'DOCX']
+ * @returns 鐢ㄤ簬鏂囦欢涓婁紶缁勪欢 accept 灞炴�х殑瀛楃涓�
+ */
+export const generateAcceptedFileTypes = (supportedFileTypes: string[]): string => {
+ const allowedExtensions = supportedFileTypes.map((ext) => ext.toLowerCase())
+ const mimeTypes: string[] = []
+
+ // 娣诲姞甯歌鐨� MIME 绫诲瀷鏄犲皠
+ if (allowedExtensions.includes('txt')) {
+ mimeTypes.push('text/plain')
+ }
+ if (allowedExtensions.includes('pdf')) {
+ mimeTypes.push('application/pdf')
+ }
+ if (allowedExtensions.includes('html') || allowedExtensions.includes('htm')) {
+ mimeTypes.push('text/html')
+ }
+ if (allowedExtensions.includes('csv')) {
+ mimeTypes.push('text/csv')
+ }
+ if (allowedExtensions.includes('xlsx') || allowedExtensions.includes('xls')) {
+ mimeTypes.push('application/vnd.ms-excel')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ }
+ if (allowedExtensions.includes('docx') || allowedExtensions.includes('doc')) {
+ mimeTypes.push('application/msword')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
+ }
+ if (allowedExtensions.includes('pptx') || allowedExtensions.includes('ppt')) {
+ mimeTypes.push('application/vnd.ms-powerpoint')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.presentationml.presentation')
+ }
+ if (allowedExtensions.includes('xml')) {
+ mimeTypes.push('application/xml')
+ mimeTypes.push('text/xml')
+ }
+ if (allowedExtensions.includes('md') || allowedExtensions.includes('markdown')) {
+ mimeTypes.push('text/markdown')
+ }
+ if (allowedExtensions.includes('epub')) {
+ mimeTypes.push('application/epub+zip')
+ }
+ if (allowedExtensions.includes('eml')) {
+ mimeTypes.push('message/rfc822')
+ }
+ if (allowedExtensions.includes('msg')) {
+ mimeTypes.push('application/vnd.ms-outlook')
+ }
+
+ // 娣诲姞鏂囦欢鎵╁睍鍚�
+ const extensions = allowedExtensions.map((ext) => `.${ext}`)
+
+ return [...mimeTypes, ...extensions].join(',')
+}
+
+/**
+ * 棣栧瓧姣嶅ぇ鍐�
+ */
+export function firstUpperCase(str: string) {
+ return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
+}
+
+export const generateUUID = () => {
+ if (typeof crypto === 'object') {
+ if (typeof crypto.randomUUID === 'function') {
+ return crypto.randomUUID()
+ }
+ if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
+ const callback = (c: any) => {
+ const num = Number(c)
+ return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(
+ 16
+ )
+ }
+ return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
+ }
+ }
+ let timestamp = new Date().getTime()
+ let performanceNow =
+ (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
+ let random = Math.random() * 16
+ if (timestamp > 0) {
+ random = (timestamp + random) % 16 | 0
+ timestamp = Math.floor(timestamp / 16)
+ } else {
+ random = (performanceNow + random) % 16 | 0
+ performanceNow = Math.floor(performanceNow / 16)
+ }
+ return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
+ })
+}
+
+/**
+ * element plus 鐨勬枃浠跺ぇ灏� Formatter 瀹炵幇
+ *
+ * @param row 琛屾暟鎹�
+ * @param column 瀛楁
+ * @param cellValue 瀛楁鍊�
+ */
+// @ts-ignore
+export const fileSizeFormatter = (row, column, cellValue) => {
+ const fileSize = cellValue
+ const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ const srcSize = parseFloat(fileSize)
+ const index = Math.floor(Math.log(srcSize) / Math.log(1024))
+ const size = srcSize / Math.pow(1024, index)
+ const sizeStr = size.toFixed(2) //淇濈暀鐨勫皬鏁颁綅鏁�
+ return sizeStr + ' ' + unitArr[index]
+}
+
+/**
+ * 灏嗗�煎鍒跺埌鐩爣瀵硅薄锛屼笖浠ョ洰鏍囧璞″睘鎬т负鍑嗭紝渚嬶細target: {a:1} source:{a:2,b:3} 缁撴灉涓猴細{a:2}
+ * @param target 鐩爣瀵硅薄
+ * @param source 婧愬璞�
+ */
+export const copyValueToTarget = (target: any, source: any) => {
+ const newObj = Object.assign({}, target, source)
+ // 鍒犻櫎澶氫綑灞炴��
+ Object.keys(newObj).forEach((key) => {
+ // 濡傛灉涓嶆槸target涓殑灞炴�у垯鍒犻櫎
+ if (Object.keys(target).indexOf(key) === -1) {
+ delete newObj[key]
+ }
+ })
+ // 鏇存柊鐩爣瀵硅薄鍊�
+ Object.assign(target, newObj)
+}
+
+/**
+ * 鑾峰彇閾炬帴鐨勫弬鏁板��
+ * @param key 鍙傛暟閿悕
+ * @param urlStr 閾炬帴鍦板潃锛岄粯璁や负褰撳墠娴忚鍣ㄧ殑鍦板潃
+ */
+export const getUrlValue = (key: string, urlStr: string = location.href): string => {
+ if (!urlStr || !key) return ''
+ const url = new URL(decodeURIComponent(urlStr))
+ return url.searchParams.get(key) ?? ''
+}
+
+/**
+ * 鑾峰彇閾炬帴鐨勫弬鏁板�硷紙鍊肩被鍨嬶級
+ * @param key 鍙傛暟閿悕
+ * @param urlStr 閾炬帴鍦板潃锛岄粯璁や负褰撳墠娴忚鍣ㄧ殑鍦板潃
+ */
+export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
+ return toNumber(getUrlValue(key, urlStr))
+}
+
+/**
+ * 鏋勫缓鎺掑簭瀛楁
+ * @param prop 瀛楁鍚嶇О
+ * @param order 椤哄簭
+ */
+export const buildSortingField = ({ prop, order }) => {
+ return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
+}
+
+// ========== NumberUtils 鏁板瓧鏂规硶 ==========
+
+/**
+ * 鏁扮粍姹傚拰
+ *
+ * @param values 鏁板瓧鏁扮粍
+ * @return 姹傚拰缁撴灉锛岄粯璁や负 0
+ */
+export const getSumValue = (values: number[]): number => {
+ return values.reduce((prev, curr) => {
+ const value = Number(curr)
+ if (!Number.isNaN(value)) {
+ return prev + curr
+ } else {
+ return prev
+ }
+ }, 0)
+}
+
+// ========== 閫氱敤閲戦鏂规硶 ==========
+
+/**
+ * 灏嗕竴涓暣鏁拌浆鎹负鍒嗘暟淇濈暀涓や綅灏忔暟
+ * @param num
+ */
+export const formatToFraction = (num: number | string | undefined): string => {
+ if (typeof num === 'undefined') return '0.00'
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ return (parsedNumber / 100.0).toFixed(2)
+}
+
+/**
+ * 灏嗕竴涓暟杞崲涓� 1.00 杩欐牱
+ * 鏁版嵁鍛堢幇鐨勬椂鍊欎娇鐢�
+ *
+ * @param num 鏁存暟
+ */
+// TODO @鑺嬭壙锛氱湅鐪嬫�庝箞铻嶅悎鎺�
+export const floatToFixed2 = (num: number | string | undefined): string => {
+ let str = '0.00'
+ if (typeof num === 'undefined') {
+ return str
+ }
+ const f = formatToFraction(num)
+ const decimalPart = f.toString().split('.')[1]
+ const len = decimalPart ? decimalPart.length : 0
+ switch (len) {
+ case 0:
+ str = f.toString() + '.00'
+ break
+ case 1:
+ str = f.toString() + '0'
+ break
+ case 2:
+ str = f.toString()
+ break
+ }
+ return str
+}
+
+/**
+ * 灏嗕竴涓垎鏁拌浆鎹负鏁存暟
+ * @param num
+ */
+// TODO @鑺嬭壙锛氱湅鐪嬫�庝箞铻嶅悎鎺�
+export const convertToInteger = (num: number | string | undefined): number => {
+ if (typeof num === 'undefined') return 0
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ // TODO 鍒嗚浆鍏冨悗杩樻湁灏忔暟鍒欏洓鑸嶄簲鍏�
+ return Math.round(parsedNumber * 100)
+}
+
+/**
+ * 鍏冭浆鍒�
+ */
+export const yuanToFen = (amount: string | number): number => {
+ return convertToInteger(amount)
+}
+
+/**
+ * 鍒嗚浆鍏�
+ */
+export const fenToYuan = (price: string | number): string => {
+ return formatToFraction(price)
+}
+
+/**
+ * 璁$畻鐜瘮
+ *
+ * @param value 褰撳墠鏁板��
+ * @param reference 瀵规瘮鏁板��
+ */
+export const calculateRelativeRate = (value?: number, reference?: number) => {
+ // 闃叉闄�0
+ if (!reference || reference == 0) return 0
+
+ return ((100 * ((value || 0) - reference)) / reference).toFixed(0)
+}
+
+// ========== ERP 涓撳睘鏂规硶 ==========
+
+const ERP_COUNT_DIGIT = 3
+const ERP_PRICE_DIGIT = 2
+
+/**
+ * 銆怑RP銆戞牸寮忓寲 Input 鏁板瓧
+ *
+ * 渚嬪璇达細搴撳瓨鏁伴噺
+ *
+ * @param num 鏁伴噺
+ * @package digit 淇濈暀鐨勫皬鏁颁綅鏁�
+ * @return 鏍煎紡鍖栧悗鐨勬暟閲�
+ */
+export const erpNumberFormatter = (num: number | string | undefined, digit: number) => {
+ if (num == null) {
+ return ''
+ }
+ if (typeof num === 'string') {
+ num = parseFloat(num)
+ }
+ // 濡傛灉闈� number锛屽垯鐩存帴杩斿洖绌轰覆
+ if (isNaN(num)) {
+ return ''
+ }
+ return num.toFixed(digit)
+}
+
+/**
+ * 銆怑RP銆戞牸寮忓寲鏁伴噺锛屼繚鐣欎笁浣嶅皬鏁�
+ *
+ * 渚嬪璇达細搴撳瓨鏁伴噺
+ *
+ * @param num 鏁伴噺
+ * @return 鏍煎紡鍖栧悗鐨勬暟閲�
+ */
+export const erpCountInputFormatter = (num: number | string | undefined) => {
+ return erpNumberFormatter(num, ERP_COUNT_DIGIT)
+}
+
+// noinspection JSCommentMatchesSignature
+/**
+ * 銆怑RP銆戞牸寮忓寲鏁伴噺锛屼繚鐣欎笁浣嶅皬鏁�
+ *
+ * @param cellValue 鏁伴噺
+ * @return 鏍煎紡鍖栧悗鐨勬暟閲�
+ */
+export const erpCountTableColumnFormatter = (_, __, cellValue: any, ___) => {
+ return erpNumberFormatter(cellValue, ERP_COUNT_DIGIT)
+}
+
+/**
+ * 銆怑RP銆戞牸寮忓寲閲戦锛屼繚鐣欎簩浣嶅皬鏁�
+ *
+ * 渚嬪璇达細搴撳瓨鏁伴噺
+ *
+ * @param num 鏁伴噺
+ * @return 鏍煎紡鍖栧悗鐨勬暟閲�
+ */
+export const erpPriceInputFormatter = (num: number | string | undefined) => {
+ return erpNumberFormatter(num, ERP_PRICE_DIGIT)
+}
+
+// noinspection JSCommentMatchesSignature
+/**
+ * 銆怑RP銆戞牸寮忓寲閲戦锛屼繚鐣欎簩浣嶅皬鏁�
+ *
+ * @param cellValue 鏁伴噺
+ * @return 鏍煎紡鍖栧悗鐨勬暟閲�
+ */
+export const erpPriceTableColumnFormatter = (_, __, cellValue: any, ___) => {
+ return erpNumberFormatter(cellValue, ERP_PRICE_DIGIT)
+}
+
+/**
+ * 銆怑RP銆戜环鏍艰绠楋紝鍥涜垗浜斿叆淇濈暀涓や綅灏忔暟
+ *
+ * @param price 浠锋牸
+ * @param count 鏁伴噺
+ * @return 鎬讳环鏍笺�傚鏋滄湁浠讳竴涓虹┖锛屽垯杩斿洖 undefined
+ */
+export const erpPriceMultiply = (price: number, count: number) => {
+ if (price == null || count == null) {
+ return undefined
+ }
+ return parseFloat((price * count).toFixed(ERP_PRICE_DIGIT))
+}
+
+/**
+ * 銆怑RP銆戠櫨鍒嗘瘮璁$畻锛屽洓鑸嶄簲鍏ヤ繚鐣欎袱浣嶅皬鏁�
+ *
+ * 濡傛灉 total 涓� 0锛屽垯杩斿洖 0
+ *
+ * @param value 褰撳墠鍊�
+ * @param total 鎬诲��
+ */
+export const erpCalculatePercentage = (value: number, total: number) => {
+ if (total === 0) return 0
+ return ((value / total) * 100).toFixed(2)
+}
+
+/**
+ * 閫傞厤 echarts map 鐨勫湴鍚�
+ *
+ * @param areaName 鍦板尯鍚嶇О
+ */
+export const areaReplace = (areaName: string) => {
+ if (!areaName) {
+ return areaName
+ }
+ return areaName
+ .replace('缁村惥灏旇嚜娌诲尯', '')
+ .replace('澹棌鑷不鍖�', '')
+ .replace('鍥炴棌鑷不鍖�', '')
+ .replace('鑷不鍖�', '')
+ .replace('鐪�', '')
+}
+
+/**
+ * 瑙f瀽 JSON 瀛楃涓�
+ *
+ * @param str
+ */
+export function jsonParse(str: string) {
+ try {
+ return JSON.parse(str)
+ } catch (e) {
+ console.warn(`str[${str}] 涓嶆槸涓�涓� JSON 瀛楃涓瞏)
+ return str
+ }
+}
+
+/**
+ * 鎴彇瀛楃涓�
+ *
+ * @param str 瀛楃涓�
+ * @param start 寮�濮嬩綅缃�
+ * @param end 缁撴潫浣嶇疆
+ */
+export const subString = (str: string, start: number, end: number) => {
+ if (str.length > end) {
+ return str.slice(start, end)
+ }
+ return str
+}
--
Gitblit v1.8.0