fix(web-antdv-next): sync shared UI fixes

pull/355/head
XuZhiqiang 2026-06-04 16:20:42 +08:00
parent 09970d89a4
commit f6a8c6e652
10 changed files with 63 additions and 21 deletions

View File

@ -72,6 +72,7 @@ import {
Checkbox as CheckboxComponent, Checkbox as CheckboxComponent,
CheckboxGroup as CheckboxGroupComponent, CheckboxGroup as CheckboxGroupComponent,
DatePicker as DatePickerComponent, DatePicker as DatePickerComponent,
DateRangePicker as RangePickerComponent,
Divider as DividerComponent, Divider as DividerComponent,
Image as ImageComponent, Image as ImageComponent,
ImagePreviewGroup, ImagePreviewGroup,
@ -84,7 +85,6 @@ import {
notification, notification,
Radio as RadioComponent, Radio as RadioComponent,
RadioGroup as RadioGroupComponent, RadioGroup as RadioGroupComponent,
DateRangePicker as RangePickerComponent,
Rate as RateComponent, Rate as RateComponent,
Select as SelectComponent, Select as SelectComponent,
Space as SpaceComponent, Space as SpaceComponent,
@ -279,9 +279,9 @@ async function previewImage(
{ {
class: 'hidden', class: 'hidden',
preview: { preview: {
open: visible.value, visible: visible.value,
current: currentIndex, current: currentIndex,
onOpenChange: (value: boolean) => { onVisibleChange: (value: boolean) => {
visible.value = value; visible.value = value;
if (!value) { if (!value) {
setTimeout(() => { setTimeout(() => {
@ -366,7 +366,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
closable: false, closable: false,
cancelText: $t('common.cancel'), cancelText: $t('common.cancel'),
okText: $t('ui.crop.confirm'), okText: $t('ui.crop.confirm'),
destroyOnHidden: true, destroyOnClose: true,
onOk: async () => { onOk: async () => {
const cropper = cropperRef.value; const cropper = cropperRef.value;
if (!cropper) { if (!cropper) {
@ -625,7 +625,6 @@ export type ComponentType =
| 'Space' | 'Space'
| 'Switch' | 'Switch'
| 'TextArea' | 'TextArea'
| 'TextArea'
| 'TimePicker' | 'TimePicker'
| 'TimeRangePicker' | 'TimeRangePicker'
| 'TreeSelect' | 'TreeSelect'
@ -676,13 +675,13 @@ async function initComponentAdapter() {
fieldNames: { label: 'label', value: 'value', children: 'children' }, fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
visibleEvent: 'onOpenChange', visibleEvent: 'onVisibleChange',
}), }),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: Select, component: Select,
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
visibleEvent: 'onOpenChange', visibleEvent: 'onVisibleChange',
}), }),
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: TreeSelect, component: TreeSelect,
@ -690,7 +689,7 @@ async function initComponentAdapter() {
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'treeData', optionsPropName: 'treeData',
visibleEvent: 'onOpenChange', visibleEvent: 'onVisibleChange',
}), }),
AutoComplete, AutoComplete,
Cascader, Cascader,
@ -744,7 +743,7 @@ async function initComponentAdapter() {
copyPreferencesSuccess: (title, content) => { copyPreferencesSuccess: (title, content) => {
notification.success({ notification.success({
description: content, description: content,
title, message: title,
placement: 'bottomRight', placement: 'bottomRight',
}); });
}, },

View File

@ -65,5 +65,6 @@ const useVbenForm = useForm<ComponentType, ComponentPropsMap>;
export { initSetupVbenForm, useVbenForm, z }; export { initSetupVbenForm, useVbenForm, z };
export type VbenFormApi = ReturnType<typeof useVbenForm>[1]; // add by 芋艿:用于 data.ts 表单 schema 内调用 setFieldValue
export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>; export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>;
export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>; export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>;

View File

@ -21,7 +21,7 @@ export function useAreaSelectRule() {
title: label, title: label,
info: '', info: '',
$required: false, $required: false,
modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value modelField: 'value', // Ant Design Vue 组件使用 value;web-ele 自定义组件使用默认 modelValue
}; };
}, },
props(_: any, { t }: any) { props(_: any, { t }: any) {

View File

@ -39,7 +39,7 @@ export function useDictSelectRule() {
title: label, title: label,
info: '', info: '',
$required: false, $required: false,
modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value modelField: 'value', // Ant Design Vue 组件使用 value;web-ele 自定义组件使用默认 modelValue
}; };
}, },
props(_: any, { t }: any) { props(_: any, { t }: any) {

View File

@ -21,7 +21,7 @@ export function useIframeRule() {
title: label, title: label,
info: '', info: '',
$required: false, $required: false,
modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value modelField: 'value', // Ant Design Vue 组件使用 value;web-ele 自定义组件使用默认 modelValue
}; };
}, },
props(_: any, { t }: any) { props(_: any, { t }: any) {

View File

@ -3,7 +3,8 @@ import type { Dayjs } from 'dayjs';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { Radio, RadioGroup } from 'antdv-next'; import { DatePicker, Radio, RadioGroup } from 'antdv-next';
import dayjs from 'dayjs';
import { getRangePickerDefaultProps } from '#/utils/rangePickerProps'; import { getRangePickerDefaultProps } from '#/utils/rangePickerProps';
@ -19,8 +20,20 @@ const times = ref<[Dayjs, Dayjs]>(); // 日期范围
const rangePickerProps = getRangePickerDefaultProps(); const rangePickerProps = getRangePickerDefaultProps();
const timeRangeOptions = [ const timeRangeOptions = [
rangePickerProps.presets[3]!, // 昨天 rangePickerProps.presets[3]!, // 昨天
rangePickerProps.presets[1]!, // 最近 7 天 {
rangePickerProps.presets[2]!, // 最近 30 天 label: rangePickerProps.presets[1]!.label,
value: [
dayjs().subtract(7, 'day').startOf('day'),
dayjs().subtract(1, 'day').endOf('day'),
],
},
{
label: rangePickerProps.presets[2]!.label,
value: [
dayjs().subtract(30, 'day').startOf('day'),
dayjs().subtract(1, 'day').endOf('day'),
],
},
]; ];
const timeRangeType = ref(timeRangeOptions[1]!.label); // 默认选中第一个选项 const timeRangeType = ref(timeRangeOptions[1]!.label); // 默认选中第一个选项
@ -75,7 +88,7 @@ onMounted(() => {
{{ option.label }} {{ option.label }}
</Radio> </Radio>
</RadioGroup> </RadioGroup>
<DateRangePicker <DatePicker.RangePicker
v-model:value="times" v-model:value="times"
:format="rangePickerProps.format" :format="rangePickerProps.format"
:value-format="rangePickerProps.valueFormat" :value-format="rangePickerProps.valueFormat"

View File

@ -1,5 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { UploadFile, UploadProps } from 'antdv-next'; import type { UploadFile, UploadProps } from 'antdv-next';
import type { UploadRequestOption } from 'antdv-next/lib/vc-upload/interface';
import type { FileUploadProps } from './typing'; import type { FileUploadProps } from './typing';
@ -16,8 +17,6 @@ import { Button, message, Upload } from 'antdv-next';
import { UploadResultStatus } from './typing'; import { UploadResultStatus } from './typing';
import { useUpload, useUploadType } from './use-upload'; import { useUpload, useUploadType } from './use-upload';
type UploadRequestOption = any;
defineOptions({ name: 'FileUpload', inheritAttrs: false }); defineOptions({ name: 'FileUpload', inheritAttrs: false });
const props = withDefaults(defineProps<FileUploadProps>(), { const props = withDefaults(defineProps<FileUploadProps>(), {
@ -33,6 +32,7 @@ const props = withDefaults(defineProps<FileUploadProps>(), {
multiple: false, multiple: false,
api: undefined, api: undefined,
resultField: '', resultField: '',
returnText: false,
showDescription: false, showDescription: false,
}); });
const emit = defineEmits([ const emit = defineEmits([
@ -148,9 +148,6 @@ function handleUploadError(error: any) {
* @returns 是否允许上传 * @returns 是否允许上传
*/ */
async function beforeUpload(file: File) { async function beforeUpload(file: File) {
const fileContent = await file.text();
emit('returnText', fileContent);
// 检查文件数量限制 // 检查文件数量限制
if (fileList.value!.length >= props.maxNumber) { if (fileList.value!.length >= props.maxNumber) {
message.error($t('ui.upload.maxNumber', [props.maxNumber])); message.error($t('ui.upload.maxNumber', [props.maxNumber]));
@ -177,6 +174,10 @@ async function beforeUpload(file: File) {
// 只有在验证通过后才增加计数器 // 只有在验证通过后才增加计数器
uploadNumber.value++; uploadNumber.value++;
if (props.returnText) {
const fileContent = await file.text();
emit('returnText', fileContent);
}
return true; return true;
} }

View File

@ -58,6 +58,7 @@ const textareaProps = computed(() => {
const fileUploadProps = computed(() => { const fileUploadProps = computed(() => {
return { return {
...props.fileUploadProps, ...props.fileUploadProps,
returnText: true,
}; };
}); });
</script> </script>

View File

@ -27,6 +27,7 @@ export interface FileUploadProps {
maxSize?: number; // 文件最大多少MB maxSize?: number; // 文件最大多少MB
multiple?: boolean; // 是否支持多选 multiple?: boolean; // 是否支持多选
resultField?: string; // support xxx.xxx.xx resultField?: string; // support xxx.xxx.xx
returnText?: boolean; // 是否返回文件文本内容
showDescription?: boolean; // 是否显示下面的描述 showDescription?: boolean; // 是否显示下面的描述
value?: string | string[]; value?: string | string[];
} }

View File

@ -202,6 +202,31 @@ onMounted(() => {
); );
}); });
const handleClick = (item: NotificationItem) => {
// 如果通知项有链接,点击时跳转
if (item.link) {
navigateTo(item.link, item.query, item.state);
}
};
function navigateTo(
link: string,
query?: Record<string, any>,
state?: Record<string, any>,
) {
if (link.startsWith('http://') || link.startsWith('https://')) {
// 外部链接,在新标签页打开
window.open(link, '_blank');
} else {
// 内部路由链接,支持 query 参数和 state
router.push({
path: link,
query: query || {},
state,
});
}
}
watch( watch(
() => ({ () => ({
enable: preferences.app.watermark, enable: preferences.app.watermark,
@ -264,6 +289,7 @@ watch(
@view-all="handleNotificationViewAll" @view-all="handleNotificationViewAll"
@open="handleNotificationOpen" @open="handleNotificationOpen"
@read="handleNotificationRead" @read="handleNotificationRead"
@on-click="handleClick"
/> />
</template> </template>
<template #header-right-1> <template #header-right-1>