style: 调整

This commit is contained in:
rd
2025-08-21 16:47:34 +08:00
parent cb9b0715b1
commit ba4878c333
3 changed files with 45 additions and 35 deletions

View File

@ -10,7 +10,7 @@ import type { BubbleProps, BubbleContentType, SlotInfoType } from './types';
export default defineComponent({ export default defineComponent({
name: 'Bubble', name: 'Bubble',
inheritAttrs: false, inheritAttrs: false,
props: {} as any, props: {},
setup(_, { attrs, slots, expose }) { setup(_, { attrs, slots, expose }) {
const props = attrs as unknown as BubbleProps<BubbleContentType> & { style?: any; class?: any }; const props = attrs as unknown as BubbleProps<BubbleContentType> & { style?: any; class?: any };
@ -18,7 +18,7 @@ export default defineComponent({
watch( watch(
() => props.content, () => props.content,
(val) => { (val) => {
content.value = val as any; content.value = val;
}, },
{ immediate: true }, { immediate: true },
); );
@ -27,13 +27,7 @@ export default defineComponent({
const [typingEnabled, typingStep, typingInterval, typingSuffix] = useTypingConfig(() => props.typing); const [typingEnabled, typingStep, typingInterval, typingSuffix] = useTypingConfig(() => props.typing);
const abortRef = ref(false); const abortRef = ref(false);
const [typedContent, isTyping] = useTypedEffect( const [typedContent, isTyping] = useTypedEffect(content, typingEnabled, typingStep, typingInterval, abortRef);
content as any,
typingEnabled,
typingStep,
typingInterval,
abortRef,
);
// 提供中止打字的能力关闭typing并立即展示完整内容 // 提供中止打字的能力关闭typing并立即展示完整内容
const abortTyping = () => { const abortTyping = () => {
@ -73,10 +67,8 @@ export default defineComponent({
}); });
const mergedContent = computed(() => { const mergedContent = computed(() => {
if (slots.message) return slots.message({ content: typedContent.value as any }) as any; if (slots.message) return slots.message({ content: typedContent.value });
return props.messageRender return props.messageRender ? props.messageRender(typedContent.value) : typedContent.value;
? (props.messageRender(typedContent.value as any) as any)
: (typedContent.value as any);
}); });
const contentNode = computed(() => { const contentNode = computed(() => {
@ -89,7 +81,7 @@ export default defineComponent({
return ( return (
<> <>
{mergedContent.value as any} {mergedContent.value}
{isTyping.value && unref(typingSuffix)} {isTyping.value && unref(typingSuffix)}
</> </>
); );
@ -97,16 +89,16 @@ export default defineComponent({
const renderHeader = () => { const renderHeader = () => {
const info: SlotInfoType = { key: props._key }; const info: SlotInfoType = { key: props._key };
if (slots.header) return slots.header({ content: typedContent.value as any, info, item: props }) as any; if (slots.header) return slots.header({ content: typedContent.value, info, item: props });
const h = props.header; const h = props.header;
return typeof h === 'function' ? h({ content: typedContent.value as any, info, item: props }) : h; return typeof h === 'function' ? h({ content: typedContent.value, info, item: props }) : h;
}; };
const renderFooter = () => { const renderFooter = () => {
const info: SlotInfoType = { key: props._key }; const info: SlotInfoType = { key: props._key };
if (slots.footer) return slots.footer({ content: typedContent.value as any, info, item: props }) as any; if (slots.footer) return slots.footer({ content: typedContent.value, info, item: props });
const f = props.footer; const f = props.footer;
return typeof f === 'function' ? f({ content: typedContent.value as any, info, item: props }) : f; return typeof f === 'function' ? f({ content: typedContent.value, info, item: props }) : f;
}; };
expose({ expose({
@ -117,7 +109,7 @@ export default defineComponent({
<div class={mergedCls.value} style={{ ...(props.style || {}) }}> <div class={mergedCls.value} style={{ ...(props.style || {}) }}>
{(slots.avatar || props.avatar) && ( {(slots.avatar || props.avatar) && (
<div class={[`${prefixCls}-avatar`, props.classNames?.avatar]} style={props.styles?.avatar}> <div class={[`${prefixCls}-avatar`, props.classNames?.avatar]} style={props.styles?.avatar}>
{avatarNode.value as any} {avatarNode.value}
</div> </div>
)} )}
@ -135,7 +127,7 @@ export default defineComponent({
{renderHeader()} {renderHeader()}
</div> </div>
) : null} ) : null}
{contentNode.value as any} {contentNode.value}
{renderFooter() ? ( {renderFooter() ? (
<div class={[`${prefixCls}-footer`, props.classNames?.footer]} style={props.styles?.footer}> <div class={[`${prefixCls}-footer`, props.classNames?.footer]} style={props.styles?.footer}>
{renderFooter()} {renderFooter()}

View File

@ -23,14 +23,14 @@ import {
export default defineComponent({ export default defineComponent({
name: 'BubbleList', name: 'BubbleList',
inheritAttrs: false, inheritAttrs: false,
props: {} as any, props: {},
setup(_, { attrs, slots, expose }) { setup(_, { attrs, slots, expose }) {
const props = attrs as unknown as BubbleListProps & { class?: any; style?: any }; const props = attrs as unknown as BubbleListProps & { class?: any; style?: any };
const passThroughAttrs = useAttrs(); const passThroughAttrs = useAttrs();
const TOLERANCE = 1; const TOLERANCE = 1;
const domProps = computed(() => pickAttrs(mergeProps(props as any, passThroughAttrs)) as any); const domProps = computed(() => pickAttrs(mergeProps(props as any, passThroughAttrs)));
const items = ref(props.items); const items = ref(props.items);
const roles = ref(props.roles as RolesType); const roles = ref(props.roles as RolesType);
@ -108,7 +108,7 @@ export default defineComponent({
}; };
// 对外暴露能力 // 对外暴露能力
expose({ expose({
nativeElement: listRef as any, nativeElement: listRef,
abortTypingByKey, abortTypingByKey,
scrollTo: (info: any) => { scrollTo: (info: any) => {
unref(listRef)?.scrollTo?.(info); unref(listRef)?.scrollTo?.(info);
@ -125,20 +125,18 @@ export default defineComponent({
props.class, props.class,
{ [`${listPrefixCls}-reach-end`]: unref(scrollReachEnd) }, { [`${listPrefixCls}-reach-end`]: unref(scrollReachEnd) },
]} ]}
style={props.style as any} style={props.style}
ref={listRef} ref={listRef}
onScroll={onInternalScroll} onScroll={onInternalScroll}
> >
{unref(displayData).map(({ key, onTypingComplete: onTypingCompleteBubble, ...bubble }: any) => ( {unref(displayData).map(({ key, onTypingComplete: onTypingCompleteBubble, ...bubble }) => (
<Bubble <Bubble
{...bubble} {...bubble}
avatar={slots.avatar ? () => slots.avatar?.({ item: { key, ...bubble } }) : (bubble as any).avatar} avatar={slots.avatar ? () => slots.avatar?.({ item: { key, ...bubble } }) : bubble.avatar}
header={slots.header?.({ item: { key, ...bubble } }) ?? (bubble as any).header} header={slots.header?.({ item: { key, ...bubble } }) ?? bubble.header}
footer={slots.footer?.({ item: { key, ...bubble } }) ?? (bubble as any).footer} footer={slots.footer?.({ item: { key, ...bubble } }) ?? bubble.footer}
loadingRender={ loadingRender={slots.loading ? () => slots.loading({ item: { key, ...bubble } }) : bubble.loadingRender}
slots.loading ? () => slots.loading({ item: { key, ...bubble } }) : (bubble as any).loadingRender content={slots.message?.({ item: { key, ...bubble } }) ?? bubble.content}
}
content={slots.message?.({ item: { key, ...bubble } }) ?? (bubble as any).content}
key={key} key={key}
ref={(node: any) => { ref={(node: any) => {
if (node) { if (node) {
@ -147,7 +145,7 @@ export default defineComponent({
delete bubbleRefs.value[key]; delete bubbleRefs.value[key];
} }
}} }}
typing={unref(initialized) ? (bubble as any).typing : false} typing={unref(initialized) ? bubble.typing : false}
onTypingComplete={() => { onTypingComplete={() => {
onTypingCompleteBubble?.(); onTypingCompleteBubble?.();
onTypingComplete(key); onTypingComplete(key);

View File

@ -4,6 +4,7 @@ import { Bubble } from '@/components/xt-chat/xt-bubble';
import { downloadByUrl } from '@/utils/tools'; import { downloadByUrl } from '@/utils/tools';
import markdownit from 'markdown-it'; import markdownit from 'markdown-it';
import { message } from 'ant-design-vue';
export default { export default {
emits: ['close'], emits: ['close'],
@ -29,6 +30,13 @@ export default {
const onDownload = () => { const onDownload = () => {
// downloadByUrl(''); // downloadByUrl('');
message.success('下载成功!');
};
const onAddMediaCenter = () => {
message.success('成功添加至“素材中心”模块。');
};
const onAddTaskManage = () => {
message.success('成功添加至“任务管理”模块。');
}; };
const abortTyping = () => { const abortTyping = () => {
bubbleRef.value?.abortTyping?.(); bubbleRef.value?.abortTyping?.();
@ -36,10 +44,22 @@ export default {
const renderHeader = () => { const renderHeader = () => {
return ( return (
<header class="header flex justify-end items-center mb-16px px-32px"> <header class="header flex justify-end items-center mb-16px px-32px">
<Button type="outline" size="medium" class="mr-16px" v-slots={{ icon: () => <icon-plus size="14" /> }}> <Button
type="outline"
size="medium"
class="mr-16px"
v-slots={{ icon: () => <icon-plus size="14" /> }}
onClick={onAddMediaCenter}
>
素材中心 素材中心
</Button> </Button>
<Button type="outline" size="medium" class="mr-16px" v-slots={{ icon: () => <icon-plus size="14" /> }}> <Button
type="outline"
size="medium"
class="mr-16px"
v-slots={{ icon: () => <icon-plus size="14" /> }}
onClick={onAddTaskManage}
>
任务管理 任务管理
</Button> </Button>
<Button <Button