diff --git a/devui/rate/index.ts b/devui/rate/index.ts
index 7955ec32f3b63ef8f66001af625f645ecdff1d12..ec34c35859ff969cbfde374d05e068b4043f26f5 100644
--- a/devui/rate/index.ts
+++ b/devui/rate/index.ts
@@ -10,6 +10,7 @@ export { Rate }
export default {
title: 'Rate 评分',
category: '数据录入',
+ status: '已完成',
install(app: App): void {
app.use(Rate as any);
},
diff --git a/devui/rate/src/rate.tsx b/devui/rate/src/rate.tsx
index 7b8eeeb0d2f81ec745b41d8472bfeb2147206a79..d9ccd7595dfe8b3090474c5d089bd3435c11e670 100644
--- a/devui/rate/src/rate.tsx
+++ b/devui/rate/src/rate.tsx
@@ -41,7 +41,7 @@ export default defineComponent({
initRating()
})
- const hoverToggle = (_, index: number, reset = false) => {
+ const hoverToggle = (e, index: number, reset = false) => {
if (props.read) {
return
}
@@ -54,17 +54,31 @@ export default defineComponent({
}
} else {
setChange(0, index + 1, '100%')
+ // 判断是否是半选模式并且判断鼠标所在图标区域
+ if (props.allowHalf && (e.offsetX * 2 <= e.target.clientWidth)) {
+ setChange(index, index + 1, '50%')
+ } else {
+ setChange(index, index + 1, '100%')
+ }
setChange(index + 1, props.count, '0')
}
}
- const selectValue = (index: number) => {
+ const selectValue = (e, index: number) => {
if (props.read) {
return
}
- setChange(0, index + 1, '100%')
+ setChange(0, index, '100%')
+ // 判断是否是半选模式
+ if (props.allowHalf && (e.offsetX * 2 <= e.target.clientWidth)) {
+ setChange(index, index + 1, '50%')
+ chooseValue.value = index - 0.5
+ } else {
+ setChange(index, index + 1, '100%')
+ chooseValue.value = index
+ }
setChange(index + 1, props.count, '0')
- chooseValue.value = index
+ index = chooseValue.value
props.onChange && props.onChange(index + 1)
props.onTouched && props.onTouched()
ctx.emit('update:modelValue', index + 1)
@@ -86,7 +100,7 @@ export default defineComponent({
type,
color,
hoverToggle,
- selectValue,
+ selectValue
} = this
return (
{totalLevelArray.map((item, index) => (
hoverToggle(e, index)}
- onClick={() => selectValue(index)}
+ onClick={(e) => selectValue(e, index)}
>
{icon && !character && (
diff --git a/devui/rate/src/use-rate.ts b/devui/rate/src/use-rate.ts
index c62c7a1ca6f58dc2bfba1d554827b1e23065c035..d5ced884beff9551ea942b7760666c1d1ae27a0c 100644
--- a/devui/rate/src/use-rate.ts
+++ b/devui/rate/src/use-rate.ts
@@ -29,6 +29,10 @@ export const rateProps = {
type: String,
default: '',
},
+ allowHalf: {
+ type: Boolean,
+ default: false,
+ },
onChange: {
type: Function as PropType<(value: number) => void>,
default: undefined,
diff --git a/devui/tag-input/src/tag-input.tsx b/devui/tag-input/src/tag-input.tsx
index 8ed491cbe549f9e6518decf9d53e49d6fa5abcd4..70d35d826f05d9fbfc73d9b00b3645d1053c3077 100644
--- a/devui/tag-input/src/tag-input.tsx
+++ b/devui/tag-input/src/tag-input.tsx
@@ -20,13 +20,21 @@ const tagInputProps = {
type: String,
default: ''
},
+ minLength: {
+ type: Number,
+ default: 3
+ },
+ maxLength: {
+ type: Number,
+ default: Number.MAX_SAFE_INTEGER
+ },
maxTags: {
type: Number,
default: Number.MAX_SAFE_INTEGER
},
maxTagsText: {
type: String,
- default: ''
+ default: '已达到最大个数:'
},
spellcheck: {
type: Boolean,
@@ -40,6 +48,10 @@ const tagInputProps = {
type: Boolean,
default: false
},
+ isAddBySpace: {
+ type: Boolean,
+ default: true
+ },
disabledText: {
type: String,
default: ''
@@ -125,6 +137,8 @@ export default defineComponent({
};
const handleEnter = () => {
let res = { [props.displayProperty]: tagInputVal.value };
+ // 判断输入框和输入建议是否为空
+ if (tagInputVal.value === '' && mergedSuggestions.value.length === 0) return false
if (mergedSuggestions.value.length) {
const target = mergedSuggestions.value[selectIndex.value];
res = target;
@@ -215,7 +229,8 @@ export default defineComponent({
isShowSuggestion,
noData,
mergedSuggestions,
- selectIndex
+ selectIndex,
+ maxTags
} = this;
const inputBoxCls = {
@@ -268,10 +283,10 @@ export default defineComponent({
onFocus={onInputFocus}
onBlur={onInputBlur}
onInput={($event: any) => onInput($event)}
- placeholder={placeholder}
+ placeholder={isTagsLimit ? `${maxTagsText} ${maxTags}` : placeholder}
spellcheck={spellcheck}
disabled={isTagsLimit}
- title={isTagsLimit ? maxTagsText : ''} />
+ />
{
!isShowSuggestion ? '' : (
diff --git a/docs/.vitepress/devui-theme/components/Page.vue b/docs/.vitepress/devui-theme/components/Page.vue
deleted file mode 100644
index 7a1d422bc5f308dce065b5a95b762aaf2bc57357..0000000000000000000000000000000000000000
--- a/docs/.vitepress/devui-theme/components/Page.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vitepress/devui-theme/composables/useToc.ts b/docs/.vitepress/devui-theme/composables/useToc.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ffb2689db24acecd70f1ef5e872f25561e128d11
--- /dev/null
+++ b/docs/.vitepress/devui-theme/composables/useToc.ts
@@ -0,0 +1,57 @@
+import { computed } from 'vue'
+import { useData } from 'vitepress'
+import { joinUrl } from '../utils'
+
+import type { PageData } from 'vitepress'
+
+type EnhanceArrayElement
= T extends Array ? (U & P)[] : never
+
+type Headers = EnhanceArrayElement<
+ PageData['headers'],
+ {
+ children?: Headers
+ }
+>
+
+export const useToc = () => {
+ const { page } = useData()
+
+ return computed(() => resolveHeaders(page.value.headers))
+}
+
+export const resolveLink = (base: string, path: string) => {
+ if (path === undefined) {
+ return path
+ }
+ // keep relative hash to the same page
+ if (path.startsWith('#')) {
+ return path
+ }
+ return joinUrl(base, path)
+}
+
+export const resolveHeaders = (headers: PageData['headers']) => {
+ return mapHeaders(groupHeaders(headers))
+}
+
+export function groupHeaders(headers: PageData['headers']) {
+ headers = headers.map((h) => Object.assign({}, h))
+ let lastH2
+
+ headers.forEach((h) => {
+ if (h.level === 3) {
+ lastH2 = h
+ } else if (lastH2) {
+ ;(lastH2.children || (lastH2.children = [])).push(h)
+ }
+ })
+ return headers.filter((h) => h.level === 3)
+}
+
+export function mapHeaders(headers: Headers) {
+ return headers.map((header) => ({
+ text: header.title,
+ link: `#${header.slug}`,
+ children: header.children ? mapHeaders(header.children) : undefined,
+ }))
+}
diff --git a/docs/components/rate/index.md b/docs/components/rate/index.md
index ab3f6ff327c98decec3c700d2f4852d2a0b4a74c..16540d0b9249a2b750bf1b5bfe13ed7d4b2b1e86 100644
--- a/docs/components/rate/index.md
+++ b/docs/components/rate/index.md
@@ -74,6 +74,33 @@ export default {
}
```
+:::
+
+### 半选模式
+
+:::demo
+
+```vue
+
+
+ {{ value }}
+
+
+```
:::
@@ -137,3 +164,10 @@ d-rate 参数
| color | `string` | -- | 可选,星星颜色 | [动态模式-自定义](#动态模式-自定义) |
| icon | `string` | -- | 可选,评分图标的样式,只支持 devUI 图标库中所有图标 | [动态模式](#动态模式) |
| character | `string` | -- | 可选,评分图标的样式,icon 与 character 只能设置其中一个 | [动态模式-自定义](#动态模式-自定义) |
+| allowHalf | `boolean` | false | 可选,动态模式下是否允许半选 | [半选模式](#半选模式) |
+
+d-rate 事件
+
+| 参数 | 类型 | 说明 | 回调参数 | 跳转 Demo |
+| --------------- | -------------------- | ----------------------------- | ----------------------------- | --------------------- |
+| change | `EventEmitter` | 分值改变时触发 | 改变后的分值 | [半选模式](#半选模式) |
diff --git a/docs/components/tag-input/index.md b/docs/components/tag-input/index.md
index 80bd047cb149732bdff969239b4df514a74174a6..82dc0ab4c8b2fc3613548817b4ec7f442359a0cc 100644
--- a/docs/components/tag-input/index.md
+++ b/docs/components/tag-input/index.md
@@ -9,20 +9,23 @@
### 基本用法
+v-model:tags="state.tags"
+v-model:suggestionList="state.suggestionList"
+display-property="name"
+no-data="暂无数据"
+:maxTags="4"
+placeholder="请输入名字"
+
+>
```html
```
@@ -37,8 +40,30 @@ export default defineComponent({
})
return {
- state,
+ state
}
}
})
-
\ No newline at end of file
+
+
+### d-tag-input 参数
+
+| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 |
+| :-------------: | :-------: | :---------------------: | :----------------------------------: | :-------------------- | ---------- |
+| tags | `Array` | [] | 必选,记录输入的标签和选择的标签列表 | [基本用法](#基本用法) |
+| suggestionList | `Array` | [] | 可选,下拉选项,默认可选择的标签列表 | [基本用法](#基本用法) |
+| displayProperty | `string` | 'name' | 可选,列表项使用的属性名 | [基本用法](#基本用法) |
+| placeholder | `boolean` | '' | 可选,输入框的 placeholder | [基本用法](#基本用法) |
+| noData | `boolean` | '' | 可选,无数据提示 | [基本用法](#基本用法) |
+| maxTags | `number` | Number.MAX_SAFE_INTEGER | 可选,可输入标签的最大个数 | [基本用法](#基本用法) |
+| caseSensitivity | `boolean` | false | 可选,大小写敏感,默认忽略大小写 | | |
+| spellcheck | `boolean` | true | 可选,input 输入框是否开启拼写检查的 | | |
+| isAddBySpace | `boolean` | true | 可选,是否支持空格键输入标签 | | |
+| disabled | `boolean` | false | 可选,disabled 灰化状态 | |
+| showAnimation | `boolean` | true | 可选,是否开启动画 | | ✔ |
+
+### d-tags-input 事件
+
+| 事件 | 类型 | 说明 | 跳转 Demo |
+| :---------: | :-----------------: | :------------------------------------------------------- | --------------------- |
+| valueChange | `EventEmitter` | 当选中某个选项项后,将会调用此函数,参数为当前选择项的值 | [基本用法](#基本用法) |
diff --git a/docs/index.md b/docs/index.md
index bc713836d6560a8cccaa2a18322dd0775414b1d6..f6f46f1cc13da44436fff756e6f2be11f7a4b2c5 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -32,12 +32,47 @@ yarn add vue-devui
main.ts
```js
+// 全局引入
import DevUI from 'vue-devui'
import 'vue-devui/style.css'
createApp(App).use(DevUI).mount('#app')
```
+```js
+// 按需引入
+// main.ts文件
+import { createApp } from 'vue'
+import App from './App.vue'
+
+// Step 1: 引入单个组件
+import { Button } from 'vue-devui'
+// or import Button from 'vue-devui/button'
+// Step 2: 引入组件样式
+// 方式一:手动引入组件样式
+import 'vue-devui/button/style.css'
+
+// 方式二:自动按需引入组件
+// vite.config.ts文件
+// import styleImport from 'vite-plugin-style-import'
+// plugins: [
+// vue(),
+// styleImport({
+// libs: [
+// {
+// libraryName: 'vue-devui',
+// esModule: true,
+// resolveStyle: (name) => `vue-devui/${name}/style`,
+// },
+// ],
+// })
+// ]
+
+createApp(App)
+.use(Button) // Step 3: 使用组件
+.mount('#app')
+```
+
### 4. 启动开发调试
```shell