[select] Optimized remote search demo (#1488)

* docs(steps): optimization of steps docs

* docs(select): optimized remote search demos

* fix(split): css vars don't work

* test(select): resolved running failed E2E test case
This commit is contained in:
黄怡林 2024-03-30 10:01:15 +08:00 committed by GitHub
parent 8de365c231
commit 772ef20270
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 408 additions and 854 deletions

View File

@ -44,7 +44,6 @@ test('多选事件', async ({ page }) => {
await page.waitForTimeout(500)
await select.click()
await expect(model.filter({ hasText: '触发 focus 事件' })).toHaveCount(1)
await expect(model.filter({ hasText: '触发 visible-change 事件' })).toHaveCount(1)
await option.nth(1).click()

View File

@ -0,0 +1,120 @@
<template>
<div>
<p>场景1单选下拉表格远程搜索基础用法</p>
<tiny-select
v-model="value1"
placeholder="请输入关键词"
render-type="grid"
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpRadio"
></tiny-select>
<p>场景2单选下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="value2"
placeholder="请输入关键词"
render-type="grid"
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpRadio"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
></tiny-select>
<p>场景3多选下拉表格远程搜索基础用法</p>
<tiny-select
v-model="value3"
placeholder="请输入关键词"
multiple
render-type="grid"
reserve-keyword
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpMultiple"
></tiny-select>
<p>场景4多选下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="value4"
placeholder="请输入关键词"
multiple
reserve-keyword
filterable
remote
render-type="grid"
:remote-method="remoteMethod"
:grid-op="gridOpMultiple"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
></tiny-select>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Select as TinySelect } from '@opentiny/vue'
const allData = Array.from({ length: 1000 }, (a, i) => {
return {
value: '00' + i,
province: '省份' + i,
city: '城市' + i,
area: '区域' + i,
label: `${i}-市${i}`
}
})
const baseGridOp = {
data: [],
height: 300,
optimization: {
animat: true,
delayHover: 250,
scrollX: { gt: 20 },
scrollY: { gt: 20 }
}
}
const baseCols = [
{ field: 'province', title: '省份' },
{ field: 'city', title: '城市' },
{ field: 'area', title: '区域' }
]
const value1 = ref('')
const value2 = ref('')
const value3 = ref([])
const value4 = ref([])
const gridOpRadio = {
...baseGridOp,
columns: [{ type: 'radio', title: '' }, ...baseCols]
}
const gridOpMultiple = {
...baseGridOp,
columns: [{ type: 'selection', title: '' }, ...baseCols]
}
const filter = (value) => {
return allData.filter((item) => item.city.includes(value))
}
const remoteMethod = (value) => {
const filterData = filter(value)
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
}
</script>
<style scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -1,106 +0,0 @@
<template>
<div>
<p>场景1下拉表格远程搜索基础用法</p>
<tiny-select
ref="select1"
v-model="radioValue1"
placeholder="请输入关键词"
clearable
filterable
remote
:remote-method="remoteMethod"
multiple
value-field="id"
text-field="city"
render-type="grid"
:grid-op="gridOpRadio"
></tiny-select>
<p>场景2下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
ref="select2"
v-model="radioValue2"
multiple
placeholder="请输入关键词"
clearable
filterable
remote
:remote-method="remoteMethod"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
value-field="id"
text-field="city"
render-type="grid"
:grid-op="gridOpRadio"
></tiny-select>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Select as TinySelect } from '@opentiny/vue'
const allData = ref([])
const radioValue1 = ref([])
const radioValue2 = ref([])
const gridOpRadio = ref({
data: [],
height: 300,
optimization: {
animat: true,
delayHover: 250,
scrollX: { gt: 20 },
scrollY: { gt: 20 }
},
columns: [
{ type: 'selection', title: '' },
{ field: 'area', title: '区域' },
{ field: 'province', title: '省份' },
{ field: 'city', title: '城市' }
]
})
allData.value = Array.from({ length: 10000 }, (a, i) => {
return {
id: '00' + i,
area: '华南区' + i,
province: '广东省' + i,
city: '广州市' + i
}
})
const remoteMethod = (value) => {
let allData = Array.from({ length: 1000 }, (a, i) => {
return {
id: '00' + i,
area: '华南区' + i,
province: '广东省' + i,
city: '广州市' + i
}
})
let filterData = allData.filter((item) => {
return item.city.includes(value)
})
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
}
const filter = (value) => {
return allData.value.filter((item) => {
return !item.city.includes(value)
})
}
</script>
<style lang="less" scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -1,68 +0,0 @@
import { expect, test } from '@playwright/test'
test('下拉表格远程搜索基础用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote-multi')
const wrap = page.locator('#nest-grid-remote-multi')
const select = wrap.locator('.tiny-select').nth(0)
const input = select.locator('.tiny-select__input')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret').first()
// 下拉按钮不显示
await expect(suffixSvg).toBeHidden()
await expect(dropdown).toBeHidden()
await input.fill(' ')
await input.press('Enter')
await page.waitForTimeout(1000)
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
await input.fill('')
await input.press('Enter')
await page.waitForTimeout(1000)
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await page.getByRole('row', { name: '华南区0 广东省0 广州市0' }).getByRole('cell').first().click()
const tags = page.locator('.tiny-select .tiny-tag')
await expect((await tags.all()).length).toEqual(1)
await expect(tags.first()).toContainText(/广州市0/)
await page.getByRole('row', { name: '华南区1 广东省1 广州市1' }).getByRole('cell').first().click()
await expect((await tags.all()).length).toEqual(2)
await expect(tags.first()).toContainText(/广州市0/)
await expect(tags.nth(1)).toContainText(/广州市1/)
})
test('下拉表格远程搜索 + 自动搜索 + 显示按钮', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote-multi')
const wrap = page.locator('#nest-grid-remote-multi')
const select = wrap.locator('.tiny-select').nth(1)
const input = select.locator('.tiny-select__input')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret').first()
const tag = select.locator('.tiny-tag')
await expect(suffixSvg).toBeVisible()
await expect(dropdown).toBeHidden()
await select.click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await dropdown.getByRole('row', { name: '华南区0 广东省0 广州市0' }).getByRole('cell').first().click()
await expect((await tag.all()).length).toEqual(1)
await expect(tag.first()).toContainText(/广州市0/)
await dropdown.getByRole('row', { name: '华南区1 广东省1 广州市1' }).getByRole('cell').first().click()
await expect((await tag.all()).length).toEqual(2)
await expect(tag.first()).toContainText(/广州市0/)
await expect(tag.nth(1)).toContainText(/广州市1/)
await tag.nth(0).locator('.tiny-svg').click()
await tag.nth(0).locator('.tiny-svg').click()
await expect((await tag.all()).length).toEqual(0)
await input.fill(' ')
await input.press('Enter')
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
})

