diff --git a/code/base-project/base-vue/packages/ao-design/src/components.ts b/code/base-project/base-vue/packages/ao-design/src/components.ts index 6a4f8fd5..a798e396 100644 --- a/code/base-project/base-vue/packages/ao-design/src/components.ts +++ b/code/base-project/base-vue/packages/ao-design/src/components.ts @@ -3,3 +3,4 @@ export { default as Button } from './button' export { default as Icon } from './icon' export { default as Input } from './input' export { default as Spin } from './spin' +export { default as Textarea } from './textarea' diff --git a/code/base-project/base-vue/packages/ao-design/src/icon/index.tsx b/code/base-project/base-vue/packages/ao-design/src/icon/index.tsx index b7299371..13ef76f3 100644 --- a/code/base-project/base-vue/packages/ao-design/src/icon/index.tsx +++ b/code/base-project/base-vue/packages/ao-design/src/icon/index.tsx @@ -6,27 +6,16 @@ import './index.scss' export default defineComponent({ name: 'AIcon', - inheritAttrs: false, props: { icon: { type: String as PropType, required: true }, size: { type: Number, default: 16 }, color: { type: String, default: 'currentColor' }, spin: { type: Boolean, default: false }, rotate: { type: Number, default: 360 }, - onClick: Function as PropType<(e: MouseEvent) => void>, // 明确 MouseEvent 类型 }, - setup(props, { attrs }) { + setup(props) { const prefixCls = getPrefixCls('icon') - // 安全调用 onClick - const handleClick = (e: MouseEvent) => { - props.onClick?.(e) - // 如果 attrs 上也传了 onClick,做类型断言 - if (attrs.onClick) { - (attrs.onClick as (e: MouseEvent) => void)(e) - } - } - return () => ( +
+ +
+ + + + + + + + + + + +
+
+ diff --git a/code/base-project/base-vue/packages/ao-design/src/input/index.scss b/code/base-project/base-vue/packages/ao-design/src/input/index.scss index f6f620bb..b7e272eb 100644 --- a/code/base-project/base-vue/packages/ao-design/src/input/index.scss +++ b/code/base-project/base-vue/packages/ao-design/src/input/index.scss @@ -3,16 +3,81 @@ $input-prefix: #{$prefix}-input; +.#{$input-prefix}-adornment { + display: flex; + width: 100%; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + + &.#{$input-prefix}-size { + &-small { + height: 24px; + font-size: 12px; + } + + &-medium { + height: 28px; + font-size: 13px; + } + + &-large { + height: 32px; + font-size: 14px; + } + } + + .#{$input-prefix}-adornment-prepend, + .#{$input-prefix}-adornment-append { + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + + background-color: #f3f3f3; + color: rgba(0, 0, 0, 0.9); + border: 1px solid #ddd; + + span { + white-space: nowrap; + word-break: keep-all; + padding: 0 8px; + } + } + + .#{$input-prefix}-adornment-prepend { + border-right: none; + } + + .#{$input-prefix}-adornment-append { + border-left: none; + } + + .#{$input-prefix}-wrapper { + border-radius: 0px; + } + + > :first-child { + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; + } + + > :last-child { + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + } +} + .#{$input-prefix}-wrapper { display: flex; align-items: center; width: 100%; border: 1px solid #ddd; + z-index: 2; box-sizing: border-box; - border-radius: 2px; padding: 0 8px; - transition: border cubic-bezier(0.38, 0, 0.24, 1) 0.2s, box-shadow cubic-bezier(0.38, 0, 0.24, 1) 0.2s, @@ -45,23 +110,6 @@ $input-prefix: #{$prefix}-input; box-shadow: $input-focus-shadow; } - &.#{$input-prefix}-size { - &-small { - height: 24px; - font-size: 12px; - } - - &-medium { - height: 28px; - font-size: 13px; - } - - &-large { - height: 32px; - font-size: 14px; - } - } - .#{$input-prefix}-align { &-left { text-align: left; @@ -119,7 +167,6 @@ $input-prefix: #{$prefix}-input; .#{$input-prefix}-clear { cursor: pointer; transition: color 0.2s; - margin-left: 4px; &:hover { color: red !important; @@ -132,14 +179,7 @@ $input-prefix: #{$prefix}-input; white-space: nowrap; } - .#{$input-prefix}-password-toggle { - display: inline-flex; - align-items: center; - cursor: pointer; - margin-left: 4px; - - .hidden { - display: none; - } + .#{$input-prefix}-password { + cursor: pointer !important; } } diff --git a/code/base-project/base-vue/packages/ao-design/src/input/index.tsx b/code/base-project/base-vue/packages/ao-design/src/input/index.tsx index 901f2794..d8e0bda4 100644 --- a/code/base-project/base-vue/packages/ao-design/src/input/index.tsx +++ b/code/base-project/base-vue/packages/ao-design/src/input/index.tsx @@ -4,7 +4,7 @@ import { getPrefixCls } from '../_utils/getPrefixCls' import Icon from '../icon' export default defineComponent({ - name: 'AInput', + name: 'Input', props: { modelValue: String, size: { @@ -24,6 +24,8 @@ export default defineComponent({ showCount: Boolean, maxlength: Number, password: Boolean, + prepend: String, + append: String, }, emits: ['update:modelValue'], setup(props, { slots, emit }) { @@ -51,65 +53,89 @@ export default defineComponent({ return showPassword.value ? 'text' : 'password' }) - return () => ( -
- {(slots.prefix || props.prefixIcon) && ( -
- {slots.prefix?.() ?? } -
- )} + const inputWrapper = () => { + return ( +
+ {(slots.prefix || props.prefixIcon) && ( +
+ {slots.prefix?.() ?? } +
+ )} - updateValue((e.target as HTMLInputElement).value)} - /> - - {props.clearable && inputValue.value && !props.disabled && !props.readonly && ( - updateValue('')} + updateValue((e.target as HTMLInputElement).value)} /> - )} - {/* 密码切换图标 */} - {props.password && ( -
- (showPassword.value = true)} - /> - (showPassword.value = false)} - /> -
- )} + {props.clearable && inputValue.value && !props.disabled && !props.readonly && ( + updateValue('')} + > + + - {(slots.suffix || props.suffixIcon) && !props.password && ( -
- {slots.suffix?.() ?? } -
- )} + )} - {props.showCount && ( - {countText.value} - )} -
- ) + {/* 密码切换图标 */} + {props.password && ( + (showPassword.value = !showPassword.value)} + > + + + )} + + {(slots.suffix || props.suffixIcon) && !props.password && ( +
+ {slots.suffix?.() ?? } +
+ )} + + {props.showCount && ( + {countText.value} + )} +
+ ) + } + + return () => { + return ( +
+ {props.prepend || slots.prepend + ? ( +
+ {slots.prepend?.() ?? (props.prepend && {props.prepend})} +
+ ) + : null} + + {inputWrapper()} + + {props.append || slots.append + ? ( +
+ {slots.append?.() ?? (props.append && {props.append})} +
+ ) + : null} +
+ ) + } }, }) diff --git a/code/base-project/base-vue/packages/ao-design/src/textarea/index.scss b/code/base-project/base-vue/packages/ao-design/src/textarea/index.scss new file mode 100644 index 00000000..37035dbe --- /dev/null +++ b/code/base-project/base-vue/packages/ao-design/src/textarea/index.scss @@ -0,0 +1,38 @@ +@use '../_styles/theme/index' as *; +@use 'sass:color'; + +$textarea-prefix: #{$prefix}-textarea; + +.#{$textarea-prefix}-wrapper { + width: 100%; + border: 1px solid #ddd; + border-radius: 2px; + box-sizing: border-box; + position: relative; + padding: 0; + + &:hover { + border-color: $input-hover-color; + } + + &:focus-within { + border-color: $input-focus-color; + box-shadow: $input-focus-shadow; + } + + .#{$textarea-prefix}-inner { + width: 100%; + min-height: 80px; // 可根据需要 + padding: 8px; // 内边距 + border: none; // 去掉默认边框 + outline: none; + resize: vertical; + box-sizing: border-box; + font-size: 13px; + color: #000; + + &::placeholder { + color: #999999; + } + } +} diff --git a/code/base-project/base-vue/packages/ao-design/src/textarea/index.tsx b/code/base-project/base-vue/packages/ao-design/src/textarea/index.tsx new file mode 100644 index 00000000..bc0b7c1a --- /dev/null +++ b/code/base-project/base-vue/packages/ao-design/src/textarea/index.tsx @@ -0,0 +1,19 @@ +import type { PropType } from 'vue' +import { computed, defineComponent, ref } from 'vue' +import { getPrefixCls } from '../_utils/getPrefixCls' + +export default defineComponent({ + name: 'Textarea', + emits: ['update:modelValue'], + setup() { + const prefixCls = getPrefixCls('input') + + return () => { + return ( +
+