tor-univer-sheet 1.0.16 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -3
- package/src/App.vue +0 -14
- package/src/components/UniverSheet/Methods.data.ts +0 -59
- package/src/components/UniverSheet/UniverSheet.data.ts +0 -533
- package/src/components/UniverSheet/data.ts +0 -18
- package/src/components/UniverSheet/index.ts +0 -22
- package/src/index.ts +0 -31
- package/src/main.ts +0 -10
- package/src/utils/decimal.ts +0 -98
- package/src/utils/index.ts +0 -33
- package/src/utils/is.ts +0 -168
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tor-univer-sheet",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"style": "./dist/style.css",
|
|
5
5
|
"description": "基于 Univer 的 Vue3 电子表格组件",
|
|
6
6
|
"author": "tortormore",
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
"./style.css": "./dist/style.css"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
|
-
"dist"
|
|
22
|
-
"src"
|
|
21
|
+
"dist"
|
|
23
22
|
],
|
|
24
23
|
"scripts": {
|
|
25
24
|
"dev": "vite",
|
package/src/App.vue
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div style="width: 100%; height: 100vh"></div>
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import { ref, onMounted } from 'vue'
|
|
7
|
-
import { ModeEnum } from './components/UniverSheet/UniverSheet.data'
|
|
8
|
-
|
|
9
|
-
const sheetRef = ref()
|
|
10
|
-
|
|
11
|
-
onMounted(() => {
|
|
12
|
-
sheetRef.value?.createUniverSheets()
|
|
13
|
-
})
|
|
14
|
-
</script>
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ICellData,
|
|
3
|
-
IObjectMatrixPrimitiveType,
|
|
4
|
-
} from '@univerjs/presets'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export function getNumColumns(cells: IObjectMatrixPrimitiveType<ICellData>) {
|
|
8
|
-
const result = Object.entries(cells).reduce((acc, [rowNum, cols]) => {
|
|
9
|
-
const colsNum = Math.max(...Object.keys(cols).map(Number))
|
|
10
|
-
if (colsNum > acc) {
|
|
11
|
-
acc = Number(colsNum)
|
|
12
|
-
} else {
|
|
13
|
-
acc = Number(acc) || 0
|
|
14
|
-
}
|
|
15
|
-
return acc
|
|
16
|
-
}, 0)
|
|
17
|
-
return result
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* 智能合并单元格数据
|
|
21
|
-
* 保留原有单元格的属性(如公式、值等),用新数据进行更新
|
|
22
|
-
* @param originalCellData - 原始单元格数据(来自 sheetSnapshot.cellData)
|
|
23
|
-
* @param newCells - 新的单元格数据(来自后端或自生成)
|
|
24
|
-
* @returns 合并后的单元格数据
|
|
25
|
-
*/
|
|
26
|
-
export function mergeCellData(
|
|
27
|
-
originalCellData: IObjectMatrixPrimitiveType<ICellData> | undefined,
|
|
28
|
-
newCells: IObjectMatrixPrimitiveType<ICellData>
|
|
29
|
-
): IObjectMatrixPrimitiveType<ICellData> {
|
|
30
|
-
const result = JSON.parse(JSON.stringify(originalCellData || {})) as IObjectMatrixPrimitiveType<ICellData>
|
|
31
|
-
|
|
32
|
-
for (const [rowNum, cols] of Object.entries(newCells)) {
|
|
33
|
-
if (!result[rowNum]) {
|
|
34
|
-
result[rowNum] = {}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
for (const [colNum, newCellData] of Object.entries(cols)) {
|
|
38
|
-
const cellData = newCellData as ICellData
|
|
39
|
-
const originalCell = result[rowNum]?.[colNum]
|
|
40
|
-
|
|
41
|
-
if (originalCell) {
|
|
42
|
-
result[rowNum][colNum] = {
|
|
43
|
-
...originalCell,
|
|
44
|
-
...cellData,
|
|
45
|
-
custom: {
|
|
46
|
-
...originalCell.custom,
|
|
47
|
-
...(cellData.custom || {})
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
result[rowNum][colNum] = cellData
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return result
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
@@ -1,533 +0,0 @@
|
|
|
1
|
-
import { isArray, isEmpty } from '@/utils/is'
|
|
2
|
-
import dayjs from 'dayjs'
|
|
3
|
-
import { ICellData, IWorksheetData, IObjectMatrixPrimitiveType, CellValueType } from '@univerjs/presets'
|
|
4
|
-
import { decimal } from '@/utils/decimal'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export enum CycleTypeEnum {
|
|
9
|
-
无 = 'no',
|
|
10
|
-
年 = 'year',
|
|
11
|
-
月 = 'month',
|
|
12
|
-
周 = 'week',
|
|
13
|
-
天 = 'day',
|
|
14
|
-
班组 = 'shift',
|
|
15
|
-
小时 = 'hour',
|
|
16
|
-
半小时 = 'half_hour'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export enum ModeEnum {
|
|
20
|
-
view = 'view',
|
|
21
|
-
edit = 'edit'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface UniverSheetsProps {
|
|
25
|
-
mode: ModeEnum
|
|
26
|
-
showImportFilePlugin?: boolean
|
|
27
|
-
showIndicatorsContextMenuPlugin?: boolean
|
|
28
|
-
showSyncContextMenuPlugin?: boolean
|
|
29
|
-
showTimeConfigContextMenuPlugin?: boolean
|
|
30
|
-
license: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function initDateRange(cycleType: CycleTypeEnum, date: string[] | string): Promise<string[]> {
|
|
34
|
-
if (!date) return Promise.reject('日期不能为空')
|
|
35
|
-
switch (cycleType) {
|
|
36
|
-
case CycleTypeEnum.年:
|
|
37
|
-
if (isArray(date)) {
|
|
38
|
-
return Promise.resolve(date)
|
|
39
|
-
}
|
|
40
|
-
const parsedYearDate = dayjs(date)
|
|
41
|
-
if (!parsedYearDate.isValid()) {
|
|
42
|
-
return Promise.reject('无效的日期格式')
|
|
43
|
-
}
|
|
44
|
-
const year = parsedYearDate.year()
|
|
45
|
-
const startMonth = `${year}-01`
|
|
46
|
-
const endMonth = `${year}-12`
|
|
47
|
-
|
|
48
|
-
return Promise.resolve([startMonth, endMonth])
|
|
49
|
-
case CycleTypeEnum.月:
|
|
50
|
-
if (isArray(date)) {
|
|
51
|
-
return Promise.resolve(date)
|
|
52
|
-
}
|
|
53
|
-
const parsedMonthDate = dayjs(date)
|
|
54
|
-
if (!parsedMonthDate.isValid()) {
|
|
55
|
-
return Promise.reject('无效的日期格式')
|
|
56
|
-
}
|
|
57
|
-
const monthStartDate = parsedMonthDate.startOf('month').format('YYYY-MM-DD')
|
|
58
|
-
const monthEndDate = parsedMonthDate.endOf('month').format('YYYY-MM-DD')
|
|
59
|
-
|
|
60
|
-
return Promise.resolve([monthStartDate, monthEndDate])
|
|
61
|
-
case CycleTypeEnum.天:
|
|
62
|
-
if (isArray(date)) {
|
|
63
|
-
return Promise.resolve(date)
|
|
64
|
-
}
|
|
65
|
-
const parsedDayDate = dayjs(date)
|
|
66
|
-
if (!parsedDayDate.isValid()) {
|
|
67
|
-
return Promise.reject('无效的日期格式')
|
|
68
|
-
}
|
|
69
|
-
const startOfDay = parsedDayDate.startOf('day').format('YYYY-MM-DD HH:mm:ss')
|
|
70
|
-
const endOfDay = parsedDayDate.endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
|
71
|
-
return Promise.resolve([startOfDay, endOfDay])
|
|
72
|
-
default:
|
|
73
|
-
return Promise.reject('不支持的周期类型')
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export enum dateTypeEnum {
|
|
78
|
-
year = 'year',
|
|
79
|
-
month = 'month',
|
|
80
|
-
day = 'day',
|
|
81
|
-
hour = 'hour'
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function getDiffNum(startDate, endDate, dateType: dateTypeEnum) {
|
|
85
|
-
if (!dateType) return 0
|
|
86
|
-
const format = {
|
|
87
|
-
year: 'YYYY',
|
|
88
|
-
month: 'YYYY-MM',
|
|
89
|
-
day: 'YYYY-MM-DD',
|
|
90
|
-
hour: 'HH:mm:ss'
|
|
91
|
-
}[dateType]
|
|
92
|
-
if (['day', 'hour'].includes(dateType)) {
|
|
93
|
-
return dayjs(endDate, format).diff(dayjs(startDate, format), dateType) + 1
|
|
94
|
-
}
|
|
95
|
-
return dayjs(endDate, format).diff(dayjs(startDate, format), dateType)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function getForwardPushTimes(startDate: string, forwardPushTime: number, dateType: dateTypeEnum): string {
|
|
99
|
-
if (!dateType) {
|
|
100
|
-
throw new Error('日期类型不能为空')
|
|
101
|
-
}
|
|
102
|
-
const format = {
|
|
103
|
-
year: 'YYYY',
|
|
104
|
-
month: 'YYYY-MM',
|
|
105
|
-
day: 'YYYY-MM-DD',
|
|
106
|
-
hour: 'HH:mm:ss'
|
|
107
|
-
}[dateType]
|
|
108
|
-
return dayjs(startDate).subtract(forwardPushTime, dateType).format(format)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function generateTime(base, type, num, times) {
|
|
112
|
-
const format = {
|
|
113
|
-
year: 'YYYY',
|
|
114
|
-
month: 'YYYY-MM',
|
|
115
|
-
day: 'YYYY-MM-DD',
|
|
116
|
-
hour: 'YYYY-MM-DD HH:mm:ss'
|
|
117
|
-
}[type]
|
|
118
|
-
return dayjs(base, format)
|
|
119
|
-
.add(num * times, type)
|
|
120
|
-
.format(format)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export interface IGenerateIndicatorsCellsParams {
|
|
124
|
-
extraArgs: any
|
|
125
|
-
rangeData: string[]
|
|
126
|
-
currentDay?: string
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export type TeamDataType = {
|
|
130
|
-
teamId: string // 班组id
|
|
131
|
-
teamName: string // 班组名称
|
|
132
|
-
shiftId: string // 班次id
|
|
133
|
-
shiftName: string // 班次名称
|
|
134
|
-
scheduleConfigName: string // 排班配置名称
|
|
135
|
-
scheduleConfigId: string // 排班配置ID
|
|
136
|
-
workName: string // 作业名称
|
|
137
|
-
workCoding: string // 作业编码
|
|
138
|
-
startDatetime: string // 开始时间
|
|
139
|
-
endDatetime: string // 结束时间
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function ensureCellExists(acc: any, rowNum: string | number, colNum: string | number): any {
|
|
143
|
-
// 确保 acc[rowNum] 存在
|
|
144
|
-
if (!acc[rowNum]) {
|
|
145
|
-
acc[rowNum] = {}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// 确保 acc[rowNum][colNum] 存在
|
|
149
|
-
if (!acc[rowNum][colNum]) {
|
|
150
|
-
acc[rowNum][colNum] = {}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return acc[rowNum][colNum]
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export async function filterIndicatorsCell(cellData: IObjectMatrixPrimitiveType<ICellData>) {
|
|
157
|
-
if (!cellData) {
|
|
158
|
-
throw new Error('cellData is required')
|
|
159
|
-
}
|
|
160
|
-
const result = Object.entries(cellData).reduce((acc, cur: any) => {
|
|
161
|
-
const [rowNum, cols] = cur
|
|
162
|
-
for (const [colNum, cellData] of Object.entries(cols)) {
|
|
163
|
-
const { custom, v } = cellData as ICellData
|
|
164
|
-
if (!custom) continue
|
|
165
|
-
const { cellType } = custom
|
|
166
|
-
if (cellType === 'indicator') {
|
|
167
|
-
const targetCell = ensureCellExists(acc, rowNum, colNum)
|
|
168
|
-
targetCell.custom = custom
|
|
169
|
-
targetCell.v = v
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return acc
|
|
173
|
-
}, {})
|
|
174
|
-
if (!result || isEmpty(result)) {
|
|
175
|
-
return Promise.reject(new Error('No data found'))
|
|
176
|
-
}
|
|
177
|
-
return Promise.resolve(result)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function createTimeCells({
|
|
181
|
-
acc,
|
|
182
|
-
params,
|
|
183
|
-
initRowNum,
|
|
184
|
-
initColNum,
|
|
185
|
-
cellData
|
|
186
|
-
}: {
|
|
187
|
-
acc: any
|
|
188
|
-
params: IGenerateIndicatorsCellsParams
|
|
189
|
-
initRowNum: number
|
|
190
|
-
initColNum: number
|
|
191
|
-
cellData: any
|
|
192
|
-
}) {
|
|
193
|
-
const { rangeData, currentDay, extraArgs } = params
|
|
194
|
-
const teamData: any = extraArgs?.teamData || {}
|
|
195
|
-
const { cycleType, timeIncrement, forwardPush, copyType, copyInterval, defaultShift } = cellData.custom as any
|
|
196
|
-
|
|
197
|
-
// 计算生成的行、列数量
|
|
198
|
-
let copyNum = 0
|
|
199
|
-
|
|
200
|
-
switch (cycleType) {
|
|
201
|
-
case CycleTypeEnum.天: {
|
|
202
|
-
let forwardServenDay: string = ''
|
|
203
|
-
if (forwardPush) {
|
|
204
|
-
forwardServenDay = getForwardPushTimes(rangeData[0], 6, dateTypeEnum.day)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 不拓展的情况
|
|
208
|
-
if (!copyType) {
|
|
209
|
-
let businessDate: string = ''
|
|
210
|
-
if (forwardPush) {
|
|
211
|
-
businessDate = forwardServenDay
|
|
212
|
-
} else {
|
|
213
|
-
businessDate = rangeData[0]
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 使用封装方法确保结构存在
|
|
217
|
-
const targetCell = ensureCellExists(acc, initRowNum, initColNum)
|
|
218
|
-
targetCell.v = businessDate
|
|
219
|
-
targetCell.t = CellValueType.STRING
|
|
220
|
-
break
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// 拓展的情况
|
|
224
|
-
if (forwardPush) {
|
|
225
|
-
copyNum = getDiffNum(forwardServenDay, rangeData[0], dateTypeEnum.day)
|
|
226
|
-
} else {
|
|
227
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.day)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 向右增加列,向下增加行
|
|
231
|
-
for (let i = 0; i <= Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
232
|
-
// 处理跨行跨列
|
|
233
|
-
const index = i * (copyInterval + 1)
|
|
234
|
-
let businessDate: string = ''
|
|
235
|
-
if (forwardPush) {
|
|
236
|
-
businessDate = generateTime(forwardServenDay, dateTypeEnum.day, i, timeIncrement)
|
|
237
|
-
} else {
|
|
238
|
-
businessDate = generateTime(rangeData[0], dateTypeEnum.day, i, timeIncrement)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const newRowNum = copyType === 'right' ? initRowNum : initRowNum + index
|
|
242
|
-
const newColNum = copyType === 'right' ? initColNum + index : initColNum
|
|
243
|
-
|
|
244
|
-
// 使用封装方法确保新位置结构存在
|
|
245
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
246
|
-
targetCell.v = businessDate
|
|
247
|
-
targetCell.t = CellValueType.STRING
|
|
248
|
-
}
|
|
249
|
-
break
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
case CycleTypeEnum.月: {
|
|
253
|
-
// 不拓展的情况
|
|
254
|
-
if (!copyType) {
|
|
255
|
-
const targetCell = ensureCellExists(acc, initRowNum, initColNum)
|
|
256
|
-
targetCell.v = rangeData[0]
|
|
257
|
-
targetCell.t = CellValueType.STRING
|
|
258
|
-
break
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// 向右增加列,向下增加行
|
|
262
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.month)
|
|
263
|
-
for (let i = 0; i <= Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
264
|
-
// 处理跨行跨列
|
|
265
|
-
const index = i * (copyInterval + 1)
|
|
266
|
-
const newRowNum = copyType === 'right' ? initRowNum : initRowNum + index
|
|
267
|
-
const newColNum = copyType === 'right' ? initColNum + index : initColNum
|
|
268
|
-
|
|
269
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
270
|
-
targetCell.v = generateTime(rangeData[0], dateTypeEnum.month, i, timeIncrement)
|
|
271
|
-
targetCell.t = CellValueType.STRING
|
|
272
|
-
}
|
|
273
|
-
break
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
case CycleTypeEnum.年: {
|
|
277
|
-
// 不拓展的情况
|
|
278
|
-
if (!copyType) {
|
|
279
|
-
const targetCell = ensureCellExists(acc, initRowNum, initColNum)
|
|
280
|
-
targetCell.v = rangeData[0]
|
|
281
|
-
targetCell.t = CellValueType.STRING
|
|
282
|
-
break
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// 向右增加列,向下增加行
|
|
286
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.year)
|
|
287
|
-
for (let i = 0; i <= Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
288
|
-
// 处理跨行跨列
|
|
289
|
-
const index = i * (copyInterval + 1)
|
|
290
|
-
const newRowNum = copyType === 'right' ? initRowNum : initRowNum + index
|
|
291
|
-
const newColNum = copyType === 'right' ? initColNum + index : initColNum
|
|
292
|
-
|
|
293
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
294
|
-
targetCell.v = generateTime(rangeData[0], dateTypeEnum.year, i, timeIncrement)
|
|
295
|
-
targetCell.t = CellValueType.STRING
|
|
296
|
-
}
|
|
297
|
-
break
|
|
298
|
-
}
|
|
299
|
-
case CycleTypeEnum.小时: {
|
|
300
|
-
if (!copyType) {
|
|
301
|
-
const targetCell = ensureCellExists(acc, initRowNum, initColNum)
|
|
302
|
-
targetCell.t = CellValueType.STRING
|
|
303
|
-
if (defaultShift) {
|
|
304
|
-
targetCell.v = dayjs(teamData?.startDatetime).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
305
|
-
break
|
|
306
|
-
}
|
|
307
|
-
targetCell.v = dayjs(currentDay).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
308
|
-
break
|
|
309
|
-
}
|
|
310
|
-
copyNum = getDiffNum(teamData?.startDatetime, teamData?.endDatetime, dateTypeEnum.hour)
|
|
311
|
-
for (let i = 0; i < Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
312
|
-
// 处理跨行跨列
|
|
313
|
-
const index = i * (copyInterval + 1)
|
|
314
|
-
const newRowNum = copyType === 'right' ? initRowNum : initRowNum + index
|
|
315
|
-
const newColNum = copyType === 'right' ? initColNum + index : initColNum
|
|
316
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
317
|
-
targetCell.t = CellValueType.STRING
|
|
318
|
-
if (defaultShift) {
|
|
319
|
-
const laterOneHour = dayjs(teamData?.startDatetime).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
320
|
-
targetCell.v = generateTime(laterOneHour, dateTypeEnum.hour, i, timeIncrement)
|
|
321
|
-
continue
|
|
322
|
-
}
|
|
323
|
-
targetCell.v = generateTime(dayjs(currentDay).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss'), dateTypeEnum.hour, i, timeIncrement)
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export async function generateIndicatorsCells(
|
|
330
|
-
cells: IObjectMatrixPrimitiveType<ICellData>,
|
|
331
|
-
params: IGenerateIndicatorsCellsParams
|
|
332
|
-
): Promise<ICellData> {
|
|
333
|
-
if (!cells) {
|
|
334
|
-
return Promise.reject('没有可用的单元格数据')
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const { extraArgs, rangeData } = params
|
|
338
|
-
if (!rangeData.length) {
|
|
339
|
-
return Promise.reject('处理时间范围失败, rangeData不能为空')
|
|
340
|
-
}
|
|
341
|
-
const teamData: TeamDataType = extraArgs?.teamData || {}
|
|
342
|
-
|
|
343
|
-
const currentDay = params?.currentDay || dayjs().format('YYYY-MM-DD')
|
|
344
|
-
|
|
345
|
-
const result = Object.entries(cells).reduce((acc, cur) => {
|
|
346
|
-
const [rowNum, cols] = cur
|
|
347
|
-
|
|
348
|
-
for (const [colNum, cellData] of Object.entries(cols)) {
|
|
349
|
-
const { custom } = cellData as ICellData
|
|
350
|
-
if (!custom) continue
|
|
351
|
-
|
|
352
|
-
const { cellType, cycleType, timeIncrement, forwardPush, copyType, copyInterval, defaultShift } = custom as any
|
|
353
|
-
|
|
354
|
-
if (cellType === 'time') {
|
|
355
|
-
createTimeCells({ acc, params, initRowNum: Number(rowNum), initColNum: Number(colNum), cellData })
|
|
356
|
-
continue
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const customData = {
|
|
360
|
-
cycleType,
|
|
361
|
-
indicatorName: custom.indicatorName,
|
|
362
|
-
indicatorCode: custom.indicatorCode,
|
|
363
|
-
indicatorId: custom.indicatorId,
|
|
364
|
-
indicatorDimensionName: custom.indicatorDimensionName,
|
|
365
|
-
indicatorDimensionConfig: custom.indicatorDimensionConfig,
|
|
366
|
-
required: custom.required,
|
|
367
|
-
cellType: custom.cellType,
|
|
368
|
-
defaultShift: custom.defaultShift
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
let copyNum = 0
|
|
372
|
-
switch (cycleType) {
|
|
373
|
-
case CycleTypeEnum.天: {
|
|
374
|
-
let forwardServenDay: string = ''
|
|
375
|
-
if (forwardPush) {
|
|
376
|
-
forwardServenDay = getForwardPushTimes(rangeData[0], 6, dateTypeEnum.day)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (!copyType) {
|
|
380
|
-
let businessDate: string = ''
|
|
381
|
-
if (forwardPush) {
|
|
382
|
-
businessDate = forwardServenDay
|
|
383
|
-
} else {
|
|
384
|
-
businessDate = rangeData[0]
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// 使用封装方法确保结构存在
|
|
388
|
-
const targetCell = ensureCellExists(acc, rowNum, colNum)
|
|
389
|
-
targetCell.custom = {
|
|
390
|
-
...customData,
|
|
391
|
-
businessDate
|
|
392
|
-
}
|
|
393
|
-
if (defaultShift) {
|
|
394
|
-
targetCell.custom.teamData = teamData
|
|
395
|
-
}
|
|
396
|
-
break
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
if (forwardPush) {
|
|
400
|
-
copyNum = getDiffNum(forwardServenDay, rangeData[0], dateTypeEnum.day)
|
|
401
|
-
} else {
|
|
402
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.day)
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
for (let i = 0; i < Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
406
|
-
const index = i * (copyInterval + 1)
|
|
407
|
-
let businessDate: string = ''
|
|
408
|
-
if (forwardPush) {
|
|
409
|
-
businessDate = generateTime(forwardServenDay, dateTypeEnum.day, i, timeIncrement)
|
|
410
|
-
} else {
|
|
411
|
-
businessDate = generateTime(rangeData[0], dateTypeEnum.day, i, timeIncrement)
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const newRowNum = copyType === 'right' ? rowNum : decimal(rowNum).add(index).toNumber()
|
|
415
|
-
const newColNum = copyType === 'right' ? decimal(colNum).add(index).toNumber() : colNum
|
|
416
|
-
|
|
417
|
-
// 使用封装方法确保新位置结构存在
|
|
418
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
419
|
-
targetCell.custom = {
|
|
420
|
-
...customData,
|
|
421
|
-
businessDate
|
|
422
|
-
}
|
|
423
|
-
if (defaultShift) {
|
|
424
|
-
targetCell.custom.teamData = teamData
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
break
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
case CycleTypeEnum.月: {
|
|
431
|
-
if (!copyType) {
|
|
432
|
-
const targetCell = ensureCellExists(acc, rowNum, colNum)
|
|
433
|
-
targetCell.custom = {
|
|
434
|
-
...customData,
|
|
435
|
-
businessDate: rangeData[0]
|
|
436
|
-
}
|
|
437
|
-
break
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.month)
|
|
441
|
-
for (let i = 0; i <= Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
442
|
-
const index = i * (copyInterval + 1)
|
|
443
|
-
const newRowNum = copyType === 'right' ? rowNum : decimal(rowNum).add(index).toNumber()
|
|
444
|
-
const newColNum = copyType === 'right' ? decimal(colNum).add(index).toNumber() : colNum
|
|
445
|
-
|
|
446
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
447
|
-
targetCell.custom = {
|
|
448
|
-
...customData,
|
|
449
|
-
businessDate: generateTime(rangeData[0], dateTypeEnum.month, i, timeIncrement)
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
break
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
case CycleTypeEnum.年: {
|
|
456
|
-
if (!copyType) {
|
|
457
|
-
const targetCell = ensureCellExists(acc, rowNum, colNum)
|
|
458
|
-
targetCell.custom = {
|
|
459
|
-
...customData,
|
|
460
|
-
businessDate: rangeData[0]
|
|
461
|
-
}
|
|
462
|
-
break
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
copyNum = getDiffNum(rangeData[0], rangeData[1], dateTypeEnum.year)
|
|
466
|
-
for (let i = 0; i < Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
467
|
-
const index = i * (copyInterval + 1)
|
|
468
|
-
const newRowNum = copyType === 'right' ? rowNum : decimal(rowNum).add(index).toNumber()
|
|
469
|
-
const newColNum = copyType === 'right' ? decimal(colNum).add(index).toNumber() : colNum
|
|
470
|
-
|
|
471
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
472
|
-
targetCell.custom = {
|
|
473
|
-
...customData,
|
|
474
|
-
businessDate: generateTime(rangeData[0], dateTypeEnum.year, i, timeIncrement)
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
break
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
case CycleTypeEnum.小时: {
|
|
481
|
-
// 不拓展的情况
|
|
482
|
-
if (!copyType) {
|
|
483
|
-
const targetCell = ensureCellExists(acc, rowNum, colNum)
|
|
484
|
-
// 默认当前用户的班组和班次
|
|
485
|
-
if (defaultShift) {
|
|
486
|
-
targetCell.custom = {
|
|
487
|
-
...customData,
|
|
488
|
-
teamData,
|
|
489
|
-
businessDate: dayjs(teamData?.startDatetime).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
490
|
-
}
|
|
491
|
-
break
|
|
492
|
-
}
|
|
493
|
-
targetCell.custom = {
|
|
494
|
-
...customData,
|
|
495
|
-
businessDate: dayjs(currentDay).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
496
|
-
}
|
|
497
|
-
break
|
|
498
|
-
}
|
|
499
|
-
copyNum = getDiffNum(teamData?.startDatetime, teamData?.endDatetime, dateTypeEnum.hour)
|
|
500
|
-
for (let i = 0; i < Math.abs(copyNum === 0 ? 1 : copyNum); i++) {
|
|
501
|
-
const index = i * (copyInterval + 1)
|
|
502
|
-
const newRowNum = copyType === 'right' ? rowNum : decimal(rowNum).add(index).toNumber()
|
|
503
|
-
const newColNum = copyType === 'right' ? decimal(colNum).add(index).toNumber() : colNum
|
|
504
|
-
const targetCell = ensureCellExists(acc, newRowNum, newColNum)
|
|
505
|
-
if (defaultShift) {
|
|
506
|
-
const laterOneHour = dayjs(teamData?.startDatetime).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
|
507
|
-
targetCell.custom = {
|
|
508
|
-
...customData,
|
|
509
|
-
teamData,
|
|
510
|
-
businessDate: generateTime(laterOneHour, dateTypeEnum.hour, i, timeIncrement)
|
|
511
|
-
}
|
|
512
|
-
continue
|
|
513
|
-
}
|
|
514
|
-
targetCell.custom = {
|
|
515
|
-
...customData,
|
|
516
|
-
businessDate: generateTime(
|
|
517
|
-
dayjs(currentDay).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss'),
|
|
518
|
-
dateTypeEnum.hour,
|
|
519
|
-
i,
|
|
520
|
-
timeIncrement
|
|
521
|
-
)
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
break
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
return acc
|
|
530
|
-
}, {})
|
|
531
|
-
|
|
532
|
-
return Promise.resolve(result)
|
|
533
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { generateUUID } from '@/utils'
|
|
2
|
-
import { IWorkbookData, IWorksheetData, ICellData, LocaleType } from '@univerjs/presets'
|
|
3
|
-
|
|
4
|
-
export type UseDataType = {
|
|
5
|
-
workbookData: IWorkbookData
|
|
6
|
-
id?: string
|
|
7
|
-
name?: string
|
|
8
|
-
appVersion?: string
|
|
9
|
-
}
|
|
10
|
-
export function useData(data: UseDataType): IWorkbookData {
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
...data?.workbookData,
|
|
14
|
-
id: data?.id || generateUUID(),
|
|
15
|
-
name: data?.name || '未命名',
|
|
16
|
-
appVersion: data?.appVersion || '1.0.0',
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// 导出数据类型和方法
|
|
2
|
-
export { useData } from './data'
|
|
3
|
-
export type { UseDataType } from './data'
|
|
4
|
-
|
|
5
|
-
// 导出数据枚举、类型和方法
|
|
6
|
-
export {
|
|
7
|
-
ModeEnum,
|
|
8
|
-
CycleTypeEnum,
|
|
9
|
-
initDateRange,
|
|
10
|
-
filterIndicatorsCell,
|
|
11
|
-
generateIndicatorsCells,
|
|
12
|
-
} from './UniverSheet.data'
|
|
13
|
-
export type {
|
|
14
|
-
UniverSheetsProps,
|
|
15
|
-
IGenerateIndicatorsCellsParams,
|
|
16
|
-
TeamDataType,
|
|
17
|
-
} from './UniverSheet.data'
|
|
18
|
-
|
|
19
|
-
export {
|
|
20
|
-
getNumColumns,
|
|
21
|
-
mergeCellData
|
|
22
|
-
} from './Methods.data'
|
package/src/index.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
export { useData } from './components/UniverSheet'
|
|
3
|
-
export type { UseDataType } from './components/UniverSheet'
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
ModeEnum,
|
|
7
|
-
CycleTypeEnum,
|
|
8
|
-
} from './components/UniverSheet'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export type {
|
|
12
|
-
UniverSheetsProps,
|
|
13
|
-
IGenerateIndicatorsCellsParams,
|
|
14
|
-
TeamDataType,
|
|
15
|
-
} from './components/UniverSheet'
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
initDateRange,
|
|
19
|
-
filterIndicatorsCell,
|
|
20
|
-
generateIndicatorsCells,
|
|
21
|
-
mergeCellData,
|
|
22
|
-
getNumColumns
|
|
23
|
-
} from './components/UniverSheet'
|
|
24
|
-
|
|
25
|
-
export { decimal } from './utils/decimal'
|
|
26
|
-
|
|
27
|
-
export { handleClearInput, generateUUID } from './utils'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// 导出样式文件路径(不导入,让使用者自己导入)
|
|
31
|
-
export const stylePath = './style.css'
|
package/src/main.ts
DELETED
package/src/utils/decimal.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import Decimal from 'decimal.js'
|
|
2
|
-
|
|
3
|
-
class DecimalChain {
|
|
4
|
-
private value: Decimal
|
|
5
|
-
|
|
6
|
-
constructor(value: string | number | Decimal) {
|
|
7
|
-
this.value = new Decimal(value)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 加法运算
|
|
12
|
-
* @param num 要加的数
|
|
13
|
-
* @returns DecimalChain 实例,支持链式调用
|
|
14
|
-
*/
|
|
15
|
-
add(num: string | number | Decimal): DecimalChain {
|
|
16
|
-
this.value = this.value.add(num || 0)
|
|
17
|
-
return this
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* 减法运算
|
|
22
|
-
* @param num 要减的数
|
|
23
|
-
* @returns DecimalChain 实例,支持链式调用
|
|
24
|
-
*/
|
|
25
|
-
subtract(num: string | number | Decimal): DecimalChain {
|
|
26
|
-
this.value = this.value.sub(num || 0)
|
|
27
|
-
return this
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* 乘法运算
|
|
32
|
-
* @param num 要乘的数
|
|
33
|
-
* @returns DecimalChain 实例,支持链式调用
|
|
34
|
-
*/
|
|
35
|
-
multiply(num: string | number | Decimal): DecimalChain {
|
|
36
|
-
this.value = this.value.mul(num || 0)
|
|
37
|
-
return this
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 除法运算
|
|
42
|
-
* @param num 要除的数
|
|
43
|
-
* @returns DecimalChain 实例,支持链式调用
|
|
44
|
-
* @throws 当除数为0时抛出错误
|
|
45
|
-
*/
|
|
46
|
-
divide(num: string | number | Decimal): DecimalChain {
|
|
47
|
-
const divisor = new Decimal(num)
|
|
48
|
-
if (divisor.isZero()) {
|
|
49
|
-
throw new Error('除数是0')
|
|
50
|
-
}
|
|
51
|
-
this.value = this.value.div(divisor)
|
|
52
|
-
return this
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 保留小数位数
|
|
57
|
-
* @param dp 保留的小数位数
|
|
58
|
-
* @param rounding 舍入模式,默认为四舍五入
|
|
59
|
-
* @returns DecimalChain 实例,支持链式调用
|
|
60
|
-
*/
|
|
61
|
-
toFixed(dp: number, rounding?: Decimal.Rounding): DecimalChain {
|
|
62
|
-
this.value = new Decimal(this.value.toFixed(dp, rounding!))
|
|
63
|
-
return this
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* 返回当前值
|
|
68
|
-
* @returns Decimal 实例
|
|
69
|
-
*/
|
|
70
|
-
valueOf(): Decimal {
|
|
71
|
-
return this.value
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* 转换为字符串
|
|
76
|
-
* @returns 字符串表示
|
|
77
|
-
*/
|
|
78
|
-
toString(): string {
|
|
79
|
-
return this.value.toString()
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 转换为数字
|
|
84
|
-
* @returns 数字表示
|
|
85
|
-
*/
|
|
86
|
-
toNumber(): number {
|
|
87
|
-
return this.value.toNumber()
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* 创建一个支持链式调用的 Decimal 实例
|
|
93
|
-
* @param value 初始值
|
|
94
|
-
* * @returns DecimalChain 实例
|
|
95
|
-
*/
|
|
96
|
-
export function decimal(value: string | number | Decimal = 0): DecimalChain {
|
|
97
|
-
return new DecimalChain(value)
|
|
98
|
-
}
|
package/src/utils/index.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export const handleClearInput = (model: any, strList: string[]) => {
|
|
3
|
-
for (const str of strList) {
|
|
4
|
-
model[str] = null
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
export const generateUUID = () => {
|
|
8
|
-
if (typeof crypto === 'object') {
|
|
9
|
-
if (typeof crypto.randomUUID === 'function') {
|
|
10
|
-
return crypto.randomUUID()
|
|
11
|
-
}
|
|
12
|
-
if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
|
|
13
|
-
const callback = (c: any) => {
|
|
14
|
-
const num = Number(c)
|
|
15
|
-
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16)
|
|
16
|
-
}
|
|
17
|
-
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
let timestamp = new Date().getTime()
|
|
21
|
-
let performanceNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
|
|
22
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
23
|
-
let random = Math.random() * 16
|
|
24
|
-
if (timestamp > 0) {
|
|
25
|
-
random = (timestamp + random) % 16 | 0
|
|
26
|
-
timestamp = Math.floor(timestamp / 16)
|
|
27
|
-
} else {
|
|
28
|
-
random = (performanceNow + random) % 16 | 0
|
|
29
|
-
performanceNow = Math.floor(performanceNow / 16)
|
|
30
|
-
}
|
|
31
|
-
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
|
|
32
|
-
})
|
|
33
|
-
}
|
package/src/utils/is.ts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
// copy to vben-admin
|
|
2
|
-
|
|
3
|
-
const toString = Object.prototype.toString
|
|
4
|
-
|
|
5
|
-
export const is = (val: unknown, type: string) => {
|
|
6
|
-
return toString.call(val) === `[object ${type}]`
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const isDef = <T = unknown>(val?: T): val is T => {
|
|
10
|
-
return typeof val !== 'undefined'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const isUnDef = <T = unknown>(val?: T): val is T => {
|
|
14
|
-
return !isDef(val)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const isObject = (val: any): val is Record<any, any> => {
|
|
18
|
-
return val !== null && is(val, 'Object')
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const isEmpty = (val: any): boolean => {
|
|
22
|
-
if (val === null || val === undefined || typeof val === 'undefined') {
|
|
23
|
-
return true
|
|
24
|
-
}
|
|
25
|
-
if (isArray(val) || isString(val)) {
|
|
26
|
-
return val.length === 0
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (val instanceof Map || val instanceof Set) {
|
|
30
|
-
return val.size === 0
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (isObject(val)) {
|
|
34
|
-
return Object.keys(val).length === 0
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return false
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const isDate = (val: unknown): val is Date => {
|
|
41
|
-
return is(val, 'Date')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const isNull = (val: unknown): val is null => {
|
|
45
|
-
return val === null
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export const isNullAndUnDef = (val: unknown): val is null | undefined => {
|
|
49
|
-
return isUnDef(val) && isNull(val)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const isNullOrUnDef = (val: unknown): val is null | undefined => {
|
|
53
|
-
return isUnDef(val) || isNull(val)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const isNumber = (val: unknown): val is number => {
|
|
57
|
-
return is(val, 'Number')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
|
|
61
|
-
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const isString = (val: unknown): val is string => {
|
|
65
|
-
return is(val, 'String')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const isFunction = (val: unknown): val is Function => {
|
|
69
|
-
return typeof val === 'function'
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const isBoolean = (val: unknown): val is boolean => {
|
|
73
|
-
return is(val, 'Boolean')
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export const isRegExp = (val: unknown): val is RegExp => {
|
|
77
|
-
return is(val, 'RegExp')
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const isArray = (val: any): val is Array<any> => {
|
|
81
|
-
return val && Array.isArray(val)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const isWindow = (val: any): val is Window => {
|
|
85
|
-
return typeof window !== 'undefined' && is(val, 'Window')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export const isElement = (val: unknown): val is Element => {
|
|
89
|
-
return isObject(val) && !!val.tagName
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export const isMap = (val: unknown): val is Map<any, any> => {
|
|
93
|
-
return is(val, 'Map')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export const isServer = typeof window === 'undefined'
|
|
97
|
-
|
|
98
|
-
export const isClient = !isServer
|
|
99
|
-
|
|
100
|
-
export const isUrl = (path: string): boolean => {
|
|
101
|
-
// fix:修复hash路由无法跳转的问题
|
|
102
|
-
const reg =
|
|
103
|
-
/(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%#\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
|
|
104
|
-
return reg.test(path)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export const isDark = (): boolean => {
|
|
108
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// 是否是图片链接
|
|
112
|
-
export const isImgPath = (path: string): boolean => {
|
|
113
|
-
return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// 密码复杂度校验:至少包含大写字母、小写字母、数字、特殊字符中的三种
|
|
117
|
-
export const isPasswordComplex = (value: string): boolean => {
|
|
118
|
-
if (!isString(value)) {
|
|
119
|
-
return false
|
|
120
|
-
}
|
|
121
|
-
let categories = 0
|
|
122
|
-
if (/[A-Z]/.test(value)) {
|
|
123
|
-
categories += 1
|
|
124
|
-
}
|
|
125
|
-
if (/[a-z]/.test(value)) {
|
|
126
|
-
categories += 1
|
|
127
|
-
}
|
|
128
|
-
if (/[0-9]/.test(value)) {
|
|
129
|
-
categories += 1
|
|
130
|
-
}
|
|
131
|
-
if (/[^A-Za-z0-9]/.test(value)) {
|
|
132
|
-
categories += 1
|
|
133
|
-
}
|
|
134
|
-
return categories >= 3
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 密码校验:长度 6-20 位并满足复杂度
|
|
138
|
-
export const isValidPassword = (value: string): boolean => {
|
|
139
|
-
if (!isString(value)) {
|
|
140
|
-
return false
|
|
141
|
-
}
|
|
142
|
-
const length = value.length
|
|
143
|
-
if (length < 6 || length > 20) {
|
|
144
|
-
return false
|
|
145
|
-
}
|
|
146
|
-
return isPasswordComplex(value)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export const isEmptyVal = (val: any): boolean => {
|
|
150
|
-
return val === '' || val === null || val === undefined
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export const isContainsChinese = (val: string): boolean => {
|
|
154
|
-
// Chinese character Unicode range: \u4e00-\u9fff
|
|
155
|
-
const chineseRegex = /[\u4e00-\u9fff]/
|
|
156
|
-
return chineseRegex.test(val)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @description 判断是否为windows环境
|
|
161
|
-
* @returns
|
|
162
|
-
*/
|
|
163
|
-
// export function isWindows(): boolean {
|
|
164
|
-
// return (
|
|
165
|
-
// (navigator?.userAgentData && navigator?.userAgentData?.platform === 'Windows') ||
|
|
166
|
-
// navigator.platform === 'Win32'
|
|
167
|
-
// )
|
|
168
|
-
// }
|