View File

@ -1,118 +0,0 @@
<template>
<div>
<p>场景1下拉表格远程搜索基础用法</p>
<tiny-select
ref="select1"
v-model="radioValue1"
placeholder="请输入关键词"
clearable
filterable
remote
:remote-method="remoteMethod"
multiple
reserve-keyword
value-field="id"
text-field="city"
render-type="grid"
:grid-op="gridOpRadio"
></tiny-select>
<p>场景2下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
ref="select2"
v-model="radioValue2"
multiple
reserve-keyword
placeholder="请输入关键词"
clearable
filterable
remote
:remote-method="remoteMethod"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
value-field="id"
text-field="city"
render-type="grid"
:grid-op="gridOpRadio"
></tiny-select>
</div>
</template>
<script>
import { Select } from '@opentiny/vue'
export default {
components: {
TinySelect: Select
},
created() {
this.allData = Array.from({ length: 10000 }, (a, i) => {
return {
id: '00' + i,
area: '华南区' + i,
province: '广东省' + i,
city: '广州市' + i
}
})
},
data() {
return {
allData: [],
radioValue1: [],
radioValue2: [],
gridOpRadio: {
data: [],
height: 300,
optimization: {
animat: true,
delayHover: 250,
scrollX: { gt: 20 },
scrollY: { gt: 20 }
},
columns: [
{ type: 'selection', title: '' },
{ field: 'area', title: '区域' },
{ field: 'province', title: '省份' },
{ field: 'city', title: '城市' }
]
}
}
},
methods: {
remoteMethod(value) {
console.log(value)
let allData = Array.from({ length: 1000 }, (a, i) => {
return {
id: '00' + i,
area: '华南区' + i,
province: '广东省' + i,
city: '广州市' + i
}
})
let filterData = allData.filter((item) => {
return item.city.includes(value)
})
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
},
filter(value) {
return this.allData.filter((item) => {
return !item.city.includes(value)
})
}
}
}
</script>
<style lang="less" scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -1,230 +0,0 @@
<template>
<div>
<p>场景1下拉表格远程搜索基础用法</p>
<tiny-select
v-model="radioValue"
placeholder="请输入关键词"
filterable
remote
:remote-method="remoteMethod"
value-field="coaNumber"
text-field="coaNumber"
render-type="grid"
:grid-op="gridOpRadio"
>
</tiny-select>
<p>场景2下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="radioValue"
placeholder="请输入关键词"
filterable
remote
:remote-method="remoteMethod"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
value-field="coaNumber"
text-field="coaNumber"
render-type="grid"
:grid-op="gridOpRadio"
>
</tiny-select>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Select as TinySelect } from '@opentiny/vue'
const radioValue = ref('')
const states = ref([
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5100000',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'test1IT Service',
cnName: 'test1IT Service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900003',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Entertainment and gymnastic service',
cnName: 'Entertainment and gymnastic service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900004',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Customer accommodation',
cnName: 'Customer accommodation'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900022',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Long-term lease',
cnName: 'Long-term lease'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900001',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Food and beverage services',
cnName: 'Food and beverage services'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900002',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Conference room leasing service',
cnName: 'Conference room leasing service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900005',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Employee accommodation',
cnName: 'Employee accommodation'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '6116001',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'C7168',
cnName: 'C7168'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '6118100',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'C2299',
cnName: 'C2299'
}
])
const gridOpRadio = ref({
radioConfig: {
trigger: 'row',
checkMethod() {
return true
}
},
data: [
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5100000',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'test1IT Service',
cnName: 'test1IT Service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900003',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Entertainment and gymnastic service',
cnName: 'Entertainment and gymnastic service'
}
],
columns: [
{ type: 'radio', title: '' },
{ field: 'coaNumber', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
})
let loading
const remoteMethod = (query) => {
if (query !== undefined) {
loading = true
return new Promise((resolve) => {
setTimeout(() => {
loading = false
const result = states.value.filter((item) => {
return item.coaNumber.includes(query)
})
resolve(result)
}, 200)
})
} else {
gridOpRadio.value.data = []
}
}
</script>
<style lang="less" scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -1,62 +0,0 @@
import { expect, test } from '@playwright/test'
test('下拉表格远程搜索基础用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote-single')
const wrap = page.locator('#nest-grid-remote-single')
const select = wrap.locator('.tiny-select').nth(0)
const input = select.locator('.tiny-input__inner')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = dropdown.locator('.tiny-input__suffix .tiny-select__caret')
await expect(suffixSvg).toBeHidden()
await expect(dropdown).toBeHidden()
await input.focus()
await input.fill(' ')
await input.press('Enter')
await page.waitForTimeout(200)
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
await input.fill('')
await input.press('Enter')
await page.waitForTimeout(200)
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await page.getByRole('row', { name: '5100000' }).locator('div').first().click()
await expect(input).toHaveValue('5100000')
await input.click()
await expect(page.getByRole('row', { name: '5100000' })).toHaveClass(/row__current/)
await page.getByRole('row', { name: '5900003' }).locator('div').first().click()
await expect(input).toHaveValue('5900003')
await input.click()
await expect(page.getByRole('row', { name: '5900003' })).toHaveClass(/row__current/)
})
test('下拉表格远程搜索 + 自动搜索 + 显示按钮', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote-single')
const wrap = page.locator('#nest-grid-remote-single')
const select = wrap.locator('.tiny-select').nth(1)
const input = select.locator('.tiny-input__inner')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret')
await expect(suffixSvg).toBeVisible()
await expect(dropdown).toBeHidden()
await input.click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await page.getByRole('row', { name: '5100000' }).getByRole('cell').first().click()
await expect(input).toHaveValue('5100000')
await input.click()
await expect(page.getByRole('row', { name: '5100000' })).toHaveClass(/row__current/)
await page.getByRole('row', { name: '5900003' }).getByRole('cell').first().click()
await expect(input).toHaveValue('5900003')
await input.click()
await expect(page.getByRole('row', { name: '5900003' })).toHaveClass(/row__current/)
await input.fill(' ')
await input.press('Enter')
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
})

