feat: [form] add type definitions to utils to enhance type safety (#3322)
* feat: 为多个文件添加类型定义以增强类型安全性 * fix(schema): 修改默认消息和系统消息的返回值为undefined * fix(schema): 优化SchemaType接口的类型定义和默认消息处理逻辑
This commit is contained in:
parent
e178dc2928
commit
2b6f894e83
|
@ -54,7 +54,7 @@ const maxDateValues = {
|
|||
const timezone1 = '-12:00,-11:00,-10:00,-09:30,-08:00,-07:00,-06:00,-05:00,-04:30,-04:00,-03:30,-02:00,-01:00'
|
||||
const timezone2 = '-00:00,+00:00,+01:00,+02:00,+03:00,+03:30,+04:00,+04:30,+05:00,+05:30,+05:45,+06:00'
|
||||
const timezone3 = '+06:30,+07:00,+08:00,+09:00,+10:00,+10:30,+11:00,+11:30,+12:00,+12:45,+13:00,+14:00'
|
||||
const timezones = [].concat(timezone1.split(','), timezone2.split(','), timezone3.split(','))
|
||||
const timezones: string[] = [...timezone1.split(','), ...timezone2.split(','), ...timezone3.split(',')]
|
||||
|
||||
const getTimezone = (date) => {
|
||||
const timezoneoffset = 0 - date.getTimezoneOffset() / 60
|
||||
|
@ -185,13 +185,17 @@ const iso8601DateParser = (m) => {
|
|||
}
|
||||
}
|
||||
|
||||
const dateParsers = [
|
||||
// 添加适当的类型定义
|
||||
type DateParser = (m: any) => Date | undefined
|
||||
type DateParserTuple = [RegExp, DateParser]
|
||||
|
||||
const dateParsers: DateParserTuple[] = [
|
||||
[yyyymmddReg, yyyymmddDateParser],
|
||||
[mmddyyyyReg, mmddyyyyDateParser],
|
||||
[iso8601Reg, iso8601DateParser]
|
||||
]
|
||||
|
||||
const parseDate = (str) => {
|
||||
const parseDate = (str: string) => {
|
||||
for (let i = 0, len = dateParsers.length; i < len; i++) {
|
||||
const m = dateParsers[i][0].exec(str)
|
||||
|
||||
|
@ -279,7 +283,7 @@ const getDateArray = (str, dateFormat) => {
|
|||
return arr
|
||||
}
|
||||
|
||||
const invalideTime = (time, min, max) => isNaN(time) || time < min || time > max
|
||||
const invalideTime = (time: number, min: number, max: number): boolean => isNaN(time) || time < min || time > max
|
||||
|
||||
const invalideValue = ({ year, month, date, hours, minutes, seconds, milliseconds }) =>
|
||||
invalideTime(year, 0, maxDateValues.YEAR) ||
|
||||
|
|
|
@ -13,6 +13,31 @@
|
|||
import { on, off } from '../dom'
|
||||
import { isServer } from '../globalConfig'
|
||||
|
||||
// 添加接口定义
|
||||
interface FullscreenEvents {
|
||||
fullscreenElement: string
|
||||
fullscreenEnabled: string
|
||||
requestFullscreen: string
|
||||
exitFullscreen: string
|
||||
fullscreenchange: string
|
||||
fullscreenerror: string
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
interface Screenfull {
|
||||
request: (element?: any, options?: any) => Promise<void>
|
||||
exit: () => Promise<void>
|
||||
toggle: (element?: any, options?: any) => Promise<void>
|
||||
onchange: (callback: any) => void
|
||||
onerror: (callback: any) => void
|
||||
on: (event: string, callback: any) => void
|
||||
off: (event: string, callback: any) => void
|
||||
raw: FullscreenEvents | {}
|
||||
isFullscreen?: boolean
|
||||
element?: any
|
||||
isEnabled?: boolean
|
||||
}
|
||||
|
||||
const fullscreenApi = [
|
||||
'fullscreenElement',
|
||||
'fullscreenEnabled',
|
||||
|
@ -53,7 +78,7 @@ const fullscreenApiMap = [fullscreenApi, fullscreenApiWebkit, fullscreenApiMoz,
|
|||
|
||||
const document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {}
|
||||
|
||||
let fullscreenEvents = null
|
||||
let fullscreenEvents: FullscreenEvents | null = null
|
||||
|
||||
const getFullScreenEvents = () => {
|
||||
if (isServer) return
|
||||
|
@ -75,12 +100,12 @@ const getFullScreenEvents = () => {
|
|||
|
||||
getFullScreenEvents()
|
||||
|
||||
const eventNameMap = {
|
||||
const eventNameMap: { [key: string]: string | undefined } = {
|
||||
change: fullscreenEvents && fullscreenEvents.fullscreenchange,
|
||||
error: fullscreenEvents && fullscreenEvents.fullscreenerror
|
||||
}
|
||||
|
||||
const screenfull = {
|
||||
const screenfull: Screenfull = {
|
||||
request(element, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const onFullscreenEntered = () => {
|
||||
|
|
|
@ -413,7 +413,14 @@ const getResult = ({ type, res, formatText, string, reg, args }) => {
|
|||
return res
|
||||
}
|
||||
|
||||
const judgForFunc = (args, formatTypes, type) => {
|
||||
interface FormatTypesInterface {
|
||||
text: string
|
||||
url: string
|
||||
html: string
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
const judgForFunc = (args: any[], formatTypes: FormatTypesInterface, type: string): { args: any[]; type: string } => {
|
||||
const lastArg = args[args.length - 1]
|
||||
|
||||
if (lastArg !== formatTypes.text && lastArg !== formatTypes.url && lastArg !== formatTypes.html) {
|
||||
|
|
|
@ -14,8 +14,43 @@ import { hasOwn, isNull } from '../type'
|
|||
import { getNodeKey } from './util'
|
||||
import { Node } from './node'
|
||||
|
||||
interface TreeStoreOptions {
|
||||
data: any
|
||||
key?: string
|
||||
props?: Record<string, any>
|
||||
load?: (node: Node, callback: (data: any) => void) => void
|
||||
lazy?: boolean
|
||||
checkStrictly?: boolean
|
||||
defaultCheckedKeys?: any[]
|
||||
defaultExpandedKeys?: any[]
|
||||
autoExpandParent?: boolean
|
||||
afterLoad?: (params: { data: any; init: boolean }) => void
|
||||
filterNodeMethod?: (value: any, data: any, node: Node) => boolean
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
// 为Node类型声明安全类型
|
||||
type NodeType = any
|
||||
type FilterNodeMethodType = (value: any, data: any, node: NodeType) => boolean
|
||||
|
||||
export class TreeStore {
|
||||
constructor(options) {
|
||||
currentNode: NodeType | null = null
|
||||
currentNodeKey: any = null
|
||||
nodesMap: Record<string, NodeType> = {}
|
||||
root: NodeType
|
||||
data: any
|
||||
lazy = false
|
||||
load?: (node: NodeType, callback: (data: any) => void) => void
|
||||
afterLoad?: (params: { data: any; init: boolean }) => void
|
||||
props: Record<string, any> = {}
|
||||
filterNodeMethod?: FilterNodeMethodType
|
||||
key = ''
|
||||
defaultCheckedKeys: any[] = []
|
||||
checkStrictly = false
|
||||
defaultExpandedKeys: any[] = []
|
||||
autoExpandParent = true
|
||||
|
||||
constructor(options: TreeStoreOptions) {
|
||||
this.currentNode = null
|
||||
this.currentNodeKey = null
|
||||
|
||||
|
@ -40,7 +75,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
getMappingData(data) {
|
||||
getMappingData(data: any) {
|
||||
const props = this.props || {}
|
||||
const mapping = {}
|
||||
|
||||
|
@ -53,16 +88,18 @@ export class TreeStore {
|
|||
return { ...data, ...mapping }
|
||||
}
|
||||
|
||||
filter(value) {
|
||||
filter(value: any) {
|
||||
const { lazy, filterNodeMethod, getMappingData } = this
|
||||
|
||||
const walkTree = (node) => {
|
||||
const walkTree = (node: NodeType) => {
|
||||
const childNodes = node.root ? node.root.childNodes : node.childNodes
|
||||
|
||||
childNodes.forEach((child) => {
|
||||
// 筛选时需要添加mapping字段,但是不能修改用户的数据
|
||||
const mappingData = getMappingData.call(this, child.data)
|
||||
child.visible = filterNodeMethod.call(child, value, mappingData, child)
|
||||
if (filterNodeMethod) {
|
||||
child.visible = filterNodeMethod.call(child, value, mappingData, child)
|
||||
}
|
||||
|
||||
walkTree(child)
|
||||
})
|
||||
|
@ -81,14 +118,14 @@ export class TreeStore {
|
|||
return
|
||||
}
|
||||
if (node.visible && !node.isLeaf && !lazy) {
|
||||
node.expand()
|
||||
node.expand(null, this.autoExpandParent)
|
||||
}
|
||||
}
|
||||
|
||||
walkTree(this)
|
||||
}
|
||||
|
||||
setData(newVal) {
|
||||
setData(newVal: any) {
|
||||
if (newVal !== this.root.data) {
|
||||
this.root.setData(newVal)
|
||||
this._initDefaultCheckedNodes()
|
||||
|
@ -97,7 +134,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
getNode(data) {
|
||||
getNode(data: any): NodeType | null {
|
||||
if (data instanceof Node) {
|
||||
return data
|
||||
}
|
||||
|
@ -107,17 +144,21 @@ export class TreeStore {
|
|||
return this.nodesMap[nodeKey] || null
|
||||
}
|
||||
|
||||
insertBefore(data, insertData) {
|
||||
insertBefore(data: any, insertData: any) {
|
||||
const refNode = this.getNode(insertData)
|
||||
refNode.parent.insertBefore({ data }, refNode)
|
||||
if (refNode && refNode.parent) {
|
||||
refNode.parent.insertBefore({ data }, refNode)
|
||||
}
|
||||
}
|
||||
|
||||
insertAfter(data, insertData) {
|
||||
insertAfter(data: any, insertData: any) {
|
||||
const refNode = this.getNode(insertData)
|
||||
refNode.parent.insertAfter({ data }, refNode)
|
||||
if (refNode && refNode.parent) {
|
||||
refNode.parent.insertAfter({ data }, refNode)
|
||||
}
|
||||
}
|
||||
|
||||
remove(data, isSaveChildNode, isNode) {
|
||||
remove(data: any, isSaveChildNode?: boolean, isNode?: boolean) {
|
||||
const treeNode = isNode ? data : this.getNode(data)
|
||||
|
||||
if (treeNode && treeNode.parent) {
|
||||
|
@ -135,7 +176,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
append(data, parentData, index) {
|
||||
append(data: any, parentData?: any, index?: number) {
|
||||
const parentNode = parentData ? this.getNode(parentData) : this.root
|
||||
|
||||
if (parentNode) {
|
||||
|
@ -144,7 +185,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
setDefaultCheckedKey(newValue) {
|
||||
setDefaultCheckedKey(newValue: any[]) {
|
||||
if (newValue !== this.defaultCheckedKeys) {
|
||||
this.defaultCheckedKeys = newValue
|
||||
this._initDefaultCheckedNodes()
|
||||
|
@ -162,7 +203,7 @@ export class TreeStore {
|
|||
})
|
||||
}
|
||||
|
||||
_initDefaultCheckedNode(node) {
|
||||
_initDefaultCheckedNode(node: NodeType) {
|
||||
const defaultCheckedKeys = this.defaultCheckedKeys || []
|
||||
|
||||
~defaultCheckedKeys.indexOf(node.key) && node.setChecked(true, !this.checkStrictly)
|
||||
|
@ -176,7 +217,7 @@ export class TreeStore {
|
|||
return this.getHalfCheckedNodes().map((node) => (node || {})[this.key])
|
||||
}
|
||||
|
||||
deregisterNode(node) {
|
||||
deregisterNode(node: NodeType) {
|
||||
const key = this.key
|
||||
if (!key || !node || !node.data) {
|
||||
return
|
||||
|
@ -189,7 +230,7 @@ export class TreeStore {
|
|||
delete this.nodesMap[node.key]
|
||||
}
|
||||
|
||||
registerNode(node) {
|
||||
registerNode(node: NodeType) {
|
||||
const key = this.key
|
||||
if (!key || !node || !node.data) {
|
||||
return
|
||||
|
@ -201,10 +242,10 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
getCheckedNodes(leafOnly = false, includeHalfChecked = false, isNode = false) {
|
||||
const checkedNodes = []
|
||||
getCheckedNodes(leafOnly = false, includeHalfChecked = false, isNode = false): any[] {
|
||||
const checkedNodes: any[] = []
|
||||
|
||||
const walkTree = (node) => {
|
||||
const walkTree = (node: NodeType) => {
|
||||
const childNodes = node.root ? node.root.childNodes : node.childNodes
|
||||
|
||||
childNodes.forEach((child) => {
|
||||
|
@ -223,10 +264,10 @@ export class TreeStore {
|
|||
return checkedNodes
|
||||
}
|
||||
|
||||
getHalfCheckedNodes() {
|
||||
const nodes = []
|
||||
getHalfCheckedNodes(): any[] {
|
||||
const nodes: any[] = []
|
||||
|
||||
const walkTree = (node) => {
|
||||
const walkTree = (node: NodeType) => {
|
||||
const childNodes = node.root ? node.root.childNodes : node.childNodes
|
||||
|
||||
childNodes.forEach((child) => {
|
||||
|
@ -243,8 +284,8 @@ export class TreeStore {
|
|||
return nodes
|
||||
}
|
||||
|
||||
_getAllNodes() {
|
||||
const allNodes = []
|
||||
_getAllNodes(): NodeType[] {
|
||||
const allNodes: NodeType[] = []
|
||||
const nodesMap = this.nodesMap
|
||||
|
||||
Object.keys(nodesMap).forEach((nodeKey) => {
|
||||
|
@ -254,7 +295,7 @@ export class TreeStore {
|
|||
return allNodes
|
||||
}
|
||||
|
||||
updateChildren(key, data) {
|
||||
updateChildren(key: string, data: any[]) {
|
||||
const node = this.nodesMap[key]
|
||||
if (!node) {
|
||||
return
|
||||
|
@ -263,7 +304,7 @@ export class TreeStore {
|
|||
const childNodes = node.childNodes
|
||||
|
||||
for (let i = childNodes.length - 1; i >= 0; i--) {
|
||||
this.remove(childNodes[i].data)
|
||||
this.remove(childNodes[i].data, false, false)
|
||||
}
|
||||
|
||||
for (let i = 0, len = data.length; i < len; i++) {
|
||||
|
@ -272,7 +313,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
_setCheckedKeys(key, leafOnly = false, checkedKeys = {}) {
|
||||
_setCheckedKeys(key: string, leafOnly = false, checkedKeys = {}) {
|
||||
const nodes = this._getAllNodes().sort((prevNode, nextNode) => nextNode.level - prevNode.level)
|
||||
const cache = Object.create(null)
|
||||
const keys = Object.keys(checkedKeys)
|
||||
|
@ -303,7 +344,7 @@ export class TreeStore {
|
|||
} else if (leafOnly) {
|
||||
node.setChecked(false, false)
|
||||
|
||||
const walkTree = (node) => {
|
||||
const walkTree = (node: NodeType) => {
|
||||
const childNodes = node.childNodes
|
||||
|
||||
childNodes.forEach((child) => {
|
||||
|
@ -321,7 +362,7 @@ export class TreeStore {
|
|||
}
|
||||
}
|
||||
|
||||
setDefaultExpandedKeys(keys) {
|
||||
setDefaultExpandedKeys(keys: any[]) {
|
||||
keys = keys || []
|
||||
this.defaultExpandedKeys = keys
|
||||
|
||||
|
@ -331,7 +372,7 @@ export class TreeStore {
|
|||
})
|
||||
}
|
||||
|
||||
setCheckedKeys(keys, leafOnly = false) {
|
||||
setCheckedKeys(keys: any[], leafOnly = false) {
|
||||
this.defaultCheckedKeys = keys
|
||||
const checkedKeys = {}
|
||||
|
||||
|
@ -342,7 +383,7 @@ export class TreeStore {
|
|||
this._setCheckedKeys(this.key, leafOnly, checkedKeys)
|
||||
}
|
||||
|
||||
setCheckedNodes(array, leafOnly = false) {
|
||||
setCheckedNodes(array: any[], leafOnly = false) {
|
||||
const key = this.key
|
||||
const checkedKeys = {}
|
||||
|
||||
|
@ -353,13 +394,13 @@ export class TreeStore {
|
|||
this._setCheckedKeys(key, leafOnly, checkedKeys)
|
||||
}
|
||||
|
||||
setChecked(data, checked, deep) {
|
||||
setChecked(data: any, checked: boolean, deep: boolean) {
|
||||
const node = this.getNode(data)
|
||||
|
||||
node && node.setChecked(!!checked, deep)
|
||||
}
|
||||
|
||||
setCurrentNode(currentNode) {
|
||||
setCurrentNode(currentNode: NodeType) {
|
||||
const prevNode = this.currentNode
|
||||
|
||||
if (prevNode) {
|
||||
|
@ -377,7 +418,7 @@ export class TreeStore {
|
|||
return this.currentNode
|
||||
}
|
||||
|
||||
setCurrentNodeKey(key) {
|
||||
setCurrentNodeKey(key: any) {
|
||||
if (isNull(key)) {
|
||||
this.currentNode && (this.currentNode.isCurrent = false)
|
||||
this.currentNode = null
|
||||
|
@ -390,20 +431,20 @@ export class TreeStore {
|
|||
node && this.setCurrentNode(node)
|
||||
}
|
||||
|
||||
setUserCurrentNode(node) {
|
||||
setUserCurrentNode(node: any) {
|
||||
const key = node[this.key]
|
||||
const currNode = this.nodesMap[key]
|
||||
|
||||
this.setCurrentNode(currNode)
|
||||
}
|
||||
|
||||
getData(data) {
|
||||
getData(data: any) {
|
||||
return (this.getNode(data) || {}).data
|
||||
}
|
||||
|
||||
getAllData() {
|
||||
const children = this.props.children
|
||||
const walkTree = (nodes) => {
|
||||
const walkTree = (nodes: NodeType[]) => {
|
||||
return nodes.map((node) => {
|
||||
return { ...node.data, [children]: walkTree(node.childNodes) }
|
||||
})
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
const getTypesObj = (translate) => ({
|
||||
type TranslateFunction = (value: string) => string
|
||||
|
||||
const getTypesObj = (translate: TranslateFunction) => ({
|
||||
string: translate('validation.types.string'),
|
||||
method: translate('validation.types.method'),
|
||||
array: translate('validation.types.array'),
|
||||
|
@ -38,7 +40,7 @@ const getTypesObj = (translate) => ({
|
|||
acceptFile: translate('validation.types.acceptFile'),
|
||||
fileSize: translate('validation.types.fileSize')
|
||||
})
|
||||
export default (translate = (value) => value) => ({
|
||||
export default (translate: TranslateFunction = (value: string) => value) => ({
|
||||
default: translate('validation.default'),
|
||||
required: translate('validation.required'),
|
||||
enum: translate('validation.enum'),
|
||||
|
|
|
@ -13,14 +13,26 @@
|
|||
import { format, complementError, asyncMap, warning, deepMerge, convertFieldsError } from './util'
|
||||
import { hasOwn, isFunction } from '../type'
|
||||
|
||||
function Schema(descriptor, translate?) {
|
||||
// 添加Schema的接口定义
|
||||
interface SchemaType {
|
||||
rules: Record<string, any> | null
|
||||
_messages: Record<string, any>
|
||||
define: (descriptor: Record<string, any>) => void
|
||||
messages: (messages?: Record<string, any>) => Record<string, any>
|
||||
getSeries: (options: any, source: any, source_: any) => Record<string, any>
|
||||
mergeMessage: (options: any) => void
|
||||
validate: (source_: any, o?: any, oc?: Function) => Promise<any>
|
||||
getValidationMethod: (rule: any) => any
|
||||
getType: (rule: any) => string
|
||||
}
|
||||
|
||||
function Schema(descriptor: Record<string, any>, translate?: any) {
|
||||
Schema.getSystemMessage = () => Schema.getDefaultMessage(translate)
|
||||
Schema.messages = Schema.getSystemMessage(translate)
|
||||
Schema.systemMessages = Schema.messages
|
||||
|
||||
this.rules = null
|
||||
this._messages = Schema.systemMessages
|
||||
this.define(descriptor)
|
||||
;(this as SchemaType).rules = null
|
||||
;(this as SchemaType)._messages = Schema.systemMessages
|
||||
;(this as SchemaType).define(descriptor)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -385,13 +397,13 @@ Schema.register = (type, validator) => {
|
|||
Schema.validators[type] = validator
|
||||
}
|
||||
|
||||
Schema.validators = {} as any
|
||||
Schema.validators = {} as Record<string, any>
|
||||
|
||||
Schema.warning = warning
|
||||
|
||||
Schema.messages = {} as any
|
||||
Schema.messages = {} as Record<string, any>
|
||||
|
||||
Schema.systemMessages = {} as any
|
||||
Schema.systemMessages = {} as Record<string, any>
|
||||
|
||||
Schema.getDefaultMessage = () => undefined
|
||||
|
||||
|
|
Loading…
Reference in New Issue