mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
parent
41dd4177b6
commit
1333bdac4f
@ -67,6 +67,14 @@ function changeValue({ value }) {
|
||||
<wd-rate v-model="value" allow-half />
|
||||
```
|
||||
|
||||
## 允许清空评分
|
||||
|
||||
设置 `clearable` 属性,当 clearable 属性设置为 true,再次点击相同的值时,可以将值重置为 0。
|
||||
|
||||
```html
|
||||
<wd-rate v-model="value" clearable />
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|
||||
@ -83,6 +91,7 @@ function changeValue({ value }) {
|
||||
| disabled | 是否禁用 | boolean | - | false | - |
|
||||
| disabled-color | 禁用的图标颜色 | string | - | linear-gradient(315deg, rgba(177,177,177,1) 0%,rgba(199,199,199,1) 100%) | - |
|
||||
| allow-half | 是否允许半选 | boolean | - | false | 1.7.0 |
|
||||
| clearable | 是否允许再次点击后清除 | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
@ -67,6 +67,14 @@ Set the `allowHalf` property.
|
||||
<wd-rate v-model="value" allow-half />
|
||||
```
|
||||
|
||||
## Allow Clear Rating
|
||||
|
||||
Set the `clearable` property. When clearable is set to true, clicking the same value again can reset the value to 0.
|
||||
|
||||
```html
|
||||
<wd-rate v-model="value" clearable />
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
| Parameter | Description | Type | Options | Default | Version |
|
||||
@ -83,6 +91,7 @@ Set the `allowHalf` property.
|
||||
| disabled | Whether it's disabled | boolean | - | false | - |
|
||||
| disabled-color | Disabled icon color | string | - | linear-gradient(315deg, rgba(177,177,177,1) 0%,rgba(199,199,199,1) 100%) | - |
|
||||
| allow-half | Whether to allow half selection | boolean | - | false | 1.7.0 |
|
||||
| clearable | Whether to allow clear rating | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
@ -1451,6 +1451,7 @@
|
||||
"yue-xiu-qu": "Yuexiu",
|
||||
"yue-xuan-ze": "Monthly selection",
|
||||
"yun-xu-ban-xuan": "Allow half selection",
|
||||
"yun-xu-qing-kong-ping-fen": "Allow clear rating",
|
||||
"yun-xu-kong-zhi-bing-she-zhi-placeholder": "Allow null values and set placeholder",
|
||||
"yy-nian-mm-yue-dd-ri": "YY year MM month DD day",
|
||||
"yy-nian-mm-yue-dd-ri-0": "YY year MM month DD day",
|
||||
|
||||
@ -1451,6 +1451,7 @@
|
||||
"yue-xiu-qu": "越秀区",
|
||||
"yue-xuan-ze": "月选择",
|
||||
"yun-xu-ban-xuan": "允许半选",
|
||||
"yun-xu-qing-kong-ping-fen": "允许清空评分",
|
||||
"yun-xu-kong-zhi-bing-she-zhi-placeholder": "允许空值,并设置 placeholder",
|
||||
"yy-nian-mm-yue-dd-ri": "YY年MM月DD日",
|
||||
"yy-nian-mm-yue-dd-ri-0": "YY年MM月DD日",
|
||||
|
||||
@ -36,6 +36,15 @@
|
||||
<demo-block :title="$t('yun-xu-ban-xuan')">
|
||||
<wd-rate v-model="value8" allow-half />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('yun-xu-qing-kong-ping-fen')">
|
||||
<view style="margin-bottom: 24rpx">
|
||||
<wd-rate v-model="value9" clearable />
|
||||
</view>
|
||||
<view>
|
||||
<wd-rate v-model="value10" clearable allow-half />
|
||||
</view>
|
||||
</demo-block>
|
||||
</page-wraper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@ -49,6 +58,8 @@ const value5 = ref<number>(4)
|
||||
const value6 = ref<number>(3)
|
||||
const value7 = ref<number>(5)
|
||||
const value8 = ref<number>(2.5)
|
||||
const value9 = ref<number>(3)
|
||||
const value10 = ref<number>(3.5)
|
||||
|
||||
function changeValue1({ value }: any) {
|
||||
console.log(value)
|
||||
|
||||
@ -92,5 +92,12 @@ export const rateProps = {
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
allowHalf: makeBooleanProp(false)
|
||||
allowHalf: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 当 clearable 属性设置为 true,再次点击相同的值时,可以将值重置为 0。
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
clearable: makeBooleanProp(false)
|
||||
}
|
||||
|
||||
@ -12,9 +12,9 @@
|
||||
:name="isActive(rate) ? activeIcon : icon"
|
||||
:size="size"
|
||||
:custom-style="rate === '100%' ? iconActiveStyle : iconStyle"
|
||||
@click="changeRate(index, false)"
|
||||
@click="handleClick(index, false)"
|
||||
/>
|
||||
<view v-if="props.allowHalf" class="wd-rate__item-half" @click.stop="changeRate(index, true)">
|
||||
<view v-if="props.allowHalf" class="wd-rate__item-half" @click.stop="handleClick(index, true)">
|
||||
<wd-icon
|
||||
custom-class="wd-rate__item-star"
|
||||
:name="isActive(rate) ? activeIcon : icon"
|
||||
@ -125,12 +125,30 @@ function computeActiveValue() {
|
||||
}
|
||||
activeValue.value = tempActiveValue
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 点击icon触发组件的change事件
|
||||
* @description 处理点击事件
|
||||
* @param index 点击的索引
|
||||
* @param isHalf 是否为半星
|
||||
*/
|
||||
function changeRate(index: number, isHalf: boolean) {
|
||||
if (props.readonly || props.disabled) return
|
||||
const value = isHalf ? index + 0.5 : index + 1
|
||||
function handleClick(index: number, isHalf: boolean) {
|
||||
const { readonly, disabled, clearable, allowHalf, modelValue } = props
|
||||
if (readonly || disabled) return
|
||||
let value = isHalf ? index + 0.5 : index + 1
|
||||
// 点击清空逻辑:当点击的值与当前modelValue相等且等于最小值时允许清空
|
||||
if (clearable) {
|
||||
const minValue = allowHalf ? 0.5 : 1
|
||||
if (value === modelValue && value === minValue) {
|
||||
value = 0
|
||||
}
|
||||
}
|
||||
updateValue(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 设置评分值并触发事件
|
||||
*/
|
||||
function updateValue(value: number) {
|
||||
emit('update:modelValue', value)
|
||||
emit('change', {
|
||||
value
|
||||
@ -149,7 +167,8 @@ async function onTouchMove(event: TouchEvent) {
|
||||
const isHalf = props.allowHalf && clientX - target.left! < itemWidth / 2
|
||||
const value = isHalf ? targetIndex + 0.5 : targetIndex + 1
|
||||
if (value >= 0.5) {
|
||||
changeRate(targetIndex, isHalf)
|
||||
const value = isHalf ? targetIndex + 0.5 : targetIndex + 1
|
||||
updateValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,9 +302,9 @@ describe('评分组件', () => {
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 直接调用组件的 changeRate 方法,模拟点击第一个星星
|
||||
// 直接调用组件的 handleClick 方法,模拟点击第一个星星
|
||||
// 这比模拟触摸事件更可靠,因为触摸事件依赖于 DOM 元素的位置
|
||||
await (wrapper.vm as any).changeRate(0, false)
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
@ -326,9 +326,9 @@ describe('评分组件', () => {
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 直接调用组件的 changeRate 方法,模拟点击第一个半星
|
||||
// 直接调用组件的 handleClick 方法,模拟点击第一个半星
|
||||
// 这比模拟触摸事件更可靠,因为触摸事件依赖于 DOM 元素的位置
|
||||
await (wrapper.vm as any).changeRate(0, true)
|
||||
await (wrapper.vm as any).handleClick(0, true)
|
||||
|
||||
// 验证事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
@ -413,4 +413,208 @@ describe('评分组件', () => {
|
||||
|
||||
expect(wrapper.attributes('style')).toBe(customStyle)
|
||||
})
|
||||
|
||||
// 测试清空功能
|
||||
describe('clearable 功能测试', () => {
|
||||
// 测试基本清空功能
|
||||
test('clearable 为 true 时,点击相同的最小值可以清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 1,
|
||||
clearable: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星(当前值为1,最小值为1)
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证清空事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(0)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 0 })
|
||||
})
|
||||
|
||||
test('clearable 为 false 时,点击相同值不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 1,
|
||||
clearable: false
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证不会清空,而是设置为1
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(1)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 1 })
|
||||
})
|
||||
|
||||
// 测试半星模式下的清空
|
||||
test('clearable + allowHalf 组合下,点击 0.5 可以清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 0.5,
|
||||
clearable: true,
|
||||
allowHalf: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个半星(当前值为0.5,最小值为0.5)
|
||||
await (wrapper.vm as any).handleClick(0, true)
|
||||
|
||||
// 验证清空事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(0)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 0 })
|
||||
})
|
||||
|
||||
test('非最小值时点击不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 2,
|
||||
clearable: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星(当前值为2,点击值为1,不等于当前值)
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证不会清空,而是设置为1
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(1)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 1 })
|
||||
})
|
||||
|
||||
// 测试边界情况
|
||||
test('当前值为 0 时点击不会触发清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 0,
|
||||
clearable: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证设置为1,而不是保持0
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(1)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 1 })
|
||||
})
|
||||
|
||||
test('点击非最小值时不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 3,
|
||||
clearable: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第三个星星(当前值为3,点击值为3,但不是最小值)
|
||||
await (wrapper.vm as any).handleClick(2, false)
|
||||
|
||||
// 验证不会清空,而是保持为3
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(3)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 3 })
|
||||
})
|
||||
|
||||
// 测试与其他状态的组合
|
||||
test('readonly + clearable 时不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 1,
|
||||
clearable: true,
|
||||
readonly: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证在只读状态下不会触发任何事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeFalsy()
|
||||
expect(emitted['change']).toBeFalsy()
|
||||
})
|
||||
|
||||
test('disabled + clearable 时不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 1,
|
||||
clearable: true,
|
||||
disabled: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第一个星星
|
||||
await (wrapper.vm as any).handleClick(0, false)
|
||||
|
||||
// 验证在禁用状态下不会触发任何事件
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeFalsy()
|
||||
expect(emitted['change']).toBeFalsy()
|
||||
})
|
||||
|
||||
// 测试半星模式下非最小值不会清空
|
||||
test('半星模式下点击非最小值不会清空', async () => {
|
||||
const wrapper = mount(WdRate, {
|
||||
props: {
|
||||
modelValue: 1.5,
|
||||
clearable: true,
|
||||
allowHalf: true
|
||||
}
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 调用 handleClick 方法,模拟点击第二个半星(当前值为1.5,点击值为1.5,但不是最小值0.5)
|
||||
await (wrapper.vm as any).handleClick(1, true)
|
||||
|
||||
// 验证不会清空,而是保持为1.5
|
||||
const emitted = wrapper.emitted() as Record<string, any[]>
|
||||
expect(emitted['update:modelValue']).toBeTruthy()
|
||||
expect(emitted['update:modelValue'][0][0]).toBe(1.5)
|
||||
|
||||
expect(emitted['change']).toBeTruthy()
|
||||
expect(emitted['change'][0][0]).toEqual({ value: 1.5 })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user