View File

@ -1,238 +0,0 @@
<template>
<div>
<p>场景1下拉表格远程搜索基础用法</p>
<tiny-select
v-model="radioValue"
placeholder="请输入关键词"
filterable
remote
:remote-method="remoteMethod"
value-field="coaNumber"
text-field="coaNumber"
render-type="grid"
:grid-op="gridOpRadio"
>
</tiny-select>
<p>场景2下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="radioValue"
placeholder="请输入关键词"
filterable
remote
:remote-method="remoteMethod"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
value-field="coaNumber"
text-field="coaNumber"
render-type="grid"
:grid-op="gridOpRadio"
>
</tiny-select>
</div>
</template>
<script>
import { Select } from '@opentiny/vue'
export default {
components: {
TinySelect: Select
},
methods: {
remoteMethod(query) {
if (query !== undefined) {
this.loading = true
return new Promise((resolve) => {
setTimeout(() => {
this.loading = false
const result = this.states.filter((item) => {
return item.coaNumber.includes(query)
})
resolve(result)
}, 200)
})
} else {
this.gridOpRadio.data = []
}
}
},
data() {
return {
radioValue: '',
states: [
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5100000',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'test1IT Service',
cnName: 'test1IT Service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900003',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Entertainment and gymnastic service',
cnName: 'Entertainment and gymnastic service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900004',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Customer accommodation',
cnName: 'Customer accommodation'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900022',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Long-term lease',
cnName: 'Long-term lease'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900001',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Food and beverage services',
cnName: 'Food and beverage services'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900002',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Conference room leasing service',
cnName: 'Conference room leasing service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900005',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Employee accommodation',
cnName: 'Employee accommodation'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '6116001',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'C7168',
cnName: 'C7168'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '6118100',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'C2299',
cnName: 'C2299'
}
],
gridOpRadio: {
radioConfig: {
trigger: 'row',
checkMethod() {
return true
}
},
data: [
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5100000',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'test1IT Service',
cnName: 'test1IT Service'
},
{
coaCategory: null,
coaCreationDate: null,
coaId: null,
coaLastUpdateDate: null,
coaNumber: '5900003',
coaStatus: null,
parentId: null,
parentNumber: null,
parentType: null,
enName: 'Entertainment and gymnastic service',
cnName: 'Entertainment and gymnastic service'
}
],
columns: [
{ type: 'radio', title: '' },
{ field: 'coaNumber', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
}
}
}
}
</script>
<style lang="less" scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -0,0 +1,135 @@
import { expect, test } from '@playwright/test'
test.describe('下拉表格远程搜索', () => {
test('单选,下拉表格远程搜索基础用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote')
const wrap = page.locator('#nest-grid-remote')
const select = wrap.locator('.tiny-select').nth(0)
const input = select.locator('.tiny-input__inner')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = dropdown.locator('.tiny-input__suffix .tiny-select__caret')
await expect(suffixSvg).toBeHidden()
await expect(dropdown).toBeHidden()
await input.focus()
await input.fill(' ')
await input.press('Enter')
await page.waitForTimeout(200)
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
await input.fill('1')
await input.press('Enter')
await page.waitForTimeout(200)
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
const row1 = page.getByRole('row', { name: '省份1 城市1 区域1' })
const row2 = page.getByRole('row', { name: '省份2 城市2 区域2' })
await expect(row2).not.toBeVisible()
await row1.getByRole('cell').first().click()
await expect(row1).toHaveClass(/row__current/)
await expect(input).toHaveValue('省1-市1')
const row3 = page.getByRole('row', { name: '省份10 城市10 区域10' })
await input.click()
await row3.getByRole('cell').first().click()
await expect(input).toHaveValue('省10-市10')
})
test('单选,下拉表格远程搜索 + 自动搜索 + 显示按钮', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote')
const wrap = page.locator('#nest-grid-remote')
const select = wrap.locator('.tiny-select').nth(1)
const input = select.locator('.tiny-input__inner')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret')
await expect(suffixSvg).toBeVisible()
await expect(dropdown).toBeHidden()
await input.click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await page.getByRole('row', { name: '省份2 城市2 区域2' }).getByRole('cell').first().click()
await expect(input).toHaveValue('省2-市2')
await input.click()
await expect(page.getByRole('row', { name: '省份2 城市2 区域2' })).toHaveClass(/row__current/)
await page.getByRole('row', { name: '省份6 城市6 区域6' }).getByRole('cell').first().click()
await expect(input).toHaveValue('省6-市6')
await input.click()
await expect(page.getByRole('row', { name: '省份6 城市6 区域6' })).toHaveClass(/row__current/)
await input.fill(' ')
await input.press('Enter')
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
})
test('多选,下拉表格远程搜索基础用法', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote')
const wrap = page.locator('#nest-grid-remote')
const select = wrap.locator('.tiny-select').nth(2)
const input = select.locator('.tiny-select__input')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret').first()
// 下拉按钮不显示
await expect(suffixSvg).toBeHidden()
await expect(dropdown).toBeHidden()
await input.fill(' ')
await input.press('Enter')
await page.waitForTimeout(1000)
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
await input.fill('')
await input.press('Enter')
await page.waitForTimeout(1000)
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await page.getByRole('row', { name: '省份0 城市0 区域0' }).getByRole('cell').first().click()
const tags = page.locator('.tiny-select .tiny-tag')
expect((await tags.all()).length).toEqual(1)
await expect(tags.first()).toContainText(/市0/)
await page.getByRole('row', { name: '省份1 城市1 区域1' }).getByRole('cell').first().click()
expect((await tags.all()).length).toEqual(2)
await expect(tags.first()).toContainText(/市0/)
await expect(tags.nth(1)).toContainText(/市1/)
})
test('多选,下拉表格远程搜索 + 自动搜索 + 显示按钮', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('select#nest-grid-remote')
const wrap = page.locator('#nest-grid-remote')
const select = wrap.locator('.tiny-select').nth(3)
const input = select.locator('.tiny-select__input')
const dropdown = page.locator('body > .tiny-select-dropdown')
const suffixSvg = select.locator('.tiny-input__suffix .tiny-select__caret').first()
const tag = select.locator('.tiny-tag')
await expect(suffixSvg).toBeVisible()
await expect(dropdown).toBeHidden()
await select.click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).not.toBeEmpty()
await dropdown.getByRole('row', { name: '省份0 城市0 区域0' }).getByRole('cell').first().click()
expect((await tag.all()).length).toEqual(1)
await expect(tag.first()).toContainText(/市0/)
await dropdown.getByRole('row', { name: '省份1 城市1 区域1' }).getByRole('cell').first().click()
expect((await tag.all()).length).toEqual(2)
await expect(tag.first()).toContainText(/市0/)
await expect(tag.nth(1)).toContainText(/市1/)
await tag.nth(0).locator('.tiny-svg').click()
await tag.nth(0).locator('.tiny-svg').click()
await expect((await tag.all()).length).toEqual(0)
await input.fill(' ')
await input.press('Enter')
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.tiny-grid__body tbody')).toBeEmpty()
})
})

