feat #272 ipAddress组件ipv6类型整改 (#337)

* close #272 ipAddress组件ipv6类型整改

* fix: 检视意见修改
This commit is contained in:
ing 2023-08-01 18:31:33 -07:00 committed by GitHub
parent b9086540ee
commit e26f182602
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 227 additions and 151 deletions

View File

@ -11,7 +11,7 @@ export default {
}, },
data() { data() {
return { return {
value: '3FFE:FFFF:7654:FEDA:1245' value: 'fe80::204:61ff:fe9d:f156'
} }
} }
} }

View File

@ -16,13 +16,18 @@ export const isIP6 = (str) => /^IPv6$/i.test(str)
export const isIP4 = (str) => /^IPv4$/i.test(str) export const isIP4 = (str) => /^IPv4$/i.test(str)
export const ipValidator = ({ props, api }) => (value) => { export const ipValidator =
({ props, api }) =>
(value) => {
let result = true let result = true
if (props.type) { if (props.type) {
/* istanbul ignore else */ /* istanbul ignore else */
if (api.isIP6(props.type)) { if (api.isIP6(props.type)) {
result = typeof value === 'string' result =
/^(((([\da-fA-F]{1,4}):){7}([\da-fA-F]{1,4}))|(((([\da-fA-F]{1,4}):){1,7}:)|((([\da-fA-F]{1,4}):){6}:([\da-fA-F]{1,4}))|((([\da-fA-F]{1,4}):){5}:(([\da-fA-F]{1,4}):)?([\da-fA-F]{1,4}))|((([\da-fA-F]{1,4}):){4}:(([\da-fA-F]{1,4}):){0,2}([\da-fA-F]{1,4}))|((([\da-fA-F]{1,4}):){3}:(([\da-fA-F]{1,4}):){0,3}([\da-fA-F]{1,4}))|((([\da-fA-F]{1,4}):){2}:(([\da-fA-F]{1,4}):){0,4}([\da-fA-F]{1,4}))|((([\da-fA-F]{1,4}):){1}:(([\da-fA-F]{1,4}):){0,5}([\da-fA-F]{1,4}))|(::(([\da-fA-F]{1,4}):){0,6}([\da-fA-F]{1,4}))|(::([\da-fA-F]{1,4})?))|(((([\da-fA-F]{1,4}):){6}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-fA-F]{1,4}):){5}:(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-fA-F]{1,4}):){4}:(([\da-fA-F]{1,4}):)?(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-fA-F]{1,4}):){3}:(([\da-fA-F]{1,4}):){0,2}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-fA-F]{1,4}):){2}:(([\da-fA-F]{1,4}):){0,3}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|(([\da-fA-F]{1,4})::(([\da-fA-F]{1,4}):){0,4}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|(::(([\da-fA-F]{1,4}):){0,5}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))))$/.test(
value
)
} else if (api.isIP4(props.type)) { } else if (api.isIP4(props.type)) {
result = /^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$/.test(value) result = /^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$/.test(value)
} }
@ -48,12 +53,22 @@ export const getCursorPosition = (el) => {
return cursorPos return cursorPos
} }
export const getValue = ({ api, props, state }) => () => { export const getValue =
({ api, props, state }) =>
() => {
const valueArr = [] const valueArr = []
let result = '' let result = ''
if (api.isIP6(props.type)) { if (api.isIP6(props.type)) {
result = state.address[0].value || '' state.address.forEach((item) => {
if (item.value) {
item.value = item.value.replace(/[^a-fA-F\d]/g, '')
}
item.value && valueArr.push(item.value)
})
result = state.address.filter((item) => item.value).length === 8 ? valueArr.join(':') : ''
} else { } else {
state.address.forEach((item) => { state.address.forEach((item) => {
if (api.isIP4(props.type) && item.value) { if (api.isIP4(props.type) && item.value) {
@ -69,18 +84,32 @@ export const getValue = ({ api, props, state }) => () => {
return result return result
} }
export const setValue = ({ api, props, state }) => (value) => { export const setValue =
({ api, props, state }) =>
(value) => {
if (value) { if (value) {
/* istanbul ignore else */ /* istanbul ignore else */
if (api.ipValidator(value)) { if (api.ipValidator(value)) {
if (api.isIP6(props.type)) { if (api.isIP6(props.type)) {
state.address = [{ value }] state.address = value.split(':').map((item) => ({ value: item }))
if (state.address.length < 8) {
let insertIndex = 0
state.address.forEach((item, index) => {
if (item.value === '') {
item.value = '0000'
insertIndex = index
}
})
for (var i = 0; i <= 8 - state.address.length; i++) {
state.address.splice(insertIndex, 0, { value: '0000' })
}
}
} else { } else {
state.address = value.split('.').map((item) => ({ value: item })) state.address = value.split('.').map((item) => ({ value: item }))
} }
} }
} else { } else {
state.address = api.isIP6(props.type) ? [{ value: '' }] : [{ value: '' }, { value: '' }, { value: '' }, { value: '' }] state.address = api.isIP6(props.type) ? new Array(8).fill({ value: '' }) : new Array(4).fill({ value: '' })
} }
} }
@ -105,15 +134,21 @@ const activeEvent = ({ emit, parent, state, index, event, type }) => {
} }
} }
export const focus = ({ emit, parent, state }) => ({ index, event }) => { export const focus =
({ emit, parent, state }) =>
({ index, event }) => {
activeEvent({ emit, parent, state, index, event, type: 'focus' }) activeEvent({ emit, parent, state, index, event, type: 'focus' })
} }
export const select = ({ emit, parent, state }) => ({ index, event }) => { export const select =
({ emit, parent, state }) =>
({ index, event }) => {
activeEvent({ emit, parent, state, index, event, type: 'select' }) activeEvent({ emit, parent, state, index, event, type: 'select' })
} }
export const inputEvent = ({ api, componentName, emit, eventName, props }) => ({ item, index }) => { export const inputEvent =
({ api, componentName, emit, eventName, props }) =>
({ item, index }) => {
const val = item.value.trim() const val = item.value.trim()
let value = '' let value = ''
@ -124,7 +159,11 @@ export const inputEvent = ({ api, componentName, emit, eventName, props }) => ({
item.value = '' item.value = ''
} }
} else { } else {
item.value = val.replace(/[\u4E00-\u9FA5]/g, '') if (!index && api.ipValidator(val)) {
api.setValue(val)
} else if (val.length > 4) {
item.value = item.value.slice(0, 4)
}
} }
value = api.getValue() value = api.getValue()
@ -133,12 +172,16 @@ export const inputEvent = ({ api, componentName, emit, eventName, props }) => ({
api.dispatch(componentName, eventName, [value]) api.dispatch(componentName, eventName, [value])
} }
export const change = ({ api, emit }) => () => { export const change =
({ api, emit }) =>
() => {
const value = api.getValue() const value = api.getValue()
emit('change', value) emit('change', value)
} }
export const blur = ({ api, componentName, emit, eventName, props, state }) => ({ item, index }) => { export const blur =
({ api, componentName, emit, eventName, props, state }) =>
({ item, index }) => {
state.active = false state.active = false
state.isDel = false state.isDel = false
@ -150,7 +193,9 @@ export const blur = ({ api, componentName, emit, eventName, props, state }) => (
api.dispatch(componentName, eventName, [item.value]) api.dispatch(componentName, eventName, [item.value])
} }
export const keyup = ({ api, props }) => ({ item, index, event }) => { export const keyup =
({ api, props }) =>
({ item, index, event }) => {
const { keyCode } = event const { keyCode } = event
const value = item.value.trim() const value = item.value.trim()
const nextIndex = index + 1 const nextIndex = index + 1
@ -171,6 +216,22 @@ export const keyup = ({ api, props }) => ({ item, index, event }) => {
api.focus({ index: nextIndex }) api.focus({ index: nextIndex })
api.select({ index: nextIndex }) api.select({ index: nextIndex })
return false
}
}
if (api.isIP6(props.type)) {
if ([KEY_CODE.Tab, KEY_CODE.Space, KEY_CODE.NumpadDecimal, KEY_CODE.NumpadComma].includes(keyCode) && value) {
api.select({ index: nextIndex })
return false
}
if (
(value.length === 4 || value === '0000') &&
(!isNaN(event.key) || (keyCode >= KEY_CODE.KeyA && keyCode <= KEY_CODE.KeyF))
) {
api.focus({ index: nextIndex })
api.select({ index: nextIndex })
return false return false
} }
} }
@ -186,14 +247,21 @@ const checkError2 = (newValue) => newValue && (isNaN(newValue) || newValue > IPT
const checkError3 = ({ isfilterKeyCodes, isSelected, value }) => !isfilterKeyCodes && !isSelected && value === '0' const checkError3 = ({ isfilterKeyCodes, isSelected, value }) => !isfilterKeyCodes && !isSelected && value === '0'
// NEXT 当内容加输入的数字大于255时屏蔽输入 // NEXT 当内容加输入的数字大于255时屏蔽输入
const checkError4 = ({ isfilterKeyCodes, isSelected, value, key }) => !isfilterKeyCodes && !isSelected && value + key > IPTHRESHOLD.Max const checkError4 = ({ isfilterKeyCodes, isSelected, value, key }) =>
!isfilterKeyCodes && !isSelected && value + key > IPTHRESHOLD.Max
// NEXT 屏蔽非数字键 // NEXT 屏蔽非数字键
const checkError5 = ({ key, isfilterKeyCodes, value, ctrlKey, keyCode, KeyV }) => isNaN(key) && !isfilterKeyCodes && !(!value && ctrlKey && keyCode === KeyV) const checkError5 = ({ key, isfilterKeyCodes, value, ctrlKey, keyCode, KeyV }) =>
isNaN(key) && !isfilterKeyCodes && !(!value && ctrlKey && keyCode === KeyV)
const isError = ({ key, value, isSelected, isfilterKeyCodes, ctrlKey, keyCode, newValue }) => { // ipv6类型屏蔽输入除A-F、a-f、数字的键
const { Tab, Space, NumpadDecimal, NumpadComma, KeyV } = KEY_CODE const checkError6 = ({ KeyA, KeyF, key, isfilterKeyCodes, value, keyCode }) =>
!(keyCode >= KeyA && keyCode <= KeyF) && isNaN(key) && !isfilterKeyCodes && value
const isError = ({ key, value, isSelected, isfilterKeyCodes, ctrlKey, keyCode, newValue, api, props }) => {
const { Tab, Space, KeyA, KeyF, NumpadDecimal, NumpadComma, KeyV } = KEY_CODE
if (api.isIP4(props.type)) {
return ( return (
checkError1({ Tab, Space, NumpadDecimal, NumpadComma, keyCode, value }) || checkError1({ Tab, Space, NumpadDecimal, NumpadComma, keyCode, value }) ||
checkError2(newValue) || checkError2(newValue) ||
@ -201,9 +269,17 @@ const isError = ({ key, value, isSelected, isfilterKeyCodes, ctrlKey, keyCode, n
checkError4({ isfilterKeyCodes, isSelected, value, key }) || checkError4({ isfilterKeyCodes, isSelected, value, key }) ||
checkError5({ key, isfilterKeyCodes, value, ctrlKey, keyCode, KeyV }) checkError5({ key, isfilterKeyCodes, value, ctrlKey, keyCode, KeyV })
) )
} else if (api.isIP6(props.type)) {
return (
checkError1({ Tab, Space, NumpadDecimal, NumpadComma, keyCode, value }) ||
checkError6({ KeyA, KeyF, key, isfilterKeyCodes, value, keyCode })
)
}
} }
export const keydown = ({ api, props, state }) => ({ item, index, event }) => { export const keydown =
({ api, props, state }) =>
({ item, index, event }) => {
const { target, key, keyCode, ctrlKey } = event const { target, key, keyCode, ctrlKey } = event
const value = item.value const value = item.value
const selectionStart = target.selectionStart const selectionStart = target.selectionStart
@ -213,9 +289,8 @@ export const keydown = ({ api, props, state }) => ({ item, index, event }) => {
const isfilterKeyCodes = state.filterKeyCodes.includes(keyCode) const isfilterKeyCodes = state.filterKeyCodes.includes(keyCode)
const nextIndex = index + 1 const nextIndex = index + 1
const lastIndex = index - 1 const lastIndex = index - 1
const newValue = isSelected && !isfilterKeyCodes && value.substr(0, selectionStart) + key + value.substr(selectionEnd) const newValue =
isSelected && !isfilterKeyCodes && value.substr(0, selectionStart) + key + value.substr(selectionEnd)
if (api.isIP4(props.type)) {
state.isDel = keyCode === KEY_CODE.Backspace || keyCode === KEY_CODE.Delete state.isDel = keyCode === KEY_CODE.Backspace || keyCode === KEY_CODE.Delete
if (keyCode === KEY_CODE.Backspace && cursorPosition === 0 && !selectionEnd) { if (keyCode === KEY_CODE.Backspace && cursorPosition === 0 && !selectionEnd) {
@ -247,14 +322,15 @@ export const keydown = ({ api, props, state }) => ({ item, index, event }) => {
isfilterKeyCodes, isfilterKeyCodes,
ctrlKey, ctrlKey,
keyCode, keyCode,
newValue newValue,
api,
props
}) })
) { ) {
event.preventDefault() event.preventDefault()
return false return false
} }
} }
}
export const getHeightOfSize = (size, isLineHeight = 'height') => { export const getHeightOfSize = (size, isLineHeight = 'height') => {
const sizeMap = { const sizeMap = {

View File

@ -127,20 +127,20 @@
} }
&:last-child { &:last-child {
margin-right: var(--ti-ip-address-padding-horizontal);
> svg { > svg {
display: none; display: none;
} }
} }
&:only-child { &:first-child {
width: 100%; margin-left: var(--ti-ip-address-padding-horizontal);
}
}
>input { &__ipv6-delimiter {
width: 100%; width: var(--ti-ip-address-icon-width);
text-align: left; text-align: center;
padding: var(--ti-ip-address-only-child-padding-vertical) var(--ti-ip-address-only-child-padding-horizontal);
}
}
} }
} }
} }

View File

@ -15,10 +15,8 @@
--ti-ip-address-normal-height: var(--ti-common-size-7x); --ti-ip-address-normal-height: var(--ti-common-size-7x);
// IP地址输入框宽度 // IP地址输入框宽度
--ti-ip-address-normal-width: calc(var(--ti-common-size-base) * 40); --ti-ip-address-normal-width: calc(var(--ti-common-size-base) * 40);
// IP地址输入框IPv6 类型垂直内边距 // IP地址输入框水平内边距
--ti-ip-address-only-child-padding-vertical: var(--ti-common-space-0); --ti-ip-address-padding-horizontal: var(--ti-common-space-3x);
// IP地址输入框IPv6 类型水平内边距
--ti-ip-address-only-child-padding-horizontal: var(--ti-common-space-2x);
// IP地址输入框默认文本色 // IP地址输入框默认文本色
--ti-ip-address-normal-text-color: var(--ti-common-color-info-normal); --ti-ip-address-normal-text-color: var(--ti-common-color-info-normal);
// IP地址输入框图标文本色 // IP地址输入框图标文本色

View File

@ -38,7 +38,9 @@
/> />
<template v-if="index < state.address.length - 1"> <template v-if="index < state.address.length - 1">
<slot :slot-scope="{ state, index, item }"> <slot :slot-scope="{ state, index, item }">
<component :is="delimiter" class="tiny-svg-size" /> <span v-if="type === 'IPv6' && delimiter === 'icon-dot-ipv4'"
class="tiny-ip-address__input__ipv6-delimiter">:</span>
<component v-else :is="delimiter" class="tiny-svg-size" />
</slot> </slot>
</template> </template>
</li> </li>