forked from opentiny/tiny-vue
fix(select): fix select/picker bugs (#1487)
This commit is contained in:
parent
a70d32573b
commit
85ce304b76
|
@ -393,6 +393,18 @@ export default {
|
|||
mode: ['mobile-first'],
|
||||
mfDemo: ''
|
||||
},
|
||||
{
|
||||
name: 'string-mode',
|
||||
type: 'Boolean',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '使用字符串模式,精度超过JS限制时使用',
|
||||
'en-US': ''
|
||||
},
|
||||
mode: ['pc', 'mobile', 'mobile-first'],
|
||||
pcDemo: 'string-mode',
|
||||
mfDemo: ''
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
type: 'Number',
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="gray-bg">
|
||||
<tiny-button ghost>幽灵按钮</tiny-button>
|
||||
<tiny-button ghost type="primary">主要按钮</tiny-button>
|
||||
<tiny-button ghost type="success">成功按钮</tiny-button>
|
||||
<tiny-button ghost type="info">信息按钮</tiny-button>
|
||||
<tiny-button ghost type="warning">告警按钮</tiny-button>
|
||||
<tiny-button ghost type="danger">危险按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0">幽灵按钮</tiny-button>
|
||||
<tiny-button ghost type="primary" reset-time="0">主要按钮</tiny-button>
|
||||
<tiny-button ghost type="success" reset-time="0">成功按钮</tiny-button>
|
||||
<tiny-button ghost type="info" reset-time="0">信息按钮</tiny-button>
|
||||
<tiny-button ghost type="warning" reset-time="0">告警按钮</tiny-button>
|
||||
<tiny-button ghost type="danger" reset-time="0">危险按钮</tiny-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@ test('幽灵按钮', async ({ page }) => {
|
|||
const getGhostBtn = (index: number) => demo.locator('.tiny-button').nth(index)
|
||||
|
||||
// 默认幽灵按钮
|
||||
await page.waitForTimeout(1000)
|
||||
await expect(getGhostBtn(0)).toHaveCSS('color', 'rgb(37, 43, 58)')
|
||||
await expect(getGhostBtn(0)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(0)).toHaveCSS('border-bottom-color', 'rgb(173, 176, 184)')
|
||||
await getGhostBtn(0).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(0).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(0)).toHaveCSS('color', 'rgb(94, 124, 224)')
|
||||
await expect(getGhostBtn(0)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
@ -21,7 +23,8 @@ test('幽灵按钮', async ({ page }) => {
|
|||
await expect(getGhostBtn(1)).toHaveCSS('color', 'rgb(94, 124, 224)')
|
||||
await expect(getGhostBtn(1)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(1)).toHaveCSS('border-bottom-color', 'rgb(94, 124, 224)')
|
||||
await getGhostBtn(1).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(1).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(1)).toHaveCSS('color', 'rgb(118, 147, 245)')
|
||||
await expect(getGhostBtn(1)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
@ -31,7 +34,8 @@ test('幽灵按钮', async ({ page }) => {
|
|||
await expect(getGhostBtn(2)).toHaveCSS('color', 'rgb(80, 212, 171)')
|
||||
await expect(getGhostBtn(2)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(2)).toHaveCSS('border-bottom-color', 'rgb(80, 212, 171)')
|
||||
await getGhostBtn(2).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(2).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(2)).toHaveCSS('color', 'rgb(172, 242, 220)')
|
||||
await expect(getGhostBtn(2)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
@ -41,7 +45,8 @@ test('幽灵按钮', async ({ page }) => {
|
|||
await expect(getGhostBtn(3)).toHaveCSS('color', 'rgb(37, 43, 58)')
|
||||
await expect(getGhostBtn(3)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(3)).toHaveCSS('border-bottom-color', 'rgb(37, 43, 58)')
|
||||
await getGhostBtn(3).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(3).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(3)).toHaveCSS('color', 'rgb(92, 97, 115)')
|
||||
await expect(getGhostBtn(3)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
@ -51,7 +56,8 @@ test('幽灵按钮', async ({ page }) => {
|
|||
await expect(getGhostBtn(4)).toHaveCSS('color', 'rgb(250, 152, 65)')
|
||||
await expect(getGhostBtn(4)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(4)).toHaveCSS('border-bottom-color', 'rgb(250, 152, 65)')
|
||||
await getGhostBtn(4).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(4).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(4)).toHaveCSS('color', 'rgb(250, 194, 10)')
|
||||
await expect(getGhostBtn(4)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
@ -61,7 +67,8 @@ test('幽灵按钮', async ({ page }) => {
|
|||
await expect(getGhostBtn(5)).toHaveCSS('color', 'rgb(199, 0, 11)')
|
||||
await expect(getGhostBtn(5)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(getGhostBtn(5)).toHaveCSS('border-bottom-color', 'rgb(199, 0, 11)')
|
||||
await getGhostBtn(5).hover()
|
||||
await page.waitForTimeout(100)
|
||||
await getGhostBtn(5).click()
|
||||
await page.waitForTimeout(100)
|
||||
await expect(getGhostBtn(5)).toHaveCSS('color', 'rgb(214, 74, 82)')
|
||||
await expect(getGhostBtn(5)).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="gray-bg">
|
||||
<tiny-button ghost>幽灵按钮</tiny-button>
|
||||
<tiny-button ghost type="primary">主要按钮</tiny-button>
|
||||
<tiny-button ghost type="success">成功按钮</tiny-button>
|
||||
<tiny-button ghost type="info">信息按钮</tiny-button>
|
||||
<tiny-button ghost type="warning">告警按钮</tiny-button>
|
||||
<tiny-button ghost type="danger">危险按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0">幽灵按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0" type="primary">主要按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0" type="success">成功按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0" type="info">信息按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0" type="warning">告警按钮</tiny-button>
|
||||
<tiny-button ghost reset-time="0" type="danger">危险按钮</tiny-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ test('鼠标滚轮事件', async ({ page }) => {
|
|||
const numeric = page.getByRole('spinbutton')
|
||||
const initVal = Number(await numeric.inputValue())
|
||||
await numeric.click()
|
||||
await page.mouse.wheel(0, -100)
|
||||
await page.mouse.wheel(0, -500)
|
||||
const currentVal = Number(await numeric.inputValue())
|
||||
expect(currentVal).toBeGreaterThanOrEqual(initVal)
|
||||
expect(currentVal).toBeLessThan(initVal)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<template>
|
||||
<tiny-numeric style="width: 500px" v-model="stepNum" :step="step" string-mode :precision="20"></tiny-numeric>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Numeric as TinyNumeric } from '@opentiny/vue'
|
||||
import { ref } from 'vue'
|
||||
const step = ref('0.00000000000000000002')
|
||||
const stepNum = ref('0.00000000000000000002')
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('高精度', async ({ page }) => {
|
||||
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||
await page.goto('numeric#string-mode')
|
||||
|
||||
const input = page.getByRole('spinbutton')
|
||||
const increaseBtn = page.locator('.tiny-numeric__increase')
|
||||
const decreaseBtn = page.locator('.tiny-numeric__decrease')
|
||||
await increaseBtn.click()
|
||||
const increasedVal = await input.inputValue()
|
||||
expect(increasedVal).toContain('0.00000000000000000004')
|
||||
|
||||
await decreaseBtn.click()
|
||||
const decreasedVal = await input.inputValue()
|
||||
expect(decreasedVal).toContain('0.00000000000000000002')
|
||||
})
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<tiny-numeric style="width: 500px" v-model="stepNum" :step="step" string-mode :precision="20"></tiny-numeric>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Numeric } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyNumeric: Numeric
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
step: '0.00000000000000000002',
|
||||
stepNum: '0.00000000000000000002'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -171,6 +171,19 @@ export default {
|
|||
},
|
||||
codeFiles: ['blur-event.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'string-mode',
|
||||
name: {
|
||||
'zh-CN': '高精度',
|
||||
'en-US': 'Out of Focus Event'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'<p>可通过 <code>string-mode</code> 设置高精度模式,当 JS 默认的 Number 不满足数字的长度与精度需求时。</p>\n',
|
||||
'en-US': '<p>The<code>@blur</code>event is triggered when the text box loses focus. </p>\n'
|
||||
},
|
||||
codeFiles: ['string-mode.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'filter-mode',
|
||||
name: {
|
||||
|
|
|
@ -82,12 +82,12 @@ const options2 = ref([
|
|||
{ value: '选项1', label: '黄金糕' },
|
||||
{ value: '选项2', label: '双皮奶', disabled: true },
|
||||
{ value: '选项3', label: '蚵仔煎' },
|
||||
{ value: '选项4', label: '龙须面' },
|
||||
{ value: '选项4', label: '龙须面', disabled: true },
|
||||
{ value: '选项5', label: '北京烤鸭' }
|
||||
])
|
||||
|
||||
const value1 = ref('')
|
||||
const value2 = ref([])
|
||||
const value2 = ref(['选项2'])
|
||||
const value3 = ref('')
|
||||
const value4 = ref(['选项2', '选项3'])
|
||||
const value5 = ref(['选项1', '选项2', '选项3', '选项4', '选项5'])
|
||||
|
|
|
@ -19,15 +19,15 @@ test('多选某项禁用', async ({ page }) => {
|
|||
const tag = select.locator('.tiny-tag')
|
||||
const option = dropdown.locator('.tiny-option')
|
||||
|
||||
await expect(tag).toHaveCount(0)
|
||||
await expect(tag).toHaveCount(1)
|
||||
await select.click()
|
||||
await expect(option.filter({ hasText: '双皮奶' })).toHaveClass(/is-disabled/)
|
||||
|
||||
await option.filter({ hasText: '双皮奶' }).click()
|
||||
await expect(tag).toHaveCount(0)
|
||||
await expect(tag).toHaveCount(1)
|
||||
|
||||
await option.filter({ hasText: '黄金糕' }).click()
|
||||
await expect(tag).toHaveCount(1)
|
||||
await expect(tag).toHaveCount(2)
|
||||
await expect(tag.filter({ hasText: '黄金糕' })).toHaveCount(1)
|
||||
})
|
||||
|
||||
|
|
|
@ -87,11 +87,11 @@ export default {
|
|||
{ value: '选项1', label: '黄金糕' },
|
||||
{ value: '选项2', label: '双皮奶', disabled: true },
|
||||
{ value: '选项3', label: '蚵仔煎' },
|
||||
{ value: '选项4', label: '龙须面' },
|
||||
{ value: '选项4', label: '龙须面', disabled: true },
|
||||
{ value: '选项5', label: '北京烤鸭' }
|
||||
],
|
||||
value1: '',
|
||||
value2: [],
|
||||
value2: ['选项2'],
|
||||
value3: '',
|
||||
value4: ['选项2', '选项3'],
|
||||
value5: ['选项1', '选项2', '选项3', '选项4', '选项5']
|
||||
|
|
|
@ -26,7 +26,7 @@ test('单选事件', async ({ page }) => {
|
|||
|
||||
await page.waitForTimeout(200)
|
||||
await input.hover()
|
||||
await select.locator('.tiny-select__caret').click()
|
||||
await select.locator('.tiny-select__caret.icon-close').click()
|
||||
await page.waitForTimeout(500)
|
||||
await expect(input).toHaveValue('')
|
||||
await expect(model.filter({ hasText: '触发 clear 事件' })).toHaveCount(1)
|
||||
|
@ -42,6 +42,7 @@ test('多选事件', async ({ page }) => {
|
|||
const option = dropdown.locator('.tiny-option')
|
||||
const model = page.locator('.tiny-modal')
|
||||
|
||||
await page.waitForTimeout(500)
|
||||
await select.click()
|
||||
await expect(model.filter({ hasText: '触发 focus 事件' })).toHaveCount(1)
|
||||
await expect(model.filter({ hasText: '触发 visible-change 事件' })).toHaveCount(1)
|
||||
|
@ -56,7 +57,6 @@ test('多选事件', async ({ page }) => {
|
|||
|
||||
await page.waitForTimeout(500)
|
||||
await tag.first().locator('.tiny-tag__close').click()
|
||||
await expect(model.filter({ hasText: '触发 blur 事件' })).toHaveCount(1)
|
||||
await expect(model.filter({ hasText: '触发 change 事件' })).toHaveCount(1)
|
||||
await expect(model.filter({ hasText: '触发 remove-tag 事件' })).toHaveCount(1)
|
||||
await expect(tag).toHaveCount(4)
|
||||
|
@ -66,7 +66,7 @@ test('多选事件', async ({ page }) => {
|
|||
|
||||
await page.waitForTimeout(200)
|
||||
await select.hover()
|
||||
await select.locator('.tiny-select__caret').click()
|
||||
await select.locator('.tiny-select__caret.icon-close').click()
|
||||
|
||||
await expect(tag).toHaveCount(0)
|
||||
await expect(model.filter({ hasText: '触发 change 事件' })).toHaveCount(1)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<br />
|
||||
<div>场景1:多选</div>
|
||||
<br />
|
||||
<tiny-select v-model="value1" multiple>
|
||||
<tiny-select v-model="value1" multiple searchable>
|
||||
<tiny-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
|
||||
</tiny-select>
|
||||
<br />
|
||||
|
|
|
@ -5,7 +5,7 @@ test('删除事件', async ({ page }) => {
|
|||
await page.goto('tabs#tabs-events-close')
|
||||
|
||||
const tabs = page.locator('.tiny-tabs')
|
||||
const tabItem = tabs.getByRole('tab', { name: '表单组件' })
|
||||
const tabItem = tabs.getByRole('tab', { name: '其他组件' })
|
||||
const close = tabItem.locator('.tiny-tabs__icon-close')
|
||||
const modal = page.locator('.tiny-modal').first()
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
prettierFormat,
|
||||
logGreen
|
||||
} from '../../shared/utils'
|
||||
import { getComponents } from '../../shared/module-utils'
|
||||
import { getComponents, excludeComponents } from '../../shared/module-utils'
|
||||
import handlebarsRender from './handlebars.render'
|
||||
|
||||
const version = getopentinyVersion({ key: 'version' })
|
||||
|
@ -61,7 +61,12 @@ const buildFullRuntime = () => {
|
|||
})
|
||||
|
||||
components.forEach((item) => {
|
||||
if (item.inEntry !== false && !item.path.includes('river') && !item.path.includes('chart-beta')) {
|
||||
if (
|
||||
item.inEntry !== false &&
|
||||
!item.path.includes('river') &&
|
||||
!item.path.includes('chart-beta') &&
|
||||
!excludeComponents.includes(item.name)
|
||||
) {
|
||||
const component = capitalizeKebabCase(item.name)
|
||||
|
||||
componentsTemplate.push(` ${component}`)
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
prettierFormat,
|
||||
logGreen
|
||||
} from '../../shared/utils'
|
||||
import { getComponents } from '../../shared/module-utils'
|
||||
import { getComponents, excludeComponents } from '../../shared/module-utils'
|
||||
import handlebarsRender from './handlebars.render'
|
||||
|
||||
const version = getopentinyVersion({ key: 'version' })
|
||||
|
@ -79,7 +79,7 @@ const createEntry = (mode) => {
|
|||
const PKGDeps = {}
|
||||
|
||||
components.forEach((item) => {
|
||||
if (item.inEntry !== false) {
|
||||
if (item.inEntry !== false && !excludeComponents.includes(item.name)) {
|
||||
const component = capitalizeKebabCase(item.name)
|
||||
PKGDeps[item.importName] = 'workspace:~'
|
||||
componentsTemplate.push(` ${component}`)
|
||||
|
|
|
@ -160,6 +160,7 @@ export const getBaseConfig = ({ vueVersion, dtsInclude, dts, buildTarget, isRunt
|
|||
}
|
||||
},
|
||||
include: [...dtsInclude, 'packages/vue/*.d.ts'],
|
||||
exclude: ['**/__tests__'],
|
||||
beforeWriteFile: (filePath, content) => {
|
||||
return {
|
||||
// "vue/src/alert/index.d.ts" ==> "alert/index.d.ts"
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
import type { Plugin, NormalizedOutputOptions, OutputBundle, OutputChunk } from 'rollup'
|
||||
import type { Plugin, NormalizedOutputOptions, OutputBundle } from 'rollup'
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import { rollup } from 'rollup'
|
||||
import chalk from 'chalk'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import { external } from '../../../shared/config'
|
||||
|
||||
const bundlesToMerge = new Set<string>()
|
||||
const commonChunk = new Set<string>()
|
||||
let buildFormat
|
||||
let isDelete
|
||||
|
||||
export default function ({ deleteInlinedFiles = true }): Plugin {
|
||||
return {
|
||||
name: 'opentiny-vue:inline-chunks',
|
||||
generateBundle: ({ format }: NormalizedOutputOptions, bundle: OutputBundle) => {
|
||||
const bundlesToDelete = new Set<string>()
|
||||
const cache = {}
|
||||
|
||||
generateBundle: async ({ format, dir }: NormalizedOutputOptions, bundle: OutputBundle) => {
|
||||
buildFormat = format
|
||||
isDelete = deleteInlinedFiles
|
||||
const jsAssets = Object.keys(bundle).filter((i) => /\.[mc]?js$/.test(i))
|
||||
for (const jsName of jsAssets) {
|
||||
const jsChunk = bundle[jsName]
|
||||
|
@ -16,51 +25,66 @@ export default function ({ deleteInlinedFiles = true }): Plugin {
|
|||
if (!jsChunk.code) continue
|
||||
|
||||
if (format === 'es') {
|
||||
jsChunk.code = jsChunk.code.replace(
|
||||
// import { _ as _export_sfc } from "../../../../_plugin-vue_export-helper-1faf6727.mjs"
|
||||
/^import\s*.+\s*from\s+"[./]+(.+-[a-f0-9]{8}.+)".*$/gim,
|
||||
(_, chunkName) => {
|
||||
if (!cache[chunkName]) {
|
||||
cache[chunkName] = (bundle[chunkName] as OutputChunk).code
|
||||
.replace(/export {[\s\S]+$/, '')
|
||||
.replace(/_extends/g, '_extends_tiny')
|
||||
.replace(/_createForOfIteratorHelperLoose/g, '_createForOfIteratorHelperLoose_tiny')
|
||||
.replace(/_unsupportedIterableToArray/g, '_unsupportedIterableToArray_tiny')
|
||||
.replace(/_arrayLikeToArray/g, '_arrayLikeToArray_tiny')
|
||||
bundlesToDelete.add(chunkName)
|
||||
const reg = /^import(\s*.+\s*from)?\s+"[./]+(.+-[a-f0-9]{8}.+)".*$/gim
|
||||
const matchArr = jsChunk.code.match(reg)
|
||||
if (matchArr) {
|
||||
const filePath = path.join(dir, jsName)
|
||||
bundlesToMerge.add(filePath)
|
||||
matchArr.forEach((matchImport) => {
|
||||
const sourceName = matchImport.match(/"(.+)"/)[1]
|
||||
commonChunk.add(path.join(filePath, '../', sourceName))
|
||||
})
|
||||
}
|
||||
|
||||
return cache[chunkName]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (format === 'cjs') {
|
||||
jsChunk.code = jsChunk.code.replace(
|
||||
// var _pluginVue_exportHelper = require("../../../../_plugin-vue_export-helper-65c7de93.js");
|
||||
/^var\s+(.+)\s+=\s+require\("[./]+(.+-[a-f0-9]{8}.+)".*$/gim,
|
||||
(_, localVarName, chunkName) => {
|
||||
if (!cache[chunkName]) {
|
||||
cache[chunkName] =
|
||||
'var _pluginVue_exportHelper = {};\n' +
|
||||
(bundle[chunkName] as OutputChunk).code.replace(/exports\./g, `${localVarName}.`)
|
||||
bundlesToDelete.add(chunkName)
|
||||
}
|
||||
|
||||
return cache[chunkName]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteInlinedFiles) {
|
||||
// 删除 chunks
|
||||
bundlesToDelete.forEach((name) => {
|
||||
delete bundle[name]
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`\n${chalk.red(name)} 已经被内联并删除`)
|
||||
const reg = /require\("[./]+(.+-[a-f0-9]{8}.+)".*$/gim
|
||||
const matchArr = jsChunk.code.match(reg)
|
||||
if (matchArr) {
|
||||
const filePath = path.join(dir, jsName)
|
||||
bundlesToMerge.add(filePath)
|
||||
matchArr.forEach((matchRequire) => {
|
||||
const sourceName = matchRequire.match(/"(.+)"/)[1]
|
||||
commonChunk.add(path.join(filePath, '../', sourceName))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
closeBundle: async () =>
|
||||
new Promise((resolve) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`\n${chalk.green('开始内联公共依赖')}`)
|
||||
let i = 0
|
||||
if (bundlesToMerge.size > 0) {
|
||||
bundlesToMerge.forEach(async (filePath) => {
|
||||
if (commonChunk.has(filePath)) {
|
||||
++i
|
||||
} else {
|
||||
const bundle = await rollup({
|
||||
input: filePath,
|
||||
external: (source) => external(source),
|
||||
plugins: buildFormat === 'cjs' ? [commonjs()] : []
|
||||
})
|
||||
await bundle.write({ dir: path.join(filePath, '../'), format: buildFormat })
|
||||
await bundle.close()
|
||||
++i
|
||||
}
|
||||
if (i === bundlesToMerge.size) {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}).then(async () => {
|
||||
if (isDelete) {
|
||||
commonChunk.forEach((filePath) => {
|
||||
fs.unlinkSync(filePath)
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`\n${chalk.red(filePath)} 已经被内联并删除`)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,15 +35,14 @@ const findAllpage = (packagesPath) => {
|
|||
// 解决TinyVue和AUI国际化键名不兼容问题
|
||||
.replace(/zhCN/g, 'zh_CN')
|
||||
.replace(/enUS/g, 'en_US')
|
||||
.replace(/-openaui/g, '-opentiny')
|
||||
// 解决在linkjs环境z-index无法统一导致下拉框被遮挡问题
|
||||
.replace(/"(.*?\/popup-manager)"/g, '"@aurora/renderless/common/deps/popup-manager"')
|
||||
|
||||
// 解决当AUI只有一个mobile-first模板而TinyVue有多个模板,导致Linkjs加载不到多端模板的问题
|
||||
if (
|
||||
packagesPath.endsWith('index.js') &&
|
||||
onlyMobileFirstTemplateLists.some(
|
||||
(item) => packagesPath.includes(`${item}\\`) || packagesPath.includes(`${item}/`)
|
||||
)
|
||||
onlyMobileFirstTemplateLists.some((item) => packagesPath.includes(`${path.sep}${item}${path.sep}`))
|
||||
) {
|
||||
result = result.replace(/pc.js/g, 'mobile-first.js')
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ const moduleMap = require(pathFromWorkspaceRoot('packages/modules.json'))
|
|||
|
||||
type mode = 'pc' | 'mobile' | 'mobile-first'
|
||||
|
||||
// 需要在入口文件中排除的组件,比如:富文本
|
||||
export const excludeComponents = ['RichText']
|
||||
|
||||
export interface Module {
|
||||
/** 源码路径,如 vue/src/button/index.ts */
|
||||
path: string
|
||||
|
@ -452,8 +455,7 @@ const createModuleMapping = (componentName, isMobile = false) => {
|
|||
parser: 'json',
|
||||
printWidth: 10
|
||||
}
|
||||
}),
|
||||
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ export default {
|
|||
medium: 42
|
||||
},
|
||||
spacingHeight: 2,
|
||||
initialInputHeight: 30
|
||||
initialInputHeight: 30,
|
||||
// 显示清除等图标时,不隐藏下拉箭头时
|
||||
autoHideDownIcon: false
|
||||
},
|
||||
props: {
|
||||
tagType: 'info'
|
||||
|
|
|
@ -14,7 +14,9 @@ export default {
|
|||
medium: 32
|
||||
},
|
||||
spacingHeight: 4,
|
||||
initialInputHeight: 30
|
||||
initialInputHeight: 30,
|
||||
// 显示清除等图标时,不隐藏下拉箭头时
|
||||
autoHideDownIcon: false
|
||||
},
|
||||
props: {
|
||||
tagType: 'info'
|
||||
|
|
|
@ -2,6 +2,7 @@ import { iconPutAway, iconExpand } from '@opentiny/vue-icon'
|
|||
|
||||
export default {
|
||||
icons: {
|
||||
// 在 showLine=true时,才要切换的图标。 并不是设置正常模式下的图标
|
||||
expanded: iconExpand(),
|
||||
collapse: iconPutAway()
|
||||
}
|
||||
|
|
|
@ -2360,6 +2360,14 @@
|
|||
"type": "template",
|
||||
"exclude": false
|
||||
},
|
||||
"RichText": {
|
||||
"path": "vue/src/rich-text/index.ts",
|
||||
"type": "component",
|
||||
"exclude": false,
|
||||
"mode": [
|
||||
"pc"
|
||||
]
|
||||
},
|
||||
"RichTextEditor": {
|
||||
"path": "vue/src/rich-text-editor/index.ts",
|
||||
"type": "component",
|
||||
|
|
|
@ -180,7 +180,7 @@ export class BigIntDecimal {
|
|||
const convertBigInt = (str) => {
|
||||
// 将以多个零开头的整数前置零清空 '0000000000000003e+21' --> '3e+21' ,解决BigInt(0000000000000003e+21)报错问题
|
||||
const validStr = str.replace(/^0+/, '') || '0'
|
||||
return f(`return BigInt(${validStr})`)()
|
||||
return f(`return BigInt('${validStr}')`)()
|
||||
}
|
||||
if (validateNumber(mergedValue)) {
|
||||
const trimRet = trimNumber(mergedValue)
|
||||
|
@ -188,7 +188,9 @@ export class BigIntDecimal {
|
|||
const numbers = trimRet.trimStr.split('.')
|
||||
this.integer = !numbers[0].includes('e') ? BigInt(numbers[0]) : numbers[0]
|
||||
const decimalStr = numbers[1] || '0'
|
||||
this.decimal = convertBigInt(decimalStr)
|
||||
|
||||
// 如果小数点后有科学计数法,需要特殊处理,如果是正常数字则保留之前逻辑
|
||||
this.decimal = decimalStr.includes('e') ? convertBigInt(decimalStr) : BigInt(decimalStr)
|
||||
this.decimalLen = decimalStr.length
|
||||
} else {
|
||||
this.nan = true
|
||||
|
|
|
@ -91,11 +91,13 @@ export const prevDate = (date, amount = 1) => new Date(date.getFullYear(), date.
|
|||
|
||||
export const nextDate = (date, amount = 1) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount)
|
||||
|
||||
export const getStartDateOfMonth = (year, month) => {
|
||||
export const getStartDateOfMonth = (year, month, offsetDay = 0) => {
|
||||
const res = new Date(year, month, 1)
|
||||
const day = res.getDay()
|
||||
const _day = day === 0 ? 7 : day
|
||||
|
||||
return day === 0 ? prevDate(res, 7) : prevDate(res, day)
|
||||
const offset = _day + offsetDay <= 0 ? 7 + _day : _day
|
||||
return prevDate(res, offset)
|
||||
}
|
||||
|
||||
export const getWeekNumber = (src) => {
|
||||
|
@ -143,6 +145,7 @@ const setRangeData = (arr, start, end, value) => {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-spread
|
||||
export const range = (length) => Array.apply(null, { length }).map((_, n) => n)
|
||||
|
||||
export const getMonthDays = (date) => {
|
||||
|
|
|
@ -207,6 +207,7 @@ export const handleClear =
|
|||
state.leftDate = calcDefaultValue(state.defaultValue)[0]
|
||||
state.rightDate = nextMonth(state.leftDate)
|
||||
state.rangeState.selecting = false
|
||||
// tiny 新增下面行
|
||||
state.rangeState.endDate = null
|
||||
|
||||
emit('pick', null)
|
||||
|
|
|
@ -127,6 +127,7 @@ const initState = ({ reactive, computed, api, constants, designConfig }) => {
|
|||
dateFormat: computed(() => (state.format ? extractDateFormat(state.format) : 'yyyy-MM-dd')),
|
||||
enableMonthArrow: computed(() => api.getEnableMonthArrow()),
|
||||
enableYearArrow: computed(() => api.computerEnableYearArrow()),
|
||||
// tiny 新增
|
||||
confirmButtonProps: {
|
||||
plain: true,
|
||||
type: 'default',
|
||||
|
|
|
@ -21,10 +21,9 @@ import {
|
|||
clearTime
|
||||
} from '../common/deps/date-util'
|
||||
import { DATEPICKER } from '../common'
|
||||
import type { IDateTableRow } from '@/types'
|
||||
|
||||
const formatJudg = ({ day, offset, j, i, cell, count, dateCountOfLastMonth }) => {
|
||||
const nodfpm = day + offset < 0 ? 7 + day + offset : day + offset
|
||||
const nodfpm = day + offset <= 0 ? 7 + day + offset : day + offset
|
||||
|
||||
if (j + i * 7 >= nodfpm) {
|
||||
cell.text = count++
|
||||
|
@ -58,22 +57,8 @@ export const getDateTimestamp = (time) => {
|
|||
return NaN
|
||||
}
|
||||
|
||||
export const arrayFindIndex = (arr, pred) => {
|
||||
for (let i = 0, len = arr.length; i !== len; ++i) {
|
||||
if (pred(arr[i])) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
export const arrayFind = (arr, pred) => {
|
||||
const idx = arrayFindIndex(arr, pred)
|
||||
return ~idx ? arr[idx] : undefined
|
||||
}
|
||||
|
||||
const getSelected = ({ props, cell, format, t, cellDate, selectedDate }) => {
|
||||
// tiny 新增: api参数多余,优化掉
|
||||
const getSelected = (props, cell, format, t, cellDate, selectedDate) => {
|
||||
let selected = cell.selected
|
||||
|
||||
if (props.selectionMode === 'dates') {
|
||||
|
@ -92,14 +77,7 @@ export const getCell =
|
|||
let cell = row[props.showWeekNumber ? j + 1 : j]
|
||||
|
||||
if (!cell) {
|
||||
cell = {
|
||||
row: i,
|
||||
column: j,
|
||||
inRange: false,
|
||||
start: false,
|
||||
end: false,
|
||||
type: DATEPICKER.Normal
|
||||
}
|
||||
cell = { row: i, column: j, inRange: false, start: false, end: false, type: DATEPICKER.Normal }
|
||||
}
|
||||
|
||||
cell.type = DATEPICKER.Normal
|
||||
|
@ -119,15 +97,7 @@ export const getCell =
|
|||
|
||||
const doCount = ({ i, day, offset, j, cell, count, dateCountOfLastMonth, dateCountOfMonth }) => {
|
||||
if (i >= 0 && i <= 1) {
|
||||
const ret = formatJudg({
|
||||
day,
|
||||
offset,
|
||||
j,
|
||||
i,
|
||||
cell,
|
||||
count,
|
||||
dateCountOfLastMonth
|
||||
})
|
||||
const ret = formatJudg({ day, offset, j, i, cell, count, dateCountOfLastMonth })
|
||||
count = ret.count
|
||||
} else {
|
||||
if (count <= dateCountOfMonth) {
|
||||
|
@ -141,8 +111,6 @@ const doCount = ({ i, day, offset, j, cell, count, dateCountOfLastMonth, dateCou
|
|||
return count
|
||||
}
|
||||
|
||||
export const coerceTruthyValueToArray = (val) => (Array.isArray(val) ? val : val ? [val] : [])
|
||||
|
||||
/**
|
||||
* 获取日期表格二维数组,用于渲染日期表格。
|
||||
*
|
||||
|
@ -160,7 +128,7 @@ export const coerceTruthyValueToArray = (val) => (Array.isArray(val) ? val : val
|
|||
*/
|
||||
export const getRows =
|
||||
({ api, props, state, t, vm }) =>
|
||||
(): IDateTableRow[][] => {
|
||||
() => {
|
||||
const date = new Date(state.year, state.month, 1)
|
||||
let day = getFirstDayOfMonth(date)
|
||||
const dateCountOfMonth = getDayCountOfMonth(date.getFullYear(), date.getMonth())
|
||||
|
@ -172,7 +140,7 @@ export const getRows =
|
|||
day = day === 0 ? 7 : day
|
||||
|
||||
const offset = state.offsetDay
|
||||
const rows: IDateTableRow[][] = state.tableRows
|
||||
const rows = state.tableRows
|
||||
const startDate = state.startDate
|
||||
const disabledDate = props.disabledDate
|
||||
const cellClassName = props.cellClassName
|
||||
|
@ -181,7 +149,7 @@ export const getRows =
|
|||
|
||||
const isFunction = props.formatWeeks instanceof Function
|
||||
|
||||
const arr: Date[][] = []
|
||||
const arr = []
|
||||
|
||||
// 日期表格行,从0开始,共6行,[0, 5]
|
||||
for (let i = 0; i < 6; i++) {
|
||||
|
@ -207,15 +175,7 @@ export const getRows =
|
|||
count = doCount({ i, day, offset, j, cell, count, dateCountOfLastMonth, dateCountOfMonth })
|
||||
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(cellDate)
|
||||
cell.selected = getSelected({
|
||||
props,
|
||||
cell,
|
||||
api,
|
||||
format: DATEPICKER.DateFormats.date,
|
||||
t,
|
||||
cellDate,
|
||||
selectedDate
|
||||
})
|
||||
cell.selected = getSelected(props, cell, DATEPICKER.DateFormats.date, t, cellDate, selectedDate)
|
||||
cell.customClass = typeof cellClassName === 'function' && cellClassName(cellDate)
|
||||
|
||||
// 更新日期表格的行数据,执行了这行代码,rows 中才会有数据
|
||||
|
@ -250,6 +210,23 @@ export const getRows =
|
|||
return rows
|
||||
}
|
||||
|
||||
export const arrayFindIndex = (arr, pred) => {
|
||||
for (let i = 0, len = arr.length; i !== len; ++i) {
|
||||
if (pred(arr[i])) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
export const arrayFind = (arr, pred) => {
|
||||
const idx = arrayFindIndex(arr, pred)
|
||||
return ~idx ? arr[idx] : undefined
|
||||
}
|
||||
|
||||
export const coerceTruthyValueToArray = (val) => (Array.isArray(val) ? val : val ? [val] : [])
|
||||
|
||||
export const watchMinDate =
|
||||
({ api, props }) =>
|
||||
(value, oldvalue) => {
|
||||
|
@ -398,7 +375,8 @@ export const markRange =
|
|||
const row = rows[i]
|
||||
|
||||
for (let j = 0, l = row.length; j < l; j++) {
|
||||
if (!props.showWeekNumber || j !== 0) {
|
||||
if (props.showWeekNumber && j === 0) continue
|
||||
|
||||
const cell = row[j]
|
||||
const index = i * 7 + j + (props.showWeekNumber ? -1 : 0)
|
||||
const time = nextDate(startDate, index - state.offsetDay).getTime()
|
||||
|
@ -409,7 +387,6 @@ export const markRange =
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const handleMouseMove =
|
||||
({ api, emit, props, state }) =>
|
||||
|
@ -468,12 +445,6 @@ const getTarget = (event) => {
|
|||
return target
|
||||
}
|
||||
|
||||
export const removeFromArray = (arr, pred) => {
|
||||
const idx = typeof pred === 'function' ? arrayFindIndex(arr, pred) : arr.indexOf(pred)
|
||||
|
||||
return idx >= 0 ? [...arr.slice(0, idx), ...arr.slice(idx + 1)] : arr
|
||||
}
|
||||
|
||||
export const handleClick =
|
||||
({ api, emit, props, state }) =>
|
||||
(event) => {
|
||||
|
@ -529,7 +500,15 @@ export const handleClick =
|
|||
}
|
||||
}
|
||||
|
||||
export const getCssToken = ({ api }) => (cell, prexfix = '') => {
|
||||
export const removeFromArray = (arr, pred) => {
|
||||
const idx = typeof pred === 'function' ? arrayFindIndex(arr, pred) : arr.indexOf(pred)
|
||||
|
||||
return idx >= 0 ? [...arr.slice(0, idx), ...arr.slice(idx + 1)] : arr
|
||||
}
|
||||
|
||||
export const getCssToken =
|
||||
({ api }) =>
|
||||
(cell, prexfix = '') => {
|
||||
const cssStr = api.getCellClasses(cell) || ''
|
||||
|
||||
return cssStr.split(' ').map((className) => prexfix + className)
|
||||
|
|
|
@ -42,7 +42,7 @@ const initState = ({ reactive, computed, api, props }) => {
|
|||
month: computed(() => !Array.isArray(props.date) && props.date.getMonth()),
|
||||
offsetDay: computed(() => api.getOffsetDay()),
|
||||
year: computed(() => !Array.isArray(props.date) && props.date.getFullYear()),
|
||||
startDate: computed(() => getStartDateOfMonth(state.year, state.month)),
|
||||
startDate: computed(() => getStartDateOfMonth(state.year, state.month, state.offsetDay)),
|
||||
date: props.value
|
||||
})
|
||||
|
||||
|
|
|
@ -116,7 +116,10 @@ export const increase =
|
|||
return
|
||||
}
|
||||
|
||||
const value = (props.mouseWheel ? state.displayValue : Number(state.userInput)) || 0
|
||||
// 处理高精度情况
|
||||
const userInput = props.stringMode ? state.userInput : Number(state.userInput)
|
||||
|
||||
const value = (props.mouseWheel ? state.displayValue : userInput) || 0
|
||||
|
||||
if (value.toString().includes('e')) {
|
||||
return
|
||||
|
@ -142,7 +145,11 @@ export const decrease =
|
|||
if (state.inputDisabled || state.minDisabled) {
|
||||
return
|
||||
}
|
||||
const value = (props.mouseWheel ? state.displayValue : Number(state.userInput)) || 0
|
||||
|
||||
// 处理高精度情况
|
||||
const userInput = props.stringMode ? state.userInput : Number(state.userInput)
|
||||
|
||||
const value = (props.mouseWheel ? state.displayValue : userInput) || 0
|
||||
|
||||
if (value.toString().includes('e')) {
|
||||
return
|
||||
|
|
|
@ -16,7 +16,6 @@ import userPopper from '../common/deps/vue-popper'
|
|||
import { DATEPICKER } from '../common'
|
||||
import { formatDate, parseDate, isDateObject, getWeekNumber, prevDate, nextDate } from '../common/deps/date-util'
|
||||
import { extend } from '../common/object'
|
||||
import { isFunction } from '../common/type'
|
||||
import globalTimezone from './timezone'
|
||||
|
||||
const iso8601Reg = /^\d{4}-\d{2}-\d{2}(.)\d{2}:\d{2}:\d{2}(.+)$/
|
||||
|
@ -41,8 +40,18 @@ export const getPanel =
|
|||
return DatePanel
|
||||
}
|
||||
|
||||
export const watchMobileVisible =
|
||||
({ api, props, state }) =>
|
||||
([dateMobileVisible, timeMobileVisible]) => {
|
||||
if (dateMobileVisible || timeMobileVisible) {
|
||||
state.valueOnOpen = Array.isArray(props.modelValue) ? [...props.modelValue] : props.modelValue
|
||||
} else {
|
||||
api.emitChange(props.modelValue)
|
||||
}
|
||||
}
|
||||
|
||||
export const watchPickerVisible =
|
||||
({ api, vm, dispatch, emit, props, state }) =>
|
||||
({ api, vm, dispatch, emit, props, state, nextTick }) =>
|
||||
(value) => {
|
||||
if (props.readonly || state.pickerDisabled || state.isMobileScreen) return
|
||||
|
||||
|
@ -52,15 +61,18 @@ export const watchPickerVisible =
|
|||
state.valueOnOpen = Array.isArray(props.modelValue) ? [...props.modelValue] : props.modelValue
|
||||
} else {
|
||||
api.hidePicker()
|
||||
api.emitChange(props.modelValue)
|
||||
// tiny 新增: 解决vue3下,modelValue的值仍是旧值,误认为值不变,不触发change事件了。
|
||||
nextTick(() => api.emitChange(props.modelValue))
|
||||
state.userInput = null
|
||||
|
||||
if (props.validateEvent) {
|
||||
dispatch('FormItem', 'form.blur')
|
||||
}
|
||||
|
||||
if (props.changeOnConfirm && !valueEquals(props.modelValue, state.oldValue)) {
|
||||
emit('update:modelValue', state.oldValue)
|
||||
}
|
||||
|
||||
emit('blur', vm)
|
||||
api.blur()
|
||||
}
|
||||
|
@ -117,14 +129,8 @@ export const displayValue =
|
|||
const formatObj = {
|
||||
rangeSeparator: props.rangeSeparator
|
||||
}
|
||||
const formattedValue = api.formatAsFormatAndType(
|
||||
state.parsedValue,
|
||||
state.format,
|
||||
state.type,
|
||||
props.rangeSeparator,
|
||||
formatObj
|
||||
)
|
||||
|
||||
const formattedValue = api.formatAsFormatAndType(state.parsedValue, state.format, state.type, formatObj)
|
||||
if (Array.isArray(state.userInput)) {
|
||||
return [
|
||||
state.userInput[0] || (formattedValue && formattedValue[0]) || '',
|
||||
|
@ -176,12 +182,13 @@ export const parsedValue =
|
|||
|
||||
if (isServiceTimezone) {
|
||||
if (Array.isArray(date)) {
|
||||
date = [].concat(date).map((item) => (isDate(item) ? formatDate(item, state.valueFormat, t) : item))
|
||||
date = [].concat(date).map((item) => {
|
||||
return isDate(item) ? formatDate(item, state.valueFormat, t) : item
|
||||
})
|
||||
} else {
|
||||
date = formatDate(date, state.valueFormat, t)
|
||||
}
|
||||
}
|
||||
|
||||
const result = api.parseAsFormatAndType(date, state.valueFormat, state.type, props.rangeSeparator)
|
||||
if (Array.isArray(result)) {
|
||||
return result.map((date) => getDateWithNewTimezone(date, from, to, timezoneOffset))
|
||||
|
@ -194,7 +201,6 @@ export const parsedValue =
|
|||
const values = []
|
||||
.concat(props.modelValue)
|
||||
.map((val) => getDateWithNewTimezone(trans(val), from, to, timezoneOffset))
|
||||
|
||||
return values.length > 1 ? values : values[0]
|
||||
}
|
||||
|
||||
|
@ -337,7 +343,6 @@ const getWeekOfTypeValueResolveMap = ({ t, props, api }) => ({
|
|||
trueDate.setHours(0, 0, 0, 0)
|
||||
trueDate.setDate(trueDate.getDate() + 3 - ((trueDate.getDay() + 6) % 7))
|
||||
}
|
||||
|
||||
let date
|
||||
if (type === 'format' && !/W/.test(format)) {
|
||||
const { start, end } = getWeekRange(value, format, t, props.pickerOptions)
|
||||
|
@ -346,6 +351,7 @@ const getWeekOfTypeValueResolveMap = ({ t, props, api }) => ({
|
|||
date = formatDate(trueDate, format, t)
|
||||
date = /WW/.test(date) ? date.replace(/WW/, week < 10 ? '0' + week : week) : date.replace(/W/, week)
|
||||
}
|
||||
|
||||
return date
|
||||
},
|
||||
parser(text, format) {
|
||||
|
@ -505,12 +511,211 @@ export const handleMouseEnter =
|
|||
}
|
||||
}
|
||||
|
||||
// 这个是 input 组件的 input 事件,应该只有一个 event 参数,input 组件的具体值从 event.target.value 中获取。
|
||||
export const handleInput =
|
||||
({ state, props, api }) =>
|
||||
(val, event) => {
|
||||
// 兼容tiny-input传参不同导致的报错问题
|
||||
event = val.target ? val : event
|
||||
if (props.autoFormat) {
|
||||
const value = api.formatInputValue({ event, prevValue: state.displayValue })
|
||||
state.userInput = value
|
||||
} else {
|
||||
const val = event.target.value
|
||||
state.userInput = val
|
||||
}
|
||||
}
|
||||
|
||||
export const formatInputValue =
|
||||
({ props, state }) =>
|
||||
({ event, prevValue = '' }) => {
|
||||
const val = event.target.value
|
||||
const inputData = event.data
|
||||
const format = state.type === 'time-select' ? 'HH:mm' : props.format || DATEPICKER.DateFormats[state.type]
|
||||
if (inputData && inputData.charCodeAt() >= 48 && inputData.charCodeAt() <= 57) {
|
||||
return formatText({ event, format, text: prevValue, needSelectionStart: true })
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
const getSelectionStart = ({ value, format, regx, event }) => {
|
||||
const formatMatchArr = format.match(regx)
|
||||
let selectionStart = getSelectionStartIndex(event)
|
||||
let I = 0
|
||||
|
||||
if (value !== '') {
|
||||
const match = value.match(/[0-9]/g)
|
||||
I = match === null ? 0 : match.length
|
||||
|
||||
for (let i = 0; i < formatMatchArr.length; i++) {
|
||||
I -= Math.max(formatMatchArr[i].length, 2)
|
||||
}
|
||||
|
||||
I = I >= 0 ? 1 : 0
|
||||
I === 1 && selectionStart >= value.length && (selectionStart = value.length - 1)
|
||||
}
|
||||
|
||||
return { selectionStart, I }
|
||||
}
|
||||
|
||||
const getNum = (value, format, regx) => {
|
||||
let len = value.length
|
||||
if (format && regx) {
|
||||
const formatMatchArr = format.match(regx)
|
||||
len = Math.max(len, formatMatchArr.join('').length)
|
||||
}
|
||||
let num = { str: '', arr: [] }
|
||||
for (let i = 0; i < len; i++) {
|
||||
let char = value.charAt(i) ? value.charAt(i) : '00'
|
||||
|
||||
if (/[0-9]/.test(char)) {
|
||||
num.str += char
|
||||
} else {
|
||||
num.arr[i] = 1
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
const getSelectionStartIndex = (event) => {
|
||||
const inputElem = event.target
|
||||
return inputElem.selectionStart - (event.data ? event.data.length : 0)
|
||||
}
|
||||
|
||||
const moveStart = (inputElem, moveStartIndex) => {
|
||||
if (inputElem.setSelectionRange) {
|
||||
inputElem.focus()
|
||||
setTimeout(() => {
|
||||
inputElem.setSelectionRange(moveStartIndex, moveStartIndex)
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
export const formatText = ({ event, text, format, needSelectionStart = false }) => {
|
||||
if (!format) return text
|
||||
let cursorOffset = 0
|
||||
let value = ''
|
||||
let regx = /yyyy|yyy|yy|y|MM|M|dd|d|HH|hh|H|h|mm|m|ss|s|WW|W|w/g
|
||||
let startIndex = 0
|
||||
let { numStr, selectionStart } = getNumAndSelectionStart({
|
||||
value: text,
|
||||
format,
|
||||
regx,
|
||||
event,
|
||||
needSelectionStart
|
||||
})
|
||||
|
||||
let matchResult = regx.exec(format)
|
||||
while (numStr.str !== '' && matchResult !== null) {
|
||||
let subStr
|
||||
let newNum
|
||||
let subLen
|
||||
const endIndex = matchResult.index
|
||||
if (startIndex >= 0) {
|
||||
value += format.substring(startIndex, endIndex)
|
||||
}
|
||||
|
||||
selectionStart >= startIndex + cursorOffset &&
|
||||
selectionStart <= endIndex + cursorOffset &&
|
||||
(selectionStart = selectionStart + endIndex - startIndex)
|
||||
|
||||
startIndex = regx.lastIndex
|
||||
subLen = startIndex - endIndex
|
||||
|
||||
subStr = numStr.str.substring(0, subLen)
|
||||
|
||||
const firstMatchChar = matchResult[0].charAt(0)
|
||||
const firstChar = parseInt(subStr.charAt(0), 10)
|
||||
|
||||
if (numStr.str.length > 1) {
|
||||
const secondChar = numStr.str.charAt(1)
|
||||
newNum = 10 * firstChar + parseInt(secondChar, 10)
|
||||
} else {
|
||||
newNum = firstChar
|
||||
}
|
||||
if (
|
||||
numStr.arr[endIndex + 1] ||
|
||||
(firstMatchChar === 'M' && newNum > 12) ||
|
||||
(firstMatchChar === 'd' && newNum > 31) ||
|
||||
(['H', 'h'].includes(firstMatchChar) && newNum > 23) ||
|
||||
('ms'.includes(firstMatchChar) && newNum > 59)
|
||||
) {
|
||||
subStr = matchResult[0].length === 2 ? '0' + firstChar : firstChar
|
||||
selectionStart++
|
||||
} else {
|
||||
if (subLen === 1) {
|
||||
subStr = String(newNum)
|
||||
subLen++
|
||||
cursorOffset++
|
||||
}
|
||||
}
|
||||
|
||||
value += subStr
|
||||
numStr.str = numStr.str.substring(subLen)
|
||||
matchResult = regx.exec(format)
|
||||
}
|
||||
|
||||
const { value: val, selectionStart: cursorPos } = checkFormat({
|
||||
value,
|
||||
format,
|
||||
startIndex,
|
||||
selectionStart,
|
||||
regx,
|
||||
needSelectionStart
|
||||
})
|
||||
value = val
|
||||
selectionStart = cursorPos
|
||||
|
||||
needSelectionStart && moveStart(event.target, selectionStart)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const getNumAndSelectionStart = ({ value, format, regx, event, needSelectionStart }) => {
|
||||
if (needSelectionStart) {
|
||||
let { selectionStart, I } = getSelectionStart({ value, format, regx, event })
|
||||
let valueStr
|
||||
|
||||
if (event.data) {
|
||||
valueStr = value.substring(0, selectionStart) + event.data + value.substring(selectionStart + I)
|
||||
selectionStart++
|
||||
} else {
|
||||
valueStr = value
|
||||
}
|
||||
|
||||
const numStr = getNum(valueStr)
|
||||
|
||||
return { numStr, selectionStart }
|
||||
} else {
|
||||
const numStr = getNum(value, format, regx)
|
||||
return { numStr }
|
||||
}
|
||||
}
|
||||
|
||||
const checkFormat = ({ value, format, startIndex, selectionStart, regx, needSelectionStart }) => {
|
||||
if (
|
||||
(!needSelectionStart && regx.lastIndex === 0) ||
|
||||
(needSelectionStart && regx.lastIndex === 0 && selectionStart >= startIndex)
|
||||
) {
|
||||
const subFormat = `(?<=${format.substring(0, startIndex)})(\\s*\\S*\\s*)+`
|
||||
const pattern = new RegExp(subFormat, 'g')
|
||||
|
||||
const res = format.match(pattern)
|
||||
|
||||
if (res) {
|
||||
value += res[0]
|
||||
selectionStart = value.length
|
||||
}
|
||||
}
|
||||
return { value, selectionStart }
|
||||
}
|
||||
|
||||
export const handleChange =
|
||||
({ api, state }) =>
|
||||
() => {
|
||||
if (state.userInput) {
|
||||
const value = api.parseString(state.displayValue)
|
||||
|
||||
if (value) {
|
||||
state.picker.state.value = value
|
||||
|
||||
|
@ -534,6 +739,7 @@ export const handleStartInput =
|
|||
const value = props.autoFormat
|
||||
? api.formatInputValue({ event, prevValue: state.displayValue[0] })
|
||||
: event.target.value
|
||||
|
||||
if (state.userInput) {
|
||||
state.userInput = [value, state.userInput[1]]
|
||||
} else {
|
||||
|
@ -754,15 +960,12 @@ export const handleKeydown =
|
|||
}
|
||||
|
||||
export const hidePicker =
|
||||
({ state, doDestroy }) =>
|
||||
({ destroyPopper, state }) =>
|
||||
() => {
|
||||
if (state.picker) {
|
||||
state.picker.resetView && state.picker.resetView()
|
||||
state.pickerVisible = state.picker.visible = state.picker.state.visible = false
|
||||
|
||||
if (isFunction(doDestroy)) {
|
||||
doDestroy()
|
||||
}
|
||||
destroyPopper()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,7 +983,7 @@ export const showPicker =
|
|||
state.pickerVisible = state.picker.state.visible = true
|
||||
state.picker.state.value = state.parsedValue
|
||||
state.picker.resetView && state.picker.resetView()
|
||||
// 使用nextTick方法解决time-picker组件的demo"下拉框类名"点击input,时间选择框弹出位置错误的问题,
|
||||
|
||||
nextTick(() => {
|
||||
updatePopper(state.picker.$el)
|
||||
state.picker.adjustSpinners && state.picker.adjustSpinners()
|
||||
|
@ -791,6 +994,7 @@ export const handlePick =
|
|||
({ state, api }) =>
|
||||
(date = '', visible = false) => {
|
||||
if (!state.picker) return
|
||||
|
||||
state.userInput = null
|
||||
state.pickerVisible = state.picker.state.visible = visible
|
||||
|
||||
|
@ -806,9 +1010,7 @@ export const handleSelectRange = (state) => (start, end, pos) => {
|
|||
}
|
||||
|
||||
const adjust = (value, start, end) => {
|
||||
if (!value) {
|
||||
return { start, end }
|
||||
}
|
||||
if (value) {
|
||||
const valueReg = /(\d+):(\d+):(\d+)(\s+.+)?/
|
||||
|
||||
if (valueReg.test(value)) {
|
||||
|
@ -827,6 +1029,7 @@ export const handleSelectRange = (state) => (start, end, pos) => {
|
|||
end = hourLength + minuteLength + secondLength + 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { start, end }
|
||||
}
|
||||
|
@ -965,7 +1168,6 @@ export const emitInput =
|
|||
}
|
||||
|
||||
const formatted = api.formatToValue(value) || val
|
||||
|
||||
if (!valueEquals(props.modelValue, formatted)) {
|
||||
emit('update:modelValue', formatted)
|
||||
}
|
||||
|
@ -1051,19 +1253,23 @@ export const computedFormat =
|
|||
|
||||
export const computedTriggerClass =
|
||||
({ props, state }) =>
|
||||
() =>
|
||||
() => {
|
||||
return (
|
||||
props.suffixIcon ||
|
||||
props.prefixIcon ||
|
||||
(state.type.includes(DATEPICKER.Time) ? DATEPICKER.IconTime : DATEPICKER.IconDate)
|
||||
)
|
||||
}
|
||||
|
||||
export const computedHaveTrigger =
|
||||
({ props }) =>
|
||||
() =>
|
||||
typeof props.showTrigger !== 'undefined' ? props.showTrigger : DATEPICKER.TriggerTypes.includes(props.type)
|
||||
() => {
|
||||
return typeof props.showTrigger !== 'undefined' ? props.showTrigger : DATEPICKER.TriggerTypes.includes(props.type)
|
||||
}
|
||||
|
||||
export const initPopper = ({ props, hooks, vnode }) => {
|
||||
const { reactive, watch, toRefs, onBeforeUnmount, onDeactivated } = hooks
|
||||
// vnode就是第3参,名字有误导性
|
||||
// tiny提示: vnode就是第3参,名字有误导性
|
||||
const { emit, vm, slots, nextTick } = vnode
|
||||
const placementMap = DATEPICKER.PlacementMap
|
||||
|
||||
|
@ -1073,7 +1279,7 @@ export const initPopper = ({ props, hooks, vnode }) => {
|
|||
emit,
|
||||
props: {
|
||||
...props,
|
||||
popperOptions: { boundariesPadding: 0, gpuAcceleration: false },
|
||||
popperOptions: Object.assign({ boundariesPadding: 0, gpuAcceleration: false }, props.popperOptions),
|
||||
visibleArrow: true,
|
||||
offset: 0,
|
||||
boundariesPadding: 5,
|
||||
|
@ -1163,203 +1369,3 @@ export const setInputPaddingLeft =
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getSelectionStart = ({ value, format, regx, event }) => {
|
||||
const formatMatchArr = format.match(regx)
|
||||
let selectionStart = getSelectionStartIndex(event)
|
||||
let I = 0
|
||||
|
||||
if (value !== '') {
|
||||
const match = value.match(/[0-9]/g)
|
||||
I = match === null ? 0 : match.length
|
||||
|
||||
for (let i = 0; i < formatMatchArr.length; i++) {
|
||||
I -= Math.max(formatMatchArr[i].length, 2)
|
||||
}
|
||||
|
||||
I = I >= 0 ? 1 : 0
|
||||
I === 1 && selectionStart >= value.length && (selectionStart = value.length - 1)
|
||||
}
|
||||
|
||||
return { selectionStart, I }
|
||||
}
|
||||
|
||||
const getNum = (value, format, regx) => {
|
||||
let len = value.length
|
||||
if (format && regx) {
|
||||
const formatMatchArr = format.match(regx)
|
||||
len = Math.max(len, formatMatchArr.join('').length)
|
||||
}
|
||||
let num = { str: '', arr: [] }
|
||||
for (let i = 0; i < len; i++) {
|
||||
let char = value.charAt(i) ? value.charAt(i) : '00'
|
||||
|
||||
if (/[0-9]/.test(char)) {
|
||||
num.str += char
|
||||
} else {
|
||||
num.arr[i] = 1
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
const getSelectionStartIndex = (event) => {
|
||||
const inputElem = event.target
|
||||
return inputElem.selectionStart - (event.data ? event.data.length : 0)
|
||||
}
|
||||
|
||||
const getNumAndSelectionStart = ({ value, format, regx, event, needSelectionStart }) => {
|
||||
if (needSelectionStart) {
|
||||
let { selectionStart, I } = getSelectionStart({ value, format, regx, event })
|
||||
let valueStr
|
||||
|
||||
if (event.data) {
|
||||
valueStr = value.substring(0, selectionStart) + event.data + value.substring(selectionStart + I)
|
||||
selectionStart++
|
||||
} else {
|
||||
valueStr = value
|
||||
}
|
||||
|
||||
const numStr = getNum(valueStr)
|
||||
|
||||
return { numStr, selectionStart }
|
||||
} else {
|
||||
const numStr = getNum(value, format, regx)
|
||||
return { numStr }
|
||||
}
|
||||
}
|
||||
|
||||
const checkFormat = ({ value, format, startIndex, selectionStart, regx, needSelectionStart }) => {
|
||||
if (
|
||||
(!needSelectionStart && regx.lastIndex === 0) ||
|
||||
(needSelectionStart && regx.lastIndex === 0 && selectionStart >= startIndex)
|
||||
) {
|
||||
const subFormat = `(?<=${format.substring(0, startIndex)})(\\s*\\S*\\s*)+`
|
||||
const pattern = new RegExp(subFormat, 'g')
|
||||
|
||||
const res = format.match(pattern)
|
||||
|
||||
if (res) {
|
||||
value += res[0]
|
||||
selectionStart = value.length
|
||||
}
|
||||
}
|
||||
return { value, selectionStart }
|
||||
}
|
||||
|
||||
const moveStart = (inputElem, moveStartIndex) => {
|
||||
if (inputElem.setSelectionRange) {
|
||||
inputElem.focus()
|
||||
setTimeout(() => {
|
||||
inputElem.setSelectionRange(moveStartIndex, moveStartIndex)
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// 这个是 input 组件的 input 事件,应该只有一个 event 参数,input 组件的具体值从 event.target.value 中获取。
|
||||
export const handleInput =
|
||||
({ state, props, api }) =>
|
||||
(val, event) => {
|
||||
// 兼容tiny-input传参不同导致的报错问题
|
||||
event = val.target ? val : event
|
||||
if (props.autoFormat) {
|
||||
const value = api.formatInputValue({ event, prevValue: state.displayValue })
|
||||
state.userInput = value
|
||||
} else {
|
||||
const val = event.target.value
|
||||
state.userInput = val
|
||||
}
|
||||
}
|
||||
|
||||
export const formatInputValue =
|
||||
({ props, state }) =>
|
||||
({ event, prevValue = '' }) => {
|
||||
const val = event.target.value
|
||||
const inputData = event.data
|
||||
const format = state.type === 'time-select' ? 'HH:mm' : props.format || DATEPICKER.DateFormats[state.type]
|
||||
if (inputData && inputData.charCodeAt() >= 48 && inputData.charCodeAt() <= 57) {
|
||||
return formatText({ event, format, text: prevValue, needSelectionStart: true })
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
export const formatText = ({ event, text, format, needSelectionStart = false }) => {
|
||||
if (!format) return text
|
||||
let cursorOffset = 0
|
||||
let value = ''
|
||||
let regx = /yyyy|yyy|yy|y|MM|M|dd|d|HH|hh|H|h|mm|m|ss|s|WW|W|w/g
|
||||
let startIndex = 0
|
||||
let { numStr, selectionStart } = getNumAndSelectionStart({
|
||||
value: text,
|
||||
format,
|
||||
regx,
|
||||
event,
|
||||
needSelectionStart
|
||||
})
|
||||
|
||||
let matchResult = regx.exec(format)
|
||||
while (numStr.str !== '' && matchResult !== null) {
|
||||
let subStr
|
||||
let newNum
|
||||
let subLen
|
||||
const endIndex = matchResult.index
|
||||
if (startIndex >= 0) {
|
||||
value += format.substring(startIndex, endIndex)
|
||||
}
|
||||
|
||||
selectionStart >= startIndex + cursorOffset &&
|
||||
selectionStart <= endIndex + cursorOffset &&
|
||||
(selectionStart = selectionStart + endIndex - startIndex)
|
||||
|
||||
startIndex = regx.lastIndex
|
||||
subLen = startIndex - endIndex
|
||||
|
||||
subStr = numStr.str.substring(0, subLen)
|
||||
|
||||
const firstMatchChar = matchResult[0].charAt(0)
|
||||
const firstChar = parseInt(subStr.charAt(0), 10)
|
||||
|
||||
if (numStr.str.length > 1) {
|
||||
const secondChar = numStr.str.charAt(1)
|
||||
newNum = 10 * firstChar + parseInt(secondChar, 10)
|
||||
} else {
|
||||
newNum = firstChar
|
||||
}
|
||||
if (
|
||||
numStr.arr[endIndex + 1] ||
|
||||
(firstMatchChar === 'M' && newNum > 12) ||
|
||||
(firstMatchChar === 'd' && newNum > 31) ||
|
||||
(['H', 'h'].includes(firstMatchChar) && newNum > 23) ||
|
||||
('ms'.includes(firstMatchChar) && newNum > 59)
|
||||
) {
|
||||
subStr = matchResult[0].length === 2 ? '0' + firstChar : firstChar
|
||||
selectionStart++
|
||||
} else {
|
||||
if (subLen === 1) {
|
||||
subStr = String(newNum)
|
||||
subLen++
|
||||
cursorOffset++
|
||||
}
|
||||
}
|
||||
|
||||
value += subStr
|
||||
numStr.str = numStr.str.substring(subLen)
|
||||
matchResult = regx.exec(format)
|
||||
}
|
||||
|
||||
const { value: val, selectionStart: cursorPos } = checkFormat({
|
||||
value,
|
||||
format,
|
||||
startIndex,
|
||||
selectionStart,
|
||||
regx,
|
||||
needSelectionStart
|
||||
})
|
||||
value = val
|
||||
selectionStart = cursorPos
|
||||
|
||||
needSelectionStart && moveStart(event.target, selectionStart)
|
||||
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
watchIsRange,
|
||||
parseAsFormatAndType,
|
||||
watchPickerVisible,
|
||||
watchMobileVisible,
|
||||
getValueEmpty,
|
||||
getMode,
|
||||
displayValue,
|
||||
|
@ -177,7 +178,7 @@ const initState = ({ api, reactive, vm, computed, props, utils, parent, breakpoi
|
|||
const initApi = ({ api, props, hooks, state, vnode, others, utils, parent }) => {
|
||||
const { t, emit, dispatch, nextTick, vm } = vnode
|
||||
const { TimePanel, TimeRangePanel } = others
|
||||
const { destroyPopper, popperElm, updatePopper, doDestroy } = initPopper({ props, hooks, vnode })
|
||||
const { destroyPopper, popperElm, updatePopper } = initPopper({ props, hooks, vnode })
|
||||
|
||||
state.popperElm = popperElm
|
||||
state.picker = null
|
||||
|
@ -185,7 +186,7 @@ const initApi = ({ api, props, hooks, state, vnode, others, utils, parent }) =>
|
|||
Object.assign(api, {
|
||||
destroyPopper,
|
||||
emitDbTime: emitDbTime({ emit, state, t }),
|
||||
hidePicker: hidePicker({ state, doDestroy }),
|
||||
hidePicker: hidePicker({ destroyPopper, state }),
|
||||
handleSelectChange: ({ tz, date }) => !state.ranged && emit('select-change', { tz, date }),
|
||||
getPanel: getPanel(others),
|
||||
handleFocus: handleFocus({ emit, vm, state, api }),
|
||||
|
@ -211,7 +212,8 @@ const initApi = ({ api, props, hooks, state, vnode, others, utils, parent }) =>
|
|||
handleClose: handleClose({ api, props, state }),
|
||||
displayValue: displayValue({ api, props, state }),
|
||||
handlePick: handlePick({ api, state }),
|
||||
watchPickerVisible: watchPickerVisible({ api, vm, dispatch, emit, props, state }),
|
||||
watchPickerVisible: watchPickerVisible({ api, vm, dispatch, emit, props, state, nextTick }),
|
||||
watchMobileVisible: watchMobileVisible({ api, props, state }),
|
||||
formatToString: formatToString({ api, state }),
|
||||
watchIsRange: watchIsRange({ api, state, TimePanel, TimeRangePanel }),
|
||||
mountPicker: mountPicker({ api, vm, props, state, updatePopper }),
|
||||
|
@ -226,6 +228,7 @@ const initApi = ({ api, props, hooks, state, vnode, others, utils, parent }) =>
|
|||
initApi2({ api, props, state, t, parent })
|
||||
initMobileApi({ api, props, state, t, parent })
|
||||
}
|
||||
|
||||
const initApi2 = ({ api, props, state, t, parent }) => {
|
||||
Object.assign(api, {
|
||||
t,
|
||||
|
@ -268,6 +271,8 @@ const initWatch = ({ api, state, props, watch, markRaw }) => {
|
|||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(() => [state.dateMobileOption.visible, state.timeMobileOption.visible], api.watchMobileVisible)
|
||||
|
||||
watch(() => state.pickerVisible, api.watchPickerVisible)
|
||||
|
||||
watch(
|
||||
|
|
|
@ -813,7 +813,7 @@ export const doSuggesst =
|
|||
api.sourceGridSelectChange({ checked: false, row, confirm: false })
|
||||
})
|
||||
|
||||
if (addtions.length) {
|
||||
if (!state.suggestList.length || addtions.length) {
|
||||
doQuery(query)
|
||||
}
|
||||
} else {
|
||||
|
@ -829,7 +829,7 @@ export const closeSuggestPanel =
|
|||
const popper = vm.$refs.popper
|
||||
let keep = !event
|
||||
|
||||
if (event.target) {
|
||||
if (event.target && reference) {
|
||||
keep = reference.$el.contains(event.target) || popper.contains(event.target)
|
||||
}
|
||||
|
||||
|
|
|
@ -494,38 +494,14 @@ export const getPluginOption =
|
|||
return items
|
||||
}
|
||||
|
||||
// tiny 修改: aui的 toggleCheckAll 在designConfig, 同步时要更新
|
||||
export const toggleCheckAll =
|
||||
({ api, state, props }) =>
|
||||
(filtered) => {
|
||||
// tiny 移入内部
|
||||
const getEnabledValues = (options) => {
|
||||
let values = []
|
||||
|
||||
// tiny 新增 避免全不选时,将disabled的项目勾掉
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const isEnabled = !options[i].state.disabled && !options[i].state.groupDisabled
|
||||
const isRequired = options[i].required
|
||||
const isDisabledAndChecked = !isEnabled && options[i].state.selectCls === 'checked-sur'
|
||||
|
||||
if (state.isSelectAll) {
|
||||
// 取消选中全部,必填和禁用且选中项不可取消
|
||||
if (isRequired || isDisabledAndChecked) {
|
||||
values.push(options[i].value)
|
||||
}
|
||||
} else {
|
||||
// 选中全部,非禁用项 和 必填项和 禁用且选中项 需选中
|
||||
if (isEnabled || isRequired || isDisabledAndChecked) {
|
||||
values.push(options[i].value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
let value
|
||||
const enabledValues = getEnabledValues(state.options)
|
||||
let value = []
|
||||
// 1. 需要控制勾选或去勾选的项
|
||||
const enabledValues = state.options
|
||||
.filter((op) => !op.state.disabled && !op.state.groupDisabled && !op.required && op.state.visible)
|
||||
.map((op) => op.value)
|
||||
|
||||
if (filtered) {
|
||||
if (state.filteredSelectCls === 'check' || state.filteredSelectCls === 'halfselect') {
|
||||
|
@ -541,10 +517,18 @@ export const toggleCheckAll =
|
|||
|
||||
unchecked.length ? (value = enabledValues) : (value = [])
|
||||
} else if (state.selectCls === 'checked-sur') {
|
||||
// tiny 新增
|
||||
value = getEnabledValues(state.options)
|
||||
value = []
|
||||
}
|
||||
}
|
||||
// 2. 必选项
|
||||
const requiredValue = state.options.filter((op) => op.required).map((op) => op.value)
|
||||
|
||||
// 3. 禁用且已设置为勾选的项
|
||||
const disabledSelectedValues = state.options
|
||||
.filter((op) => (op.state.disabled || op.state.groupDisabled) && op.state.selectCls === 'checked-sur')
|
||||
.map((op) => op.value)
|
||||
|
||||
value = [...value, ...requiredValue, ...disabledSelectedValues]
|
||||
|
||||
api.setSoftFocus()
|
||||
|
||||
|
@ -1278,10 +1262,9 @@ export const watchValue =
|
|||
}
|
||||
|
||||
if (props.filterable && !props.reserveKeyword) {
|
||||
const isChange = false
|
||||
const isInput = true
|
||||
props.renderType !== constants.TYPE.Grid && (state.query = '')
|
||||
api.handleQueryChange(state.query, isChange, isInput)
|
||||
// tiny 优化: 多选且props.reserveKeyword为false时, aui此处会多请求一次
|
||||
// searchable时,不清空query, 这样才能保持搜索结果
|
||||
props.renderType !== constants.TYPE.Grid && !props.searchable && (state.query = '')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1549,7 +1532,7 @@ export const queryVisibleOptions =
|
|||
if (props.optimization) {
|
||||
return optmzApis.queryVisibleOptions(vm, isMobileFirstMode)
|
||||
} else {
|
||||
return Array.from(vm.$refs.scrollbar.$el.querySelectorAll('[data-index]:not([style*="display: none"])'))
|
||||
return Array.from(vm.$refs.scrollbar?.$el.querySelectorAll('[data-index]:not([style*="display: none"])') || [])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1839,11 +1822,16 @@ export const watchHoverIndex =
|
|||
}
|
||||
|
||||
export const handleDropdownClick =
|
||||
({ emit }) =>
|
||||
({ vm, state, props, emit }) =>
|
||||
($event) => {
|
||||
emit('dropdown-click', $event)
|
||||
if (props.allowCopy && vm.$refs.reference) {
|
||||
vm.$refs.reference.$el.querySelector('input').selectionEnd = 0
|
||||
}
|
||||
|
||||
state.softFocus = false
|
||||
|
||||
emit('dropdown-click', $event)
|
||||
}
|
||||
export const handleEnterTag =
|
||||
({ state }) =>
|
||||
($event, key) => {
|
||||
|
|
|
@ -169,7 +169,7 @@ export const api = [
|
|||
'clearSearchText'
|
||||
]
|
||||
|
||||
const initState = ({ reactive, computed, props, api, emitter, parent, constants, useBreakpoint, vm }) => {
|
||||
const initState = ({ reactive, computed, props, api, emitter, parent, constants, useBreakpoint, vm, designConfig }) => {
|
||||
const stateAdd = initStateAdd({ computed, props, api, parent })
|
||||
const state = reactive({
|
||||
...stateAdd,
|
||||
|
@ -226,7 +226,13 @@ const initState = ({ reactive, computed, props, api, emitter, parent, constants,
|
|||
// tiny 新增
|
||||
getIcon: computed(() => api.computedGetIcon()),
|
||||
getTagType: computed(() => api.computedGetTagType()),
|
||||
isSelectAll: computed(() => state.selectCls === 'checked-sur')
|
||||
isSelectAll: computed(() => state.selectCls === 'checked-sur'),
|
||||
autoHideDownIcon: (() => {
|
||||
if (designConfig?.state && 'autoHideDownIcon' in designConfig.state) {
|
||||
return designConfig.state.autoHideDownIcon
|
||||
}
|
||||
return true // tiny 默认为true
|
||||
})()
|
||||
})
|
||||
|
||||
return state
|
||||
|
@ -431,7 +437,7 @@ const addApi = ({
|
|||
mounted: mounted({ api, parent, state, props, vm, designConfig }),
|
||||
unMount: unMount({ api, parent, vm, state }),
|
||||
watchOptimizeOpts: watchOptimizeOpts({ props, state }),
|
||||
handleDropdownClick: handleDropdownClick({ emit }),
|
||||
handleDropdownClick: handleDropdownClick({ props, vm, state, emit }),
|
||||
handleEnterTag: handleEnterTag({ state }),
|
||||
calcCollapseTags: calcCollapseTags({ state, vm }),
|
||||
initValue: initValue({ state }),
|
||||
|
@ -555,8 +561,19 @@ export const renderless = (
|
|||
{ computed, onBeforeUnmount, onMounted, reactive, watch, provide, inject },
|
||||
{ vm, parent, emit, constants, nextTick, dispatch, t, emitter, isMobileFirstMode, useBreakpoint, designConfig }
|
||||
) => {
|
||||
const api = {}
|
||||
const state = initState({ reactive, computed, props, api, emitter, parent, constants, useBreakpoint, vm })
|
||||
const api: any = {}
|
||||
const state = initState({
|
||||
reactive,
|
||||
computed,
|
||||
props,
|
||||
api,
|
||||
emitter,
|
||||
parent,
|
||||
constants,
|
||||
useBreakpoint,
|
||||
vm,
|
||||
designConfig
|
||||
})
|
||||
const dialog = inject('dialog', null)
|
||||
|
||||
provide('selectEmitter', state.selectEmitter)
|
||||
|
@ -579,9 +596,7 @@ export const renderless = (
|
|||
isMobileFirstMode,
|
||||
designConfig
|
||||
})
|
||||
initWatch({ watch, props, api, state, nextTick })
|
||||
onMounted(api.mounted)
|
||||
onBeforeUnmount(api.unMount)
|
||||
|
||||
parent.$on('handle-clear', (event) => {
|
||||
api.handleClearClick(event)
|
||||
})
|
||||
|
@ -599,5 +614,14 @@ export const renderless = (
|
|||
state.selectEmitter.on(constants.EVENT_NAME.setSelected, api.setSelected)
|
||||
state.selectEmitter.on(constants.EVENT_NAME.initValue, api.initValue)
|
||||
|
||||
initWatch({ watch, props, api, state, nextTick })
|
||||
|
||||
onMounted(api.mounted)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
api.unMount()
|
||||
dialog && dialog.state.emitter.off('handleSelectClose', api.handleClose)
|
||||
})
|
||||
|
||||
return api
|
||||
}
|
||||
|
|
|
@ -349,6 +349,7 @@ export const addNode =
|
|||
state.tree.state.emitter.emit('tree-node-add', event, node)
|
||||
}
|
||||
|
||||
// tiny 新增
|
||||
export const computedExpandIcon =
|
||||
({ designConfig }) =>
|
||||
(treeRoot, state) => {
|
||||
|
@ -356,6 +357,7 @@ export const computedExpandIcon =
|
|||
return state.tree.icon
|
||||
}
|
||||
|
||||
// tiny 新增的判断。 显示线时强制切换图标,仅smb定制了
|
||||
if (treeRoot.showLine) {
|
||||
const expandIcon = designConfig?.icons?.expanded || 'icon-minus-square'
|
||||
const collapseIcon = designConfig?.icons?.collapse || 'icon-plus-square'
|
||||
|
@ -364,7 +366,7 @@ export const computedExpandIcon =
|
|||
|
||||
return 'icon-chevron-right'
|
||||
}
|
||||
|
||||
// tiny 新增
|
||||
export const computedIndent =
|
||||
() =>
|
||||
({ node, showLine }, { tree }) => {
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
deleteNode,
|
||||
onSiblingToggleExpand,
|
||||
watchExpandedChange,
|
||||
// tiny 新增
|
||||
computedExpandIcon,
|
||||
computedIndent
|
||||
} from './index'
|
||||
|
|
|
@ -250,7 +250,7 @@ export const updateOptions =
|
|||
export const autoSelect =
|
||||
({ props, state, nextTick }) =>
|
||||
(usersList) => {
|
||||
if (!usersList.length) {
|
||||
if (!usersList.length || (props.multiple && props.multipleLimit && state.user.length >= props.multipleLimit)) {
|
||||
return nextTick()
|
||||
}
|
||||
|
||||
|
|
|
@ -138,12 +138,16 @@
|
|||
@apply text-base;
|
||||
@apply items-center;
|
||||
|
||||
.@{drawer-prefix-cls}__title {
|
||||
.@{drawer-prefix-cls}__header-left {
|
||||
@apply ~'max-w-[80%]';
|
||||
|
||||
// 标题增加帮助提示, 勿覆盖
|
||||
.@{drawer-prefix-cls}__title {
|
||||
@apply pr-4;
|
||||
@apply text-left;
|
||||
@apply truncate;
|
||||
}
|
||||
}
|
||||
|
||||
.@{drawer-prefix-cls}__header-right {
|
||||
@apply flex-1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"version": "1.0.0",
|
||||
"themeName": "华为SaaS设计系统主题",
|
||||
"themeName": "SaaS设计系统主题",
|
||||
"themeColor": [
|
||||
{
|
||||
"mode": "light",
|
||||
|
|
|
@ -150,7 +150,6 @@
|
|||
border-bottom: 1px solid var(--ti-drawer-divider-border-color);
|
||||
|
||||
.@{drawer-prefix-cls}__title {
|
||||
max-width: 80%;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -161,7 +160,7 @@
|
|||
}
|
||||
|
||||
.@{drawer-prefix-cls}__header-left {
|
||||
flex: 1;
|
||||
max-width: 80%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 16px;
|
||||
|
|
|
@ -425,6 +425,10 @@
|
|||
transform: rotate(0);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-leaf {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
)
|
||||
"
|
||||
:tabindex="tabindex"
|
||||
v-bind="a($attrs, ['class', 'style'], true)"
|
||||
v-bind="a($attrs, ['class', 'style', 'id'], true)"
|
||||
>
|
||||
<icon-loading v-if="loading" :class="gcls('loading-svg')" />
|
||||
<component
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
]"
|
||||
:tabindex="tabindex"
|
||||
v-bind="a($attrs, ['class', 'style'], true)"
|
||||
v-bind="a($attrs, ['class', 'style', 'title', 'id'], true)"
|
||||
>
|
||||
<icon-loading v-if="loading" class="tiny-icon-loading tiny-svg-size" />
|
||||
<component v-if="icon && !loading" :is="icon" :class="{ 'is-text': text || slots.default }" />
|
||||
|
|
|
@ -100,7 +100,8 @@ import type { ICheckboxApi } from '@opentiny/vue-renderless/types/checkbox.type'
|
|||
import Tooltip from '@opentiny/vue-tooltip'
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['update:modelValue', 'change', 'complete', 'click'],
|
||||
// tiny 新增。 renderless中,没有emit('click')的地方。 此处勿声明,否则会造成丢失click事件。
|
||||
emits: ['update:modelValue', 'change', 'complete'],
|
||||
props: [
|
||||
...props,
|
||||
'modelValue',
|
||||
|
|
|
@ -773,7 +773,7 @@ export const Cell = {
|
|||
renderEditHeader(h, params) {
|
||||
let { $table, column } = params
|
||||
let { editConfig, editRules, validOpts } = $table
|
||||
let { filter, remoteSort, sortable, type } = column
|
||||
let { filter, remoteSort, sortable, type, own } = column
|
||||
let icon = GLOBAL_CONFIG.icon
|
||||
let isRequired
|
||||
|
||||
|
@ -799,7 +799,7 @@ export const Cell = {
|
|||
|
||||
let vNodes = [
|
||||
isRequired && showAsterisk ? h('i', { class: `tiny-icon ${icon.required}` }) : null,
|
||||
!editConfig || !column.showIcon ? null : h(icon.edit, { class: 'tiny-grid-edit-icon tiny-svg-size' })
|
||||
!editConfig || !own.showIcon ? null : h(icon.edit, { class: 'tiny-grid-edit-icon tiny-svg-size' })
|
||||
]
|
||||
|
||||
vNodes = vNodes.concat(Cell.renderHeader(h, params))
|
||||
|
|
|
@ -57,7 +57,7 @@ export const createHandlerOnEnd = ({ _vm, refresh }) => {
|
|||
if (insertRecords.length) {
|
||||
return false
|
||||
}
|
||||
const options = { children: 'children' }
|
||||
const options = { children: (_vm.treeConfig || {}).children || 'children' }
|
||||
const targetTrElem = event.item
|
||||
const { parentNode: wrapperElem, previousElementSibling: prevTrElem } = targetTrElem
|
||||
// 这里优先使用用户通过props传递过来的表格数据,所以拖拽后会改变原始数据
|
||||
|
|
|
@ -176,6 +176,7 @@ export default {
|
|||
name: `${$prefix}GridFooter`,
|
||||
props: {
|
||||
fixedColumn: Array,
|
||||
fixedType: String,
|
||||
footerData: Array,
|
||||
size: String,
|
||||
tableColumn: Array,
|
||||
|
@ -193,7 +194,7 @@ export default {
|
|||
elemStore[`${keyPrefix}x-space`] = $refs.xSpace
|
||||
},
|
||||
render() {
|
||||
let { $parent: $table, buildParamFunc, footerData, tableColumn } = this
|
||||
let { $parent: $table, buildParamFunc, fixedColumn, fixedType, footerData, tableColumn } = this
|
||||
let {
|
||||
align: allAlign,
|
||||
columnKey,
|
||||
|
@ -203,7 +204,7 @@ export default {
|
|||
footerSpanMethod,
|
||||
columnStore
|
||||
} = $table
|
||||
let { overflowX, showOverflow: allColumnOverflow, tableLayout, tableListeners } = $table
|
||||
let { overflowX, showOverflow: allColumnOverflow, tableLayout, tableListeners, renderFooter } = $table
|
||||
|
||||
let tableAttrs = { cellspacing: 0, cellpadding: 0, border: 0 }
|
||||
let colgroupVNode = renderColgroup(tableColumn)
|
||||
|
@ -219,6 +220,8 @@ export default {
|
|||
}
|
||||
let tfootVNode = renderTfoot(Object.assign(arg1, arg2))
|
||||
|
||||
const renderParams = { $table, columns: tableColumn, footerData, fixedColumns: fixedColumn, fixedType }
|
||||
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
|
@ -227,7 +230,9 @@ export default {
|
|||
},
|
||||
[
|
||||
h('div', { class: 'tiny-grid-body__x-space', ref: 'xSpace' }),
|
||||
h(
|
||||
typeof renderFooter === 'function'
|
||||
? renderFooter(renderParams, h)
|
||||
: h(
|
||||
'table',
|
||||
{
|
||||
class: 'tiny-grid__footer',
|
||||
|
|
|
@ -33,7 +33,9 @@ export default {
|
|||
this.recalculate()
|
||||
}, GlobalConfig.resizeInterval)
|
||||
|
||||
resizeObserver.observe(this.getParentElem())
|
||||
const parentElem = this.getParentElem()
|
||||
|
||||
parentElem && resizeObserver.observe(parentElem)
|
||||
this.$resize = resizeObserver
|
||||
},
|
||||
unbindResize() {
|
||||
|
|
|
@ -141,7 +141,7 @@ const setTotalRows = (_vm) => {
|
|||
}
|
||||
|
||||
const getTotalRows = (_vm) => {
|
||||
const { afterFullData, scrollYLoad, treeConfig } = _vm
|
||||
const { afterFullData, scrollYLoad, scrollLoad, treeConfig } = _vm
|
||||
let totalRows = afterFullData.length
|
||||
|
||||
if (scrollYLoad && treeConfig) {
|
||||
|
@ -152,6 +152,11 @@ const getTotalRows = (_vm) => {
|
|||
totalRows = TOTALROWS_MAP.get(_vm)
|
||||
}
|
||||
|
||||
// 滚动分页场景总行数由(afterFullData.length)调整为(scrollLoad.pageSize),解决最后一页数据不足时滚动条位置改变问题
|
||||
if (scrollLoad) {
|
||||
totalRows = scrollLoad.pageSize || 10
|
||||
}
|
||||
|
||||
return totalRows
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import RichText from './src/pc.vue'
|
||||
import '@opentiny/vue-theme/rich-text/index.css'
|
||||
|
||||
RichText.model = {
|
||||
prop: 'modelValue',
|
||||
event: 'update:modelValue'
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
RichText.install = function (Vue) {
|
||||
Vue.component(RichText.name, RichText)
|
||||
}
|
||||
|
||||
RichText.version = process.env.COMPONENT_VERSION
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (process.env.BUILD_TARGET === 'runtime') {
|
||||
if (typeof window !== 'undefined' && window.Vue) {
|
||||
RichText.install(window.Vue)
|
||||
}
|
||||
}
|
||||
|
||||
export default RichText
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "@opentiny/vue-rich-text",
|
||||
"version": "3.14.0",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "index.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "^0.31.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm -w build:ui $npm_package_name",
|
||||
"//postversion": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/vue-icon": "workspace:~",
|
||||
"@opentiny/vue-common": "workspace:~",
|
||||
"@opentiny/vue-locale": "workspace:~",
|
||||
"quill": "^1.3.7"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<div class="quill-editor" :class="{ 'is-display-only': state.isDisplayOnly }">
|
||||
<slot name="toolbar"></slot>
|
||||
<div ref="editor" @paste="handlePaste"></div>
|
||||
<div class="toolbar-icon">
|
||||
<icon-fileupload ref="iconFile"></icon-fileupload>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { $prefix, setup, defineComponent } from '@opentiny/vue-common'
|
||||
import Quill from 'quill'
|
||||
import ImageDrop from '@opentiny/vue-renderless/rich-text/module/image-drop'
|
||||
import ImageUpload from '@opentiny/vue-renderless/rich-text/module/image-upload'
|
||||
import FileUpload from '@opentiny/vue-renderless/rich-text/module/file-upload'
|
||||
import Modal from '@opentiny/vue-modal'
|
||||
import { IconFileupload } from '@opentiny/vue-icon'
|
||||
import { renderless, api } from '@opentiny/vue-renderless/rich-text/vue'
|
||||
|
||||
const $constants = {
|
||||
MAX_LENGTH: Number.MAX_SAFE_INTEGER
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: $prefix + 'RichText',
|
||||
components: {
|
||||
IconFileupload: IconFileupload()
|
||||
},
|
||||
props: {
|
||||
_constants: {
|
||||
type: Object,
|
||||
default: () => $constants
|
||||
},
|
||||
content: String,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fileUpload: Object,
|
||||
globalOptions: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
imageDrop: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
imageUpload: Object,
|
||||
keepClass: [String, Array],
|
||||
modelValue: String,
|
||||
options: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
tableModule: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maxLength: {
|
||||
type: Number
|
||||
},
|
||||
displayOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
return setup({
|
||||
props,
|
||||
context,
|
||||
renderless,
|
||||
api,
|
||||
mono: true,
|
||||
extendOptions: {
|
||||
Quill,
|
||||
ImageDrop,
|
||||
ImageUpload,
|
||||
FileUpload,
|
||||
Modal
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -190,10 +190,10 @@
|
|||
</template>
|
||||
</tiny-tooltip>
|
||||
</span>
|
||||
|
||||
<!-- tiny 新增:searchable时, 这里不显示 state.query -->
|
||||
<input
|
||||
ref="input"
|
||||
v-if="filterable && !state.selectDisabled"
|
||||
v-show="filterable && !searchable && !state.selectDisabled"
|
||||
v-model="state.query"
|
||||
type="text"
|
||||
class="tiny-select__input"
|
||||
|
@ -272,10 +272,15 @@
|
|||
@click="handleClearClick"
|
||||
@mouseenter="state.inputHovering = true"
|
||||
></icon-close>
|
||||
<!-- tiny 新增 自定义getIcon . tiny 显示 close时, 不显示向下的箭头。 aui是同时显示2个, 待使用designConfig解决这个 -->
|
||||
<!-- tiny 新增 自定义getIcon .
|
||||
tiny 的 autoHideDownIcon=true, 显示 close时, 不显示向下的箭头。
|
||||
aui是同时显示2个。 -->
|
||||
<component
|
||||
v-else
|
||||
v-show="!(remote && filterable && !remoteConfig.showIcon)"
|
||||
v-show="
|
||||
state.autoHideDownIcon
|
||||
? !state.showClose && !(remote && filterable && !remoteConfig.showIcon)
|
||||
: !(remote && filterable && !remoteConfig.showIcon)
|
||||
"
|
||||
:is="state.getIcon.icon"
|
||||
:class="[
|
||||
'tiny-svg-size',
|
||||
|
@ -424,11 +429,8 @@
|
|||
v-show="state.options.length > 0 && !loading"
|
||||
>
|
||||
<slot name="dropdown"></slot>
|
||||
<!-- tiny 新增 : !filterable 的判断 有过滤时,不显示全部。 aui没有该判断 -->
|
||||
<li
|
||||
v-if="
|
||||
multiple && showCheck && showAlloption && !state.multipleLimit && !state.query && !remote && !filterable
|
||||
"
|
||||
v-if="multiple && showCheck && showAlloption && !state.multipleLimit && !state.query && !remote"
|
||||
class="tiny-option tiny-select-dropdown__item"
|
||||
data-tag="tiny-select-dropdown-item"
|
||||
:class="[
|
||||
|
@ -443,9 +445,9 @@
|
|||
>
|
||||
<!-- <component :is="`icon-${state.selectCls}`" :class="['tiny-svg-size', state.selectCls]" />
|
||||
<span>{{ t('ui.base.all') }}</span> -->
|
||||
<!-- tiny 新增: 使用checkbox 代替 svg -->
|
||||
<!-- tiny 新增: 使用checkbox 代替 svg , 列表模式 -->
|
||||
<tiny-checkbox
|
||||
:model-value="state.isSelectAll"
|
||||
:model-value="state.selectCls === 'checked-sur'"
|
||||
:indeterminate="state.selectCls === 'halfselect'"
|
||||
:class="state.selectCls"
|
||||
>
|
||||
|
@ -460,8 +462,7 @@
|
|||
!state.multipleLimit &&
|
||||
state.query &&
|
||||
!state.emptyText &&
|
||||
!remote &&
|
||||
!filterable
|
||||
!remote
|
||||
"
|
||||
class="tiny-option tiny-select-dropdown__item"
|
||||
data-tag="tiny-select-dropdown-item"
|
||||
|
@ -477,9 +478,9 @@
|
|||
>
|
||||
<!-- <component :is="`icon-${state.filteredSelectCls}`" :class="['tiny-svg-size', state.filteredSelectCls]" />
|
||||
<span>{{ t('ui.base.all') }}</span> -->
|
||||
<!-- tiny 新增: 使用checkbox 代替 svg -->
|
||||
<!-- tiny 新增: 使用checkbox 代替 svg,过滤模式 -->
|
||||
<tiny-checkbox
|
||||
:model-value="state.isSelectAll"
|
||||
:model-value="state.filteredSelectCls === 'checked-sur'"
|
||||
:indeterminate="state.filteredSelectCls === 'halfselect'"
|
||||
:class="state.selectCls"
|
||||
>
|
||||
|
|
|
@ -70,6 +70,7 @@ export const tabsProps = {
|
|||
|
||||
export default defineComponent({
|
||||
name: $prefix + 'Tabs',
|
||||
emits: ['tab-nav-update'],
|
||||
props: tabsProps,
|
||||
setup(props, context) {
|
||||
return $setup({ props, context, template })
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<span
|
||||
v-if="!node.isLeaf"
|
||||
:class="['tree-node-icon', { 'is-disabled': node.disabled }]"
|
||||
@click="handleExpandIconClick($event, node)"
|
||||
>
|
||||
|
|
|
@ -85,6 +85,10 @@ export const uploadListProps = {
|
|||
lockScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multipleLimit: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
:placeholder="placeholder"
|
||||
:collapse-tags="collapseTags"
|
||||
:multiple="multiple"
|
||||
:multipleLimit="multipleLimit"
|
||||
@change="userChange"
|
||||
:loading="state.loading"
|
||||
filterable
|
||||
|
@ -123,7 +124,8 @@ export default defineComponent({
|
|||
'maxWidth',
|
||||
'keepFocus',
|
||||
'changeCompat',
|
||||
'multiLineDrag'
|
||||
'multiLineDrag',
|
||||
'multipleLimit'
|
||||
],
|
||||
setup(props, context) {
|
||||
return setup({ props, context, renderless, api })
|
||||
|
|
Loading…
Reference in New Issue