View File

@ -0,0 +1,136 @@
<template>
<div>
<p>场景1单选下拉表格远程搜索基础用法</p>
<tiny-select
v-model="value1"
placeholder="请输入关键词"
render-type="grid"
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpRadio"
></tiny-select>
<p>场景2单选下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="value2"
placeholder="请输入关键词"
render-type="grid"
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpRadio"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
></tiny-select>
<p>场景3多选下拉表格远程搜索基础用法</p>
<tiny-select
v-model="value3"
placeholder="请输入关键词"
multiple
render-type="grid"
reserve-keyword
filterable
remote
:remote-method="remoteMethod"
:grid-op="gridOpMultiple"
></tiny-select>
<p>场景4多选下拉表格远程搜索 + 自动搜索 + 显示按钮</p>
<tiny-select
v-model="value4"
placeholder="请输入关键词"
multiple
reserve-keyword
filterable
remote
render-type="grid"
:remote-method="remoteMethod"
:grid-op="gridOpMultiple"
:remote-config="{ autoSearch: true, clearData: true, showIcon: true }"
></tiny-select>
</div>
</template>
<script>
import { Select } from '@opentiny/vue'
export default {
components: {
TinySelect: Select
},
created() {
this.allData = Array.from({ length: 1000 }, (a, i) => {
return {
value: '00' + i,
province: '省份' + i,
city: '城市' + i,
area: '区域' + i,
label: `${i}-市${i}`
}
})
},
data() {
const baseGridOp = {
data: [],
height: 300,
optimization: {
animat: true,
delayHover: 250,
scrollX: { gt: 20 },
scrollY: { gt: 20 }
}
}
const baseCols = [
{
field: 'province',
title: '省份'
},
{ field: 'city', title: '城市' },
{
field: 'area',
title: '区域'
}
]
return {
allData: [],
value1: '',
value2: '',
value3: [],
value4: [],
gridOpRadio: {
...baseGridOp,
columns: [{ type: 'radio', title: '' }, ...baseCols]
},
gridOpMultiple: {
...baseGridOp,
columns: [{ type: 'selection', title: '' }, ...baseCols]
}
}
},
methods: {
remoteMethod(value) {
const filterData = this.filter(value)
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
},
filter(value) {
return this.allData.filter((item) => item.city.includes(value))
}
}
}
</script>
<style scoped>
.tiny-select {
width: 280px;
}
p {
font-size: 14px;
line-height: 1.5;
}
</style>

