diff --git a/src/rate/README.md b/src/rate/README.md index b4da9466d..f91033417 100644 --- a/src/rate/README.md +++ b/src/rate/README.md @@ -88,6 +88,23 @@ export default { ``` +### Readonly Half Star + +```html + +``` + +```js +import { ref } from 'vue'; + +export default { + setup() { + const value = ref(3.3); + return { value }; + }, +}; +``` + ### Change Event ```html diff --git a/src/rate/README.zh-CN.md b/src/rate/README.zh-CN.md index e3f22f0d0..3bbe865b7 100644 --- a/src/rate/README.zh-CN.md +++ b/src/rate/README.zh-CN.md @@ -88,6 +88,25 @@ export default { ``` +### 只读状态显示小数 + +设置 `readonly` 和 `allow-half` 属性后,Rate 组件可以展示任意小数结果。 + +```html + +``` + +```js +import { ref } from 'vue'; + +export default { + setup() { + const value = ref(3.3); + return { value }; + }, +}; +``` + ### 监听 change 事件 ```html diff --git a/src/rate/Rate.tsx b/src/rate/Rate.tsx index 533b18d17..e7ef69936 100644 --- a/src/rate/Rate.tsx +++ b/src/rate/Rate.tsx @@ -15,18 +15,34 @@ const [name, bem] = createNamespace('rate'); type RateStatus = 'full' | 'half' | 'void'; +type RateListItem = { + status: RateStatus; + value: number; +}; + function getRateStatus( value: number, index: number, - allowHalf: boolean -): RateStatus { + allowHalf: boolean, + readonly: boolean +): RateListItem { if (value >= index) { - return 'full'; + return { status: 'full', value: 1 }; } - if (value + 0.5 >= index && allowHalf) { - return 'half'; + + if (value + 0.5 >= index && allowHalf && !readonly) { + return { status: 'half', value: 0.5 }; } - return 'void'; + + if (value + 1 >= index && allowHalf && readonly) { + const cardinal = 10 ** 10; + return { + status: 'half', + value: Math.round((value - index + 1) * cardinal) / cardinal, + }; + } + + return { status: 'void', value: 0 }; } export default defineComponent({ @@ -72,10 +88,17 @@ export default defineComponent({ const untouchable = () => props.readonly || props.disabled || !props.touchable; - const list = computed(() => + const list = computed(() => Array(props.count) .fill('') - .map((_, i) => getRateStatus(props.modelValue, i + 1, props.allowHalf)) + .map((_, i) => + getRateStatus( + props.modelValue, + i + 1, + props.allowHalf, + props.readonly + ) + ) ); const select = (index: number) => { @@ -130,7 +153,7 @@ export default defineComponent({ } }; - const renderStar = (status: RateStatus, index: number) => { + const renderStar = (item: RateListItem, index: number) => { const { icon, size, @@ -145,8 +168,8 @@ export default defineComponent({ disabledColor, } = props; const score = index + 1; - const isFull = status === 'full'; - const isVoid = status === 'void'; + const isFull = item.status === 'full'; + const isVoid = item.status === 'void'; let style; if (gutter && score !== +count) { @@ -181,6 +204,7 @@ export default defineComponent({ {allowHalf && ( + + + + - + @@ -57,6 +61,7 @@ const i18n = { customStyle: '自定义样式', customCount: '自定义数量', readonly: '只读状态', + readonlyHalfStar: '只读状态小数显示', changeEvent: '监听 change 事件', toastContent: (value: number) => `当前值:${value}`, }, @@ -67,6 +72,7 @@ const i18n = { customStyle: 'Custom Style', customCount: 'Custom Count', readonly: 'Readonly', + readonlyHalfStar: 'Readonly Half Star', changeEvent: 'Change Event', toastContent: (value: number) => `current value:${value}`, }, @@ -82,7 +88,8 @@ export default { value4: 2.5, value5: 4, value6: 3, - value7: 2, + value7: 3.3, + value8: 2, }); const onChange = (value: number) => Toast(t('toastContent', value)); diff --git a/src/rate/test/__snapshots__/demo.spec.ts.snap b/src/rate/test/__snapshots__/demo.spec.ts.snap index 6a48eb0c0..5d8c74d03 100644 --- a/src/rate/test/__snapshots__/demo.spec.ts.snap +++ b/src/rate/test/__snapshots__/demo.spec.ts.snap @@ -225,7 +225,7 @@ exports[`should render demo and match snapshot 1`] = ` > @@ -243,7 +243,7 @@ exports[`should render demo and match snapshot 1`] = ` > @@ -261,7 +261,7 @@ exports[`should render demo and match snapshot 1`] = ` > @@ -279,7 +279,7 @@ exports[`should render demo and match snapshot 1`] = ` > @@ -297,7 +297,7 @@ exports[`should render demo and match snapshot 1`] = ` > @@ -517,6 +517,98 @@ exports[`should render demo and match snapshot 1`] = ` +
+
+ + + + + +
+
{ triggerDrag(wrapper, 100, 0); expect(wrapper.emitted('change')).toBeFalsy(); }); + +test('should get decimal when using allow-half and readonly prop', () => { + const wrapper = mount(Rate, { + props: { + allowHalf: true, + readonly: true, + modelValue: 3.3, + }, + }); + + const item4 = wrapper.findAll('.van-rate__icon--half')[3]; + expect(item4.style.width).toEqual('0.3em'); +});