diff --git a/devui/rate/demo/basic/index.tsx b/devui/rate/demo/basic/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2a0afb0a11f17a6dfa39c58b987187b324a5a078 --- /dev/null +++ b/devui/rate/demo/basic/index.tsx @@ -0,0 +1,34 @@ +import { defineComponent, ref } from 'vue'; +import DRate from '../../rate'; + +export default defineComponent({ + name: 'BasicRate', + components: { + DRate, + }, + props: {}, + setup() { + const value = ref(2); + const onUpdateValue = (newVal: number) => { + value.value = newVal; + }; + return { + value, + onUpdateValue, + }; + }, + render() { + const { value, onUpdateValue } = this; + const doNew = { + 'onUpdate:value': onUpdateValue, + }; + return ( + <> +
+ +
+
{value} star
+ + ); + }, +}); diff --git a/devui/rate/demo/customize/index.tsx b/devui/rate/demo/customize/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2e44d3161c28d4651b11dfece5fde68abcab715d --- /dev/null +++ b/devui/rate/demo/customize/index.tsx @@ -0,0 +1,40 @@ +import { defineComponent, ref } from 'vue'; +import DRate from '../../rate'; + +export default defineComponent({ + name: 'BasicRate', + components: { + DRate, + }, + props: {}, + setup() { + const value = ref(3); + const onUpdateValue = (newVal: number) => { + value.value = newVal; + }; + return { + value, + onUpdateValue, + }; + }, + render() { + const { value, onUpdateValue } = this; + const doNew = { + 'onUpdate:value': onUpdateValue, + }; + return ( + <> +
+ +
+
{value} A
+ + ); + }, +}); diff --git a/devui/rate/demo/only-read/index.tsx b/devui/rate/demo/only-read/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..354704ff17b6f0cee6696c1dce7458a0653d4733 --- /dev/null +++ b/devui/rate/demo/only-read/index.tsx @@ -0,0 +1,24 @@ +import { defineComponent, ref } from 'vue'; +import DRate from '../../rate'; + +export default defineComponent({ + name: 'OnlyRead', + components: { + DRate, + }, + props: {}, + setup() { + const value = ref(3.5); + return { + value, + }; + }, + render() { + const { value } = this; + return ( +
+ +
+ ); + }, +}); diff --git a/devui/rate/demo/rate-demo.tsx b/devui/rate/demo/rate-demo.tsx index a735c81a2851199233e1ef84146a4ae5b16466d1..6461b839bd06eeffbc326e74d0651e8b2164130c 100644 --- a/devui/rate/demo/rate-demo.tsx +++ b/devui/rate/demo/rate-demo.tsx @@ -1,12 +1,42 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; +import { useDemo } from 'hooks/use-demo'; +import OnlyRead from './only-read/index'; +import OnlyReadCode from './only-read/index?raw'; +import BasicRate from './basic/index'; +import BasicRateCode from './basic/index?raw'; +import CustomizeRate from './customize/index'; +import CustomizeRateCode from './customize/index?raw'; +import TypeRate from './type/index'; +import TypeRateCode from './type/index?raw'; export default defineComponent({ - name: 'd-rate-demo', - props: { + name: 'DRateDemo', + render() { + return useDemo([ + { + id: 'only-read', + title: '只读模式', + code: OnlyReadCode, + content: , + }, + { + id: 'basic-rate', + title: '动态模式', + code: BasicRateCode, + content: , + }, + { + id: 'customize-rate', + title: '动态模式-自定义', + code: CustomizeRateCode, + content: , + }, + { + id: 'type-rate', + title: '使用type参数', + code: TypeRateCode, + content: , + }, + ]); }, - setup(props, ctx) { - return () => { - return
devui-rate-demo
- } - } -}) \ No newline at end of file +}); diff --git a/devui/rate/demo/type/index.tsx b/devui/rate/demo/type/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e67c1e7724a0b07c4f885d8b57bc4a71d7381081 --- /dev/null +++ b/devui/rate/demo/type/index.tsx @@ -0,0 +1,36 @@ +import { defineComponent, ref } from 'vue'; +import DRate from '../../rate'; + +export default defineComponent({ + name: 'BasicRate', + components: { + DRate, + }, + props: {}, + setup() { + const value1 = ref(5); + const value2 = ref(3); + const value3 = ref(2); + return { + value1, + value2, + value3, + }; + }, + render() { + const { value1, value2, value3 } = this; + return ( + <> +
+ +
+
+ +
+
+ +
+ + ); + }, +}); diff --git a/devui/rate/doc/api-cn.md b/devui/rate/doc/api-cn.md index 5a4e97330499586e33c8e637f9b27e1806a7c66a..b54491e900441f961c7a79555e80bd5bd11fb273 100644 --- a/devui/rate/doc/api-cn.md +++ b/devui/rate/doc/api-cn.md @@ -1,22 +1,26 @@ # 如何使用 -在module中引入: + +在 module 中引入: + ```ts -import { RateModule } from 'ng-devui/rate'; +import { DRate } from "vue-devui"; ``` 在页面中使用: + ```html - + ``` + # Rate ## d-rate 参数 -| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | -| :-------: | :-----------------------------: | :---: | :------------------------------------------------------- | ------------------------------------------------------ | -| read | `boolean` | false | 可选,设置是否为只读模式,只读模式无法交互 | [只读模式](demo#read-only-mode) | -| count | `number` | 5 | 可选,设置总等级数 | [只读模式](demo#read-only-mode) | -| type | `'success'\|'warning'\|'error'` | -- | 可选,设置当前评分的类型,不同类型对应不同颜色 | [使用type参数](demo#using-the-type-parameter) | -| color | `string` | -- | 可选,星星颜色 | [动态模式-自定义](demo#dynamic-mode-Custom) | -| icon | `string` | -- | 可选,评分图标的样式,只支持 devUI 图标库中所有图标 | [动态模式](demo#dynamic-mode) | -| character | `string` | -- | 可选,评分图标的样式,icon 与 character 只能设置其中一个 | [动态模式-自定义](demo#dynamic-mode-Custom) | +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | +| :-------: | :-----------------------------: | :----: | :------------------------------------------------------- | ----------------------------------------------- | +| read | `boolean` | false | 可选,设置是否为只读模式,只读模式无法交互 | [只读模式](demo#read-only-mode) | +| count | `number` | 5 | 可选,设置总等级数 | [只读模式](demo#read-only-mode) | +| type | `'success'\|'warning'\|'error'` | -- | 可选,设置当前评分的类型,不同类型对应不同颜色 | [使用 type 参数](demo#using-the-type-parameter) | +| color | `string` | -- | 可选,星星颜色 | [动态模式-自定义](demo#dynamic-mode-Custom) | +| icon | `string` | -- | 可选,评分图标的样式,只支持 devUI 图标库中所有图标 | [动态模式](demo#dynamic-mode) | +| character | `string` | -- | 可选,评分图标的样式,icon 与 character 只能设置其中一个 | [动态模式-自定义](demo#dynamic-mode-Custom) | diff --git a/devui/rate/doc/api-en.md b/devui/rate/doc/api-en.md index 75b4451488eb4dcaac861e0080e8ec1ef6057dc7..6904c6b32a378803f78c8ae8e6af44345d4c8e2a 100644 --- a/devui/rate/doc/api-en.md +++ b/devui/rate/doc/api-en.md @@ -1,22 +1,26 @@ # How to use + Import into module: + ```ts -import { RateModule } from 'ng-devui/rate'; +import { DRate } from "vue-devui"; ``` In the page: + ```html - + ``` + # Rate ## d-rate parameter -| Parameter | Type | Default | Description | Jump to Demo | -| :-------: | :-----------------------------: | :---: | :------------------------------------------------------- | ------------------------------------------------------ | -| read | `boolean` | false | Optional. This parameter specifies whether to enable read-only mode. In read-only mode, interaction is not supported. | [Read-only Mode](demo#read-only-mode) | -| count | `number` | 5 | Optional. Sets the total number of levels. | [Read-only Mode](demo#read-only-mode) | -| type | `'success'\|'warning'\|'error'` | -- | Optional. Set the current rating type. Different types correspond to different colors. | [Use the type parameter](demo#using-the-type-parameter) | -| color | `string` | -- | Optional. Star color. | [Dynamic Mode-Custom](demo#dynamic-mode-Custom) | -| icon | `string` | -- | Optional. Style of the rating icon. Only all icons in the DevUI icon library are supported. | [Dynamic Mode](demo#dynamic-mode) | -| character | `string` | -- | Optional. Scoring icon style. Only one of icon and character can be set. | [Dynamic Mode-Custom](demo#dynamic-mode-Custom) | +| Parameter | Type | Default | Description | Jump to Demo | +| :-------: | :-----------------------------: | :-----: | :-------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| read | `boolean` | false | Optional. This parameter specifies whether to enable read-only mode. In read-only mode, interaction is not supported. | [Read-only Mode](demo#read-only-mode) | +| count | `number` | 5 | Optional. Sets the total number of levels. | [Read-only Mode](demo#read-only-mode) | +| type | `'success'\|'warning'\|'error'` | -- | Optional. Set the current rating type. Different types correspond to different colors. | [Use the type parameter](demo#using-the-type-parameter) | +| color | `string` | -- | Optional. Star color. | [Dynamic Mode-Custom](demo#dynamic-mode-Custom) | +| icon | `string` | -- | Optional. Style of the rating icon. Only all icons in the DevUI icon library are supported. | [Dynamic Mode](demo#dynamic-mode) | +| character | `string` | -- | Optional. Scoring icon style. Only one of icon and character can be set. | [Dynamic Mode-Custom](demo#dynamic-mode-Custom) | diff --git a/devui/rate/rate.scss b/devui/rate/rate.scss new file mode 100644 index 0000000000000000000000000000000000000000..2e35ff0575510a3efc142e6169b8fe25173ca906 --- /dev/null +++ b/devui/rate/rate.scss @@ -0,0 +1,70 @@ +@import '../style/theme/color'; +@import '../style/core/_font'; + +.devui-star-align { + font-size: $devui-font-size-icon; + margin-right: 5px; + position: relative; + line-height: 1; +} + +.devui-pointer { + cursor: pointer; +} + +.devui-star-container { + display: inline-flex; +} + +.devui-star-color-active { + color: #6a81ed; + line-height: 1.5; + + svg g { + fill: #6a81ed; + } +} + +.devui-star-color-success { + color: #3dcca6; + + svg g { + fill: #3dcca6; + } +} + +.devui-star-color-warning { + color: #fac20a; + + svg g { + fill: #fac20a; + } +} + +.devui-star-color-error { + color: #f66f6a; + + svg g { + fill: #f66f6a; + } +} + +.devui-active-star { + position: absolute; + top: 0; + left: 0; + overflow: hidden; +} + +.devui-star-color { + color: $devui-dividing-line; + line-height: 1.5; + + svg g { + fill: $devui-dividing-line; + } +} + +.devui-only-read { + cursor: not-allowed; +} diff --git a/devui/rate/rate.tsx b/devui/rate/rate.tsx index 33a175e38f39d5cf163b03b141797c723d93b0bb..85ceaafd2a905f8bae407dbe295805218cf15e56 100644 --- a/devui/rate/rate.tsx +++ b/devui/rate/rate.tsx @@ -1,12 +1,161 @@ -import { defineComponent } from 'vue' +import { defineComponent, onMounted, watch, reactive, ref } from 'vue'; +import { rateProps } from './use-rate'; +import './rate.scss'; export default defineComponent({ - name: 'd-rate', - props: { - }, + name: 'DRate', + props: rateProps, + emits: ['change', 'update:value'], setup(props, ctx) { - return () => { - return
devui-rate
- } - } -}) \ No newline at end of file + const totalLevelArray = reactive[]>([]); + const chooseValue = ref(0); + + // 根据mouseMove,mouseLeave,select等操作,改变颜色与是否选中 + const setChange = (start: number, end: number, width: string) => { + for (let i = start; i < end; i++) { + totalLevelArray[i]['width'] = width; + } + }; + + // 初始化设置 + const initRating = () => { + if (!props.value) { + return; + } + chooseValue.value = props.value - 1; + const halfStar = chooseValue.value % 1; + const intCurrentLevel = Math.floor(chooseValue.value); + setChange(0, intCurrentLevel + 1, '100%'); + if (halfStar > 0) { + totalLevelArray[intCurrentLevel + 1]['width'] = halfStar * 100 + '%'; + setChange(intCurrentLevel + 2, props.count, '0'); + } else { + setChange(intCurrentLevel + 1, props.count, '0'); + } + }; + + onMounted(() => { + for (let i = 0; i < props.count; i++) { + totalLevelArray.push({ width: '0' }); + } + initRating(); + }); + + const hoverToggle = (_, index: number, reset = false) => { + if (props.read) { + return; + } + if (reset) { + if (chooseValue.value >= 0) { + setChange(0, chooseValue.value + 1, '100%'); + setChange(chooseValue.value + 1, props.count, '0'); + } else { + setChange(0, props.count, '0'); + } + } else { + setChange(0, index + 1, '100%'); + setChange(index + 1, props.count, '0'); + } + }; + + const selectValue = (index: number) => { + if (props.read) { + return; + } + setChange(0, index + 1, '100%'); + setChange(index + 1, props.count, '0'); + chooseValue.value = index; + props.onChange && props.onChange(index + 1); + props.onTouched && props.onTouched(); + ctx.emit('update:value', index + 1); + }; + return { + totalLevelArray, + chooseValue, + hoverToggle, + selectValue, + }; + }, + render() { + const { + totalLevelArray, + chooseValue, + icon, + character, + read, + type, + color, + hoverToggle, + selectValue, + } = this; + return ( +
hoverToggle(e, chooseValue, true)} + > + {totalLevelArray.map((item, index) => ( +
hoverToggle(e, index)} + onClick={() => selectValue(index)} + > + + {character} + {!icon && !character && ( + + + + + + + + )} + + + {character} + {!icon && !character && ( + + + + + + + + )} + +
+ ))} +
+ ); + }, +}); diff --git a/devui/rate/use-rate.ts b/devui/rate/use-rate.ts new file mode 100644 index 0000000000000000000000000000000000000000..8adf7317a88b884c41a272af8b2a4d52281679ad --- /dev/null +++ b/devui/rate/use-rate.ts @@ -0,0 +1,39 @@ +import { PropType } from 'vue'; + +export const rateProps = { + value: { + type: Number, + }, + read: { + type: Boolean, + default: false, + }, + count: { + type: Number, + default: 5, + }, + type: { + type: String as PropType<'success' | 'warning' | 'error'>, + default: '', + }, + color: { + type: String, + default: '', + }, + icon: { + type: String, + default: '', + }, + character: { + type: String, + default: '', + }, + onChange: { + type: Function as PropType<(value: number) => void>, + default: undefined, + }, + onTouched: { + type: Function as PropType<() => void>, + default: undefined, + }, +};