View File

@ -460,32 +460,18 @@ export default {
codeFiles: ['nest-grid-disable.vue']
},
{
demoId: 'nest-grid-remote-single',
demoId: 'nest-grid-remote',
name: {
'zh-CN': '下拉表格远程搜索(单选)',
'en-US': 'Select table Remote Search (Single)'
'zh-CN': '下拉表格远程搜索',
'en-US': 'Select table Remote Search'
},
desc: {
'zh-CN':
'<p>通过 <code>remote</code> 和 <code>remote-method</code> 和 <code>filterable</code> 开启远程搜索。通过 <code>remote-config</code> 设置自动搜索和显示展开按钮 。</p>\n',
'en-US':
'<p>Enable remote search through <code>remote</code>,<code>remote-method</code>, and <code>filterable</code>. Set up automatic search and display expansion buttons through <code>remote-config</code>.</p>'
'zh-CN': `<p>同时使用 <code>remote</code> 和 <code>remote-method</code> 和 <code>filterable</code> 3个属性开启远程搜索。通过 <code>remote-config</code> 设置自动搜索和显示展开按钮。</p>
<p>在多选模式下可通过 <code>reserve-keyword</code></p>`,
'en-US': `<p>Enable remote search through <code>remote</code>,<code>remote-method</code>, and <code>filterable</code>. Set up automatic search and display expansion buttons through <code>remote-config</code>.</p>
<p>In multiple selection mode, <code>reserve-keyword</code> set to retain search keywords after selecting multiple options.</p>`
},
codeFiles: ['nest-grid-remote-single.vue']
},
{
demoId: 'nest-grid-remote-multi',
name: {
'zh-CN': '下拉表格远程搜索(多选)',
'en-US': 'Select table Remote Search (Multiple)'
},
desc: {
'zh-CN':
'<p>通过 <code>remote</code> 和 <code>remote-method</code> 和 <code>filterable</code> 开启远程搜索。通过 <code>remote-config</code> 设置自动搜索和显示展开按钮。<code>reserve-keyword</code>设置多选选中一个选项后依然保留搜索关键字。</p>\n',
'en-US':
'<p>Enable remote search through <code>remote</code>,<code>remote-method</code>, and <code>filterable</code>. Set up automatic search and display expansion buttons through <code>remote-config</code> <code>reserve-keyword</code> set to retain search keywords after selecting multiple options.</p>'
},
codeFiles: ['nest-grid-remote-multi.vue']
codeFiles: ['nest-grid-remote.vue']
},
{
demoId: 'nest-grid-init-query',

View File

@ -17,14 +17,14 @@
@split-prefix-cls: ~'@{css-prefix}split';
.@{split-prefix-cls} {
.component-css-vars-split();
&-wrapper {
.component-css-vars-split();
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
box-shadow: 0 0 0px 1px #d9d9d9;
box-shadow: 0 0 0 1px #d9d9d9;
}
&-pane {
@ -60,7 +60,6 @@
&.bottom-pane {
bottom: 0;
}
}
&-trigger {
@ -90,7 +89,7 @@
&-vertical {
width: 4px;
height: 100%;
background: #EAECF1;
background: #eaecf1;
cursor: e-resize;
.@{split-prefix-cls}-trigger-bar {
@ -103,11 +102,10 @@
}
}
&-horizontal {
height: 4px;
width: 100%;
background: #EAECF1;
background: #eaecf1;
cursor: n-resize;
.@{split-prefix-cls}-trigger-bar {
@ -158,7 +156,8 @@
}
.@{split-prefix-cls}-trigger-con.@{split-prefix-cls}-trigger-con-disabled {
.@{split-prefix-cls}-trigger-vertical,.@{split-prefix-cls}-trigger-horizontal {
.@{split-prefix-cls}-trigger-vertical,
.@{split-prefix-cls}-trigger-horizontal {
cursor: auto;
&:hover {
@ -231,7 +230,8 @@
}
.@{split-prefix-cls}-trigger-con.@{split-prefix-cls}-trigger-con-disabled {
.@{split-prefix-cls}-trigger-vertical,.@{split-prefix-cls}-trigger-horizontal {
.@{split-prefix-cls}-trigger-vertical,
.@{split-prefix-cls}-trigger-horizontal {
cursor: auto;
&